diff options
| author | Justin Bronn <jbronn@gmail.com> | 2007-09-20 13:02:11 +0000 |
|---|---|---|
| committer | Justin Bronn <jbronn@gmail.com> | 2007-09-20 13:02:11 +0000 |
| commit | 7376474260a967e7ad88ee5bf554b4a28e3e7feb (patch) | |
| tree | 735479f07bbe7cde8385b44ff76552afc9c2bffc | |
| parent | 69452d623794bc9ef160c33c5e9b02180ca4848d (diff) | |
gis: Merged revisions 6021-6393 via svnmerge from [repos:django/trunk trunk].
git-svn-id: http://code.djangoproject.com/svn/django/branches/gis@6394 bcc190cf-cafb-0310-a4f2-bffc1f526a37
305 files changed, 31858 insertions, 15314 deletions
@@ -49,6 +49,7 @@ answer newbie questions, and generally made Django that much better: andy@jadedplanet.net Fabrice Aneche <akh@nobugware.com> ant9000@netwise.it + Florian Apolloner David Ascher <http://ascher.ca/> david@kazserve.org Arthur <avandorp@gmail.com> @@ -75,16 +76,20 @@ answer newbie questions, and generally made Django that much better: Chris Chamberlin <dja@cdc.msbx.net> Amit Chakradeo <http://amit.chakradeo.net/> ChaosKCW + Sengtha Chay <sengtha@e-khmer.com> ivan.chelubeev@gmail.com Bryan Chow <bryan at verdjn dot com> Michal Chruszcz <troll@pld-linux.org> Ian Clelland <clelland@gmail.com> + Russell Cloran <russell@rucus.net> colin@owlfish.com crankycoder@gmail.com + Paul Collier <paul@paul-collier.com> Pete Crosier <pete.crosier@gmail.com> Matt Croydon <http://www.postneo.com/> flavio.curella@gmail.com Jure Cuhalev <gandalf@owca.info> + John D'Agostino <john.dagostino@gmail.com> dackze+django@gmail.com David Danier <goliath.mailinglist@gmx.de> Dirk Datzert <dummy@habmalnefrage.de> @@ -111,18 +116,22 @@ answer newbie questions, and generally made Django that much better: Ludvig Ericson <ludvig.ericson@gmail.com> Dirk Eschler <dirk.eschler@gmx.net> Marc Fargas <telenieko@telenieko.com> + Szilveszter Farkas <szilveszter.farkas@gmail.com> favo@exoweb.net Bill Fenner <fenner@gmail.com> Stefane Fermgier <sf@fermigier.com> Afonso Fernández Nogueira <fonzzo.django@gmail.com> Matthew Flanagan <http://wadofstuff.blogspot.com> Eric Floehr <eric@intellovations.com> + Vincent Foley <vfoleybourgon@yahoo.ca> Jorge Gajon <gajon@gajon.org> gandalf@owca.info Marc Garcia <marc.garcia@accopensys.com> Baishampayan Ghose + Dimitris Glezos <dimitris@glezos.com> glin@seznam.cz martin.glueck@gmail.com + Artyom Gnilov <boobsd@gmail.com> GomoX <gomo@datafull.com> Mario Gonzalez <gonzalemario@gmail.com> pradeep.gowda@gmail.com @@ -144,6 +153,7 @@ answer newbie questions, and generally made Django that much better: Sung-Jin Hong <serialx.net@gmail.com> Richard House <Richard.House@i-logue.com> Robert Rock Howard <http://djangomojo.com/> + Rob Hudson <http://rob.cogit8.org/> Jason Huggins <http://www.jrandolph.com/blog/> Hyun Mi Ae Tom Insam @@ -155,6 +165,7 @@ answer newbie questions, and generally made Django that much better: jpellerin@gmail.com junzhang.jn@gmail.com Antti Kaihola <http://akaihola.blogspot.com/> + Nagy Károly <charlie@rendszergazda.com> Ben Dean Kawamura <ben.dean.kawamura@gmail.com> Ian G. Kelly <ian.g.kelly@gmail.com> Ben Khoo <khoobks@westnet.com.au> @@ -176,6 +187,7 @@ answer newbie questions, and generally made Django that much better: lakin.wecker@gmail.com Nick Lane <nick.lane.au@gmail.com> Stuart Langridge <http://www.kryogenix.org/> + Paul Lanier <planier@google.com> Nicola Larosa <nico@teknico.net> Eugene Lazutkin <http://lazutkin.com/blog/> Jeong-Min Lee <falsetru@gmail.com> @@ -185,10 +197,12 @@ answer newbie questions, and generally made Django that much better: Waylan Limberg <waylan@gmail.com> limodou Philip Lindborg <philip.lindborg@gmail.com> + msaelices <msaelices@gmail.com> Matt McClanahan <http://mmcc.cx/> Martin Maney <http://www.chipy.org/Martin_Maney> masonsimon+django@gmail.com Manuzhai + Petr Marhoun <petr.marhoun@gmail.com> Petar Marić <http://www.petarmaric.com/> Nuno Mariz <nmariz@gmail.com> Marijn Vriens <marijn@metronomo.cl> @@ -226,22 +240,28 @@ answer newbie questions, and generally made Django that much better: phil@produxion.net phil.h.smith@gmail.com Gustavo Picon + pigletto Luke Plant <http://lukeplant.me.uk/> plisk Daniel Poelzleithner <http://poelzi.org/> polpak@yahoo.com Jyrki Pulliainen <jyrki.pulliainen@gmail.com> Johann Queuniet <johann.queuniet@adh.naellia.eu> - J. Rademaker + Jan Rademaker Michael Radziej <mir@noris.de> + Amit Ramon <amit.ramon@gmail.com> + Philippe Raoult <philippe.raoult@n2nsoft.com> Massimiliano Ravelli <massimiliano.ravelli@gmail.com> Brian Ray <http://brianray.chipy.org/> remco@diji.biz rhettg@gmail.com + Matt Riggott Henrique Romano <onaiort@gmail.com> Armin Ronacher Brian Rosner <brosner@gmail.com> Oliver Rutherfurd <http://rutherfurd.net/> + ryankanno + Manuel Saelices <msaelices@yaco.es> Ivan Sagalaev (Maniac) <http://www.softwaremaniacs.org/> Vinay Sajip <vinay_sajip@yahoo.co.uk> David Schein @@ -252,22 +272,30 @@ answer newbie questions, and generally made Django that much better: Jozko Skrablin <jozko.skrablin@gmail.com> SmileyChris <smileychris@gmail.com> smurf@smurf.noris.de + Vsevolod Solovyov sopel + Leo Soto <leo.soto@gmail.com> Wiliam Alves de Souza <wiliamsouza83@gmail.com> + Don Spaulding <donspauldingii@gmail.com> + Bjørn Stabell <bjorn@exoweb.net> Georgi Stanojevski <glisha@gmail.com> Vasiliy Stavenko <stavenko@gmail.com> Thomas Steinacher <http://www.eggdrop.ch/> nowell strite + Thomas Stromberg <tstromberg@google.com> Sundance SuperJared Radek Švarz <http://www.svarz.cz/translate/> Swaroop C H <http://www.swaroopch.info> Aaron Swartz <http://www.aaronsw.com/> Ville Säävuori <http://www.unessa.net/> + Tyler Tarabula <tyler.tarabula@gmail.com> Tyson Tate <tyson@fallingbullets.com> Frank Tegtmeyer <fte@fte.to> thebjorn <bp@datakortet.no> Zach Thompson <zthompson47@gmail.com> + Michael Thornhill + Deepak Thukral <deep.thukral@gmail.com> tibimicu@gmax.net tobias@neuyork.de Tom Tobin @@ -280,10 +308,12 @@ answer newbie questions, and generally made Django that much better: Amit Upadhyay Geert Vanderkelen viestards.lists@gmail.com + George Vilches <gav@thataddress.com> Vlado <vlado@labath.org> Milton Waddams wam-djangobug@wamber.net wangchun <yaohua2000@gmail.com> + Filip Wasilewski <filip.wasilewski@gmail.com> Dan Watson <http://theidioteque.net/> Chris Wesseling <Chris.Wesseling@cwi.nl> James Wheare <django@sparemint.com> diff --git a/django/bin/compile-messages.py b/django/bin/compile-messages.py index 2e1e908bbf..2838cb8aa4 100755 --- a/django/bin/compile-messages.py +++ b/django/bin/compile-messages.py @@ -4,20 +4,31 @@ import optparse import os import sys +try: + set +except NameError: + from sets import Set as set # For Python 2.3 + + def compile_messages(locale=None): - basedir = None + basedirs = [os.path.join('conf', 'locale'), 'locale'] + if os.environ.get('DJANGO_SETTINGS_MODULE'): + from django.conf import settings + basedirs += settings.LOCALE_PATHS + + # Gather existing directories. + basedirs = set(map(os.path.abspath, filter(os.path.isdir, basedirs))) - if os.path.isdir(os.path.join('conf', 'locale')): - basedir = os.path.abspath(os.path.join('conf', 'locale')) - elif os.path.isdir('locale'): - basedir = os.path.abspath('locale') - else: - print "This script should be run from the Django SVN tree or your project or app tree." + if not basedirs: + print "This script should be run from the Django SVN tree or your project or app tree, or with the settings module specified." sys.exit(1) - if locale is not None: - basedir = os.path.join(basedir, locale, 'LC_MESSAGES') + for basedir in basedirs: + if locale: + basedir = os.path.join(basedir, locale, 'LC_MESSAGES') + compile_messages_in_dir(basedir) +def compile_messages_in_dir(basedir): for dirpath, dirnames, filenames in os.walk(basedir): for f in filenames: if f.endswith('.po'): @@ -40,9 +51,13 @@ def main(): parser = optparse.OptionParser() parser.add_option('-l', '--locale', dest='locale', help="The locale to process. Default is to process all.") + parser.add_option('--settings', + help='Python path to settings module, e.g. "myproject.settings". If provided, all LOCALE_PATHS will be processed. If this isn\'t provided, the DJANGO_SETTINGS_MODULE environment variable will be checked as well.') options, args = parser.parse_args() if len(args): parser.error("This program takes no arguments") + if options.settings: + os.environ['DJANGO_SETTINGS_MODULE'] = options.settings compile_messages(options.locale) if __name__ == "__main__": diff --git a/django/conf/__init__.py b/django/conf/__init__.py index f28da2d764..f19e509ea3 100644 --- a/django/conf/__init__.py +++ b/django/conf/__init__.py @@ -112,6 +112,7 @@ class Settings(object): # Move the time zone info into os.environ. See ticket #2315 for why # we don't do this unconditionally (breaks Windows). os.environ['TZ'] = self.TIME_ZONE + time.tzset() def get_all_members(self): return dir(self) diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py index e11ea7531b..b3cbf095c3 100644 --- a/django/conf/global_settings.py +++ b/django/conf/global_settings.py @@ -51,6 +51,7 @@ LANGUAGES = ( ('fa', gettext_noop('Persian')), ('fi', gettext_noop('Finnish')), ('fr', gettext_noop('French')), + ('ga', gettext_noop('Gaeilge')), ('gl', gettext_noop('Galician')), ('hu', gettext_noop('Hungarian')), ('he', gettext_noop('Hebrew')), @@ -59,6 +60,7 @@ LANGUAGES = ( ('it', gettext_noop('Italian')), ('ja', gettext_noop('Japanese')), ('ko', gettext_noop('Korean')), + ('km', gettext_noop('Khmer')), ('kn', gettext_noop('Kannada')), ('lv', gettext_noop('Latvian')), ('mk', gettext_noop('Macedonian')), @@ -269,12 +271,14 @@ MIDDLEWARE_CLASSES = ( # SESSIONS # ############ -SESSION_COOKIE_NAME = 'sessionid' # Cookie name. This can be whatever you want. -SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2 # Age of cookie, in seconds (default: 2 weeks). -SESSION_COOKIE_DOMAIN = None # A string like ".lawrence.com", or None for standard domain cookie. -SESSION_COOKIE_SECURE = False # Whether the session cookie should be secure (https:// only). -SESSION_SAVE_EVERY_REQUEST = False # Whether to save the session data on every request. -SESSION_EXPIRE_AT_BROWSER_CLOSE = False # Whether sessions expire when a user closes his browser. +SESSION_COOKIE_NAME = 'sessionid' # Cookie name. This can be whatever you want. +SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2 # Age of cookie, in seconds (default: 2 weeks). +SESSION_COOKIE_DOMAIN = None # A string like ".lawrence.com", or None for standard domain cookie. +SESSION_COOKIE_SECURE = False # Whether the session cookie should be secure (https:// only). +SESSION_SAVE_EVERY_REQUEST = False # Whether to save the session data on every request. +SESSION_EXPIRE_AT_BROWSER_CLOSE = False # Whether sessions expire when a user closes his browser. +SESSION_ENGINE = 'django.contrib.sessions.backends.db' # The module to store session data +SESSION_FILE_PATH = '/tmp/' # Directory to store session files if using the file session module ######### # CACHE # diff --git a/django/conf/locale/ca/LC_MESSAGES/django.mo b/django/conf/locale/ca/LC_MESSAGES/django.mo Binary files differindex 82cd1bee4b..28bc60a758 100644 --- a/django/conf/locale/ca/LC_MESSAGES/django.mo +++ b/django/conf/locale/ca/LC_MESSAGES/django.mo diff --git a/django/conf/locale/ca/LC_MESSAGES/django.po b/django/conf/locale/ca/LC_MESSAGES/django.po index 451c60e2db..fe2836ff89 100644 --- a/django/conf/locale/ca/LC_MESSAGES/django.po +++ b/django/conf/locale/ca/LC_MESSAGES/django.po @@ -5,147 +5,99 @@ msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-06-25 17:31+0200\n" -"PO-Revision-Date: 2007-06-25 17:47+0200\n" -"Last-Translator: Marc Fargas <telenieko@telenieko.com>\n" +"POT-Creation-Date: 2007-09-14 12:38+0200\n" +"PO-Revision-Date: 2007-09-14 14:21+0100\n" +"Last-Translator: Marc Garcia <marc.garcia@accopensys.com>\n" "Language-Team: <es@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: template/defaultfilters.py:491 -msgid "yes,no,maybe" -msgstr "si,no,potser" - -#: template/defaultfilters.py:520 -#, python-format -msgid "%(size)d byte" -msgid_plural "%(size)d bytes" -msgstr[0] "%(size)d byte" -msgstr[1] "%(size)d bytes" - -#: template/defaultfilters.py:522 +#: db/models/manipulators.py:309 #, python-format -msgid "%.1f KB" -msgstr "%.1f KB" - -#: template/defaultfilters.py:524 -#, python-format -msgid "%.1f MB" -msgstr "%.1f MB" - -#: template/defaultfilters.py:525 -#, python-format -msgid "%.1f GB" -msgstr "%.1f GB" - -#: newforms/models.py:172 newforms/fields.py:432 -msgid "Select a valid choice. That choice is not one of the available choices." -msgstr "" -"Esculli una opció vàlida; Aquesta opció no és una de les opcions disponibles." - -#: newforms/models.py:185 newforms/fields.py:87 newforms/fields.py:444 -#: newforms/fields.py:522 newforms/fields.py:533 oldforms/__init__.py:357 -#: db/models/fields/__init__.py:126 db/models/fields/__init__.py:283 -#: db/models/fields/__init__.py:680 db/models/fields/__init__.py:691 -msgid "This field is required." -msgstr "Aquest camp és obligatori." - -#: newforms/models.py:189 newforms/fields.py:448 newforms/fields.py:526 -msgid "Enter a list of values." -msgstr "Introdueixi una llista de valors." - -#: newforms/models.py:195 newforms/fields.py:457 -#, python-format -msgid "Select a valid choice. %s is not one of the available choices." -msgstr "Esculli una opció vàlida; %s' no és una de les opcions vàlides." - -#: newforms/widgets.py:181 contrib/admin/filterspecs.py:150 -#: oldforms/__init__.py:577 -msgid "Unknown" -msgstr "Desconegut" - -#: newforms/widgets.py:181 contrib/admin/filterspecs.py:143 -#: oldforms/__init__.py:577 -msgid "Yes" -msgstr "Si" - -#: newforms/widgets.py:181 contrib/admin/filterspecs.py:143 -#: oldforms/__init__.py:577 -msgid "No" -msgstr "No" +msgid "%(object)s with this %(type)s already exists for the given %(field)s." +msgstr "Ja existeix un %(object)s del tipus %(type)s amb aquest %(field)s." -#: newforms/fields.py:110 newforms/fields.py:324 -#, python-format -msgid "Ensure this value has at most %d characters." -msgstr "Asseguris de que el seu texte té com a màxim %d caracters." +#: db/models/manipulators.py:310 +#: core/validators.py:283 +#: contrib/admin/views/main.py:342 +#: contrib/admin/views/main.py:344 +#: contrib/admin/views/main.py:346 +msgid "and" +msgstr "i" -#: newforms/fields.py:112 newforms/fields.py:326 +#: db/models/fields/related.py:55 #, python-format -msgid "Ensure this value has at least %d characters." -msgstr "Asseguris de que el seu texte té almenys %d caracters." +msgid "Please enter a valid %s." +msgstr "Si us plau, introdueixi un %s vàlid." -#: newforms/fields.py:135 core/validators.py:121 -msgid "Enter a whole number." -msgstr "Introdueixi un número sencer." +#: db/models/fields/related.py:658 +msgid "Separate multiple IDs with commas." +msgstr "Separi múltiples IDs amb comes." -#: newforms/fields.py:137 newforms/fields.py:160 newforms/fields.py:192 -#, python-format -msgid "Ensure this value is less than or equal to %s." -msgstr "Aquest valor ha de ser menor o igual a %s." +#: db/models/fields/related.py:660 +msgid "Hold down \"Control\", or \"Command\" on a Mac, to select more than one." +msgstr "Premi \"Control\" o \"Command\" en un Mac per escollir més d'un." -#: newforms/fields.py:139 newforms/fields.py:162 newforms/fields.py:194 +#: db/models/fields/related.py:707 #, python-format -msgid "Ensure this value is greater than or equal to %s." -msgstr "Asseguris de que aquest valor sigui superior o igual a %s." - -#: newforms/fields.py:158 newforms/fields.py:186 -msgid "Enter a number." -msgstr "Introdueixi un número." +msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid." +msgid_plural "Please enter valid %(self)s IDs. The values %(value)r are invalid." +msgstr[0] "Si us plau, introdueixi els IDs de %(self)s vàlids. El valor %(value)r és invàlid." +msgstr[1] "Si us plau, introdueixi IDs de %(self)s vàlids. Els valors %(value)r són invàlids." -#: newforms/fields.py:196 +#: db/models/fields/__init__.py:52 #, python-format -msgid "Ensure that there are no more than %s digits in total." -msgstr "Asseguris de que no hi ha més de %s dígits en total." +msgid "%(optname)s with this %(fieldname)s already exists." +msgstr "Ja existeix %(optname)s amb auqest %(fieldname)s." -#: newforms/fields.py:198 -#, python-format -msgid "Ensure that there are no more than %s decimal places." -msgstr "Asseguris de que no hi ha més de %s decimals." +#: db/models/fields/__init__.py:159 +#: db/models/fields/__init__.py:316 +#: db/models/fields/__init__.py:724 +#: db/models/fields/__init__.py:735 +#: oldforms/__init__.py:373 +#: newforms/fields.py:93 +#: newforms/fields.py:509 +#: newforms/fields.py:585 +#: newforms/fields.py:596 +#: newforms/models.py:193 +msgid "This field is required." +msgstr "Aquest camp és obligatori." -#: newforms/fields.py:200 -#, python-format -msgid "Ensure that there are no more than %s digits before the decimal point." -msgstr "Asseguris de que no hia ha més de %s dígits decimals." +#: db/models/fields/__init__.py:414 +msgid "This value must be an integer." +msgstr "Aquest valor ha de ser un enter." -#: newforms/fields.py:233 newforms/fields.py:566 -msgid "Enter a valid date." -msgstr "Introdueixi una data vàlida." +#: db/models/fields/__init__.py:449 +msgid "This value must be either True or False." +msgstr "Aquest valor ha de ser True (Veritat) o False (Fals)" -#: newforms/fields.py:260 newforms/fields.py:568 -msgid "Enter a valid time." -msgstr "Introdueixi una hora vàlida." +#: db/models/fields/__init__.py:470 +msgid "This field cannot be null." +msgstr "Aquest camp no pot ser null (estar buit)." -#: newforms/fields.py:296 -msgid "Enter a valid date/time." -msgstr "Introdueixi una data/hora vàlides." +#: db/models/fields/__init__.py:504 +#: core/validators.py:156 +msgid "Enter a valid date in YYYY-MM-DD format." +msgstr "Introdueixi una data vàlida en el forma AAAA-MM-DD." -#: newforms/fields.py:310 -msgid "Enter a valid value." -msgstr "Introdueixi un valor vàlid." +#: db/models/fields/__init__.py:573 +#: core/validators.py:165 +msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format." +msgstr "Introdueixi un data/hora vàlida en format YYYY-MM-DD HH:MM." -#: newforms/fields.py:339 core/validators.py:163 -msgid "Enter a valid e-mail address." -msgstr "Introdueixi una adreça de correu vàlida." +#: db/models/fields/__init__.py:634 +msgid "This value must be a decimal number." +msgstr "Aquest valor ha de ser un número decimal." -#: newforms/fields.py:357 newforms/fields.py:379 -msgid "Enter a valid URL." -msgstr "Introdueixi una URL vàlida." +#: db/models/fields/__init__.py:744 +msgid "Enter a valid filename." +msgstr "Introdueixi un nom de fitxer vàlid." -#: newforms/fields.py:381 -msgid "This URL appears to be a broken link." -msgstr "Aquesta URL sembla ser un enllaç trencat." +#: db/models/fields/__init__.py:887 +msgid "This value must be either None, True or False." +msgstr "Aquest valor ha de ser None (Cap), True (Veritat) o False (Fals)" #: conf/global_settings.py:39 msgid "Arabic" @@ -220,461 +172,572 @@ msgid "Hebrew" msgstr "Hebreu" #: conf/global_settings.py:57 +msgid "Croatian" +msgstr "Croat" + +#: conf/global_settings.py:58 msgid "Icelandic" msgstr "Islandès" -#: conf/global_settings.py:58 +#: conf/global_settings.py:59 msgid "Italian" msgstr "Italià" -#: conf/global_settings.py:59 +#: conf/global_settings.py:60 msgid "Japanese" msgstr "Japonès" -#: conf/global_settings.py:60 +#: conf/global_settings.py:61 msgid "Korean" msgstr "Coreà" -#: conf/global_settings.py:61 +#: conf/global_settings.py:62 +msgid "Khmer" +msgstr "Khmer" + +#: conf/global_settings.py:63 msgid "Kannada" msgstr "Canès" -#: conf/global_settings.py:62 +#: conf/global_settings.py:64 msgid "Latvian" msgstr "Letó" -#: conf/global_settings.py:63 +#: conf/global_settings.py:65 msgid "Macedonian" msgstr "Macedoni" -#: conf/global_settings.py:64 +#: conf/global_settings.py:66 msgid "Dutch" msgstr "Holandès" -#: conf/global_settings.py:65 +#: conf/global_settings.py:67 msgid "Norwegian" msgstr "Norueg" -#: conf/global_settings.py:66 +#: conf/global_settings.py:68 msgid "Polish" msgstr "Polac" -#: conf/global_settings.py:67 +#: conf/global_settings.py:69 msgid "Portugese" msgstr "Portuguès" -#: conf/global_settings.py:68 +#: conf/global_settings.py:70 msgid "Brazilian" msgstr "Brasileny" -#: conf/global_settings.py:69 +#: conf/global_settings.py:71 msgid "Romanian" msgstr "Rumanès" -#: conf/global_settings.py:70 +#: conf/global_settings.py:72 msgid "Russian" msgstr "Rús" -#: conf/global_settings.py:71 +#: conf/global_settings.py:73 msgid "Slovak" msgstr "Eslovac" -#: conf/global_settings.py:72 +#: conf/global_settings.py:74 msgid "Slovenian" msgstr "Esloveni" -#: conf/global_settings.py:73 +#: conf/global_settings.py:75 msgid "Serbian" msgstr "Serbi" -#: conf/global_settings.py:74 +#: conf/global_settings.py:76 msgid "Swedish" msgstr "Suec" -#: conf/global_settings.py:75 +#: conf/global_settings.py:77 msgid "Tamil" msgstr "Tàmil" -#: conf/global_settings.py:76 +#: conf/global_settings.py:78 msgid "Telugu" msgstr "Telugu" -#: conf/global_settings.py:77 +#: conf/global_settings.py:79 msgid "Turkish" msgstr "Turc" -#: conf/global_settings.py:78 +#: conf/global_settings.py:80 msgid "Ukrainian" msgstr "Ucranià" -#: conf/global_settings.py:79 +#: conf/global_settings.py:81 msgid "Simplified Chinese" msgstr "Xinés simplificat" -#: conf/global_settings.py:80 +#: conf/global_settings.py:82 msgid "Traditional Chinese" msgstr "Xinés tradicional" -#: contrib/comments/models.py:67 contrib/comments/models.py:166 -msgid "object ID" -msgstr "ID de l'objecte" +#: core/validators.py:72 +msgid "This value must contain only letters, numbers and underscores." +msgstr "Aquest valor ha de contenir només números, guions, i guions baixos." -#: contrib/comments/models.py:68 -msgid "headline" -msgstr "encapçalament" +#: core/validators.py:76 +msgid "This value must contain only letters, numbers, underscores, dashes or slashes." +msgstr "Aquest valor ha de contenir només lletres, números, guions, guions baixos, i barres (/)." -#: contrib/comments/models.py:69 contrib/comments/models.py:90 -#: contrib/comments/models.py:167 -msgid "comment" -msgstr "comentari" +#: core/validators.py:80 +msgid "This value must contain only letters, numbers, underscores or hyphens." +msgstr "Aquest valor ha de contenir només lletres, números, guions o guions baixos" -#: contrib/comments/models.py:70 -msgid "rating #1" -msgstr "qualificació #1" +#: core/validators.py:84 +msgid "Uppercase letters are not allowed here." +msgstr "No es permeten majúscules aquí." -#: contrib/comments/models.py:71 -msgid "rating #2" -msgstr "qualificació #2" +#: core/validators.py:88 +msgid "Lowercase letters are not allowed here." +msgstr "No es permeten minúscules aquí." -#: contrib/comments/models.py:72 -msgid "rating #3" -msgstr "qualificació #3" +#: core/validators.py:95 +msgid "Enter only digits separated by commas." +msgstr "Introdueixi només dígits separats per comes." -#: contrib/comments/models.py:73 -msgid "rating #4" -msgstr "qualificació #4" +#: core/validators.py:107 +msgid "Enter valid e-mail addresses separated by commas." +msgstr "Introdueixi adreces de correu electrònic vàlides separades per comes." -#: contrib/comments/models.py:74 -msgid "rating #5" -msgstr "qualificació #5" +#: core/validators.py:111 +msgid "Please enter a valid IP address." +msgstr "Per favor introdueixi una adreça IP vàlida." -#: contrib/comments/models.py:75 -msgid "rating #6" -msgstr "qualificació #6" +#: core/validators.py:115 +msgid "Empty values are not allowed here." +msgstr "No s'admeten valor buits." -#: contrib/comments/models.py:76 -msgid "rating #7" -msgstr "qualificació #7" +#: core/validators.py:119 +msgid "Non-numeric characters aren't allowed here." +msgstr "No s'admeten caracters no numèrics." -#: contrib/comments/models.py:77 -msgid "rating #8" -msgstr "qualificació #8" +#: core/validators.py:123 +msgid "This value can't be comprised solely of digits." +msgstr "Aquest valor no pot contenir només dígits." -#: contrib/comments/models.py:82 -msgid "is valid rating" -msgstr "és qualificació vàlida" +#: core/validators.py:128 +#: newforms/fields.py:149 +msgid "Enter a whole number." +msgstr "Introdueixi un número sencer." -#: contrib/comments/models.py:83 contrib/comments/models.py:169 -msgid "date/time submitted" -msgstr "data/hora d'enviament" +#: core/validators.py:132 +msgid "Only alphabetical characters are allowed here." +msgstr "Només s'admeted caracters alfabètics aquí." -#: contrib/comments/models.py:84 contrib/comments/models.py:170 -msgid "is public" -msgstr "és públic" +#: core/validators.py:147 +msgid "Year must be 1900 or later." +msgstr "L'any ha de ser posterior al 1900" -#: contrib/comments/models.py:85 contrib/admin/views/doc.py:305 -msgid "IP address" -msgstr "Adreça IP" +#: core/validators.py:151 +#, python-format +msgid "Invalid date: %s" +msgstr "Data invàlida: %s" -#: contrib/comments/models.py:86 -msgid "is removed" -msgstr "està eliminat" +#: core/validators.py:161 +msgid "Enter a valid time in HH:MM format." +msgstr "Introdueixi una hora vàlida en el format HH:MM." -#: contrib/comments/models.py:86 -msgid "" -"Check this box if the comment is inappropriate. A \"This comment has been " -"removed\" message will be displayed instead." -msgstr "" -"Marqui aquesta caixa si el comentari no és apropiat. En lloc seu es mostrarà " -"\"Aquest comentari ha estat eliminat\" " +#: core/validators.py:170 +#: newforms/fields.py:343 +msgid "Enter a valid e-mail address." +msgstr "Introdueixi una adreça de correu vàlida." -#: contrib/comments/models.py:91 -msgid "comments" -msgstr "comentaris" +#: core/validators.py:182 +#: core/validators.py:469 +#: oldforms/__init__.py:686 +#: newforms/fields.py:377 +msgid "No file was submitted. Check the encoding type on the form." +msgstr "No s'ha enviat cap fitxer. Comprovi el tipus de codificació del formulari." -#: contrib/comments/models.py:131 contrib/comments/models.py:207 -msgid "Content object" -msgstr "Objecte Contingut" +#: core/validators.py:193 +#: newforms/fields.py:405 +msgid "Upload a valid image. The file you uploaded was either not an image or a corrupted image." +msgstr "Envii una imatge vàilda. El fitxer que ha enviat no era una imatge o estaba corrupte." -#: contrib/comments/models.py:159 +#: core/validators.py:200 +#, python-format +msgid "The URL %s does not point to a valid image." +msgstr "La URL %s no apunta una imatge vàlida." + +#: core/validators.py:204 +#, python-format +msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid." +msgstr "El números de telèfon han de guardar-se en el format XXX-XXX-XXXX. \"%s\" no és vàlid." + +#: core/validators.py:212 +#, python-format +msgid "The URL %s does not point to a valid QuickTime video." +msgstr "La URL %s no apunta a un video QuickTime vàlid." + +#: core/validators.py:216 +msgid "A valid URL is required." +msgstr "Es precisa d'una URL vàlida." + +#: core/validators.py:230 #, python-format msgid "" -"Posted by %(user)s at %(date)s\n" -"\n" -"%(comment)s\n" -"\n" -"http://%(domain)s%(url)s" +"Valid HTML is required. Specific errors are:\n" +"%s" msgstr "" -"Enviat per %(user)s el %(date)s\n" -"\n" -"%(comment)s\n" -"\n" -"http://%(domain)s%(url)s" - -#: contrib/comments/models.py:168 -msgid "person's name" -msgstr "nom de la persona" +"Es precisa HTML vàlid. Els errors específics sòn:\n" +"%s" -#: contrib/comments/models.py:171 -msgid "ip address" -msgstr "adreça ip" +#: core/validators.py:237 +#, python-format +msgid "Badly formed XML: %s" +msgstr "XML incorrectament formatejat: %s" -#: contrib/comments/models.py:173 -msgid "approved by staff" -msgstr "aprovat per el \"staff\"" +#: core/validators.py:254 +#, python-format +msgid "Invalid URL: %s" +msgstr "URL invalida: %s" -#: contrib/comments/models.py:176 -msgid "free comment" -msgstr "comentari lliure" +#: core/validators.py:259 +#: core/validators.py:261 +#, python-format +msgid "The URL %s is a broken link." +msgstr "La URL %sés un enllaç trencat." -#: contrib/comments/models.py:177 -msgid "free comments" -msgstr "comentaris lliures" +#: core/validators.py:267 +msgid "Enter a valid U.S. state abbreviation." +msgstr "Introdueixi una abreviatura vàlida d'estat d'els E.U.A.." -#: contrib/comments/models.py:233 -msgid "score" -msgstr "puntuació" +#: core/validators.py:281 +#, python-format +msgid "Watch your mouth! The word %s is not allowed here." +msgid_plural "Watch your mouth! The words %s are not allowed here." +msgstr[0] "Vigili la seva boca! Aquí no admetem la paraula: %s." +msgstr[1] "Vigili la seva boca! Aquí no admetem les paraules: %s." -#: contrib/comments/models.py:234 -msgid "score date" -msgstr "data de la puntuació" +#: core/validators.py:288 +#, python-format +msgid "This field must match the '%s' field." +msgstr "Aquest camp ha de concordar amb el camp '%s'." -#: contrib/comments/models.py:237 -msgid "karma score" -msgstr "puntuació de karma" +#: core/validators.py:307 +msgid "Please enter something for at least one field." +msgstr "Si us plau, introdueixi alguna cosa alemnys en un camp." -#: contrib/comments/models.py:238 -msgid "karma scores" -msgstr "punts de karma" +#: core/validators.py:316 +#: core/validators.py:327 +msgid "Please enter both fields or leave them both empty." +msgstr "Si us plau, ompli els dos camps o deixi'ls tots dos en blanc." -#: contrib/comments/models.py:242 +#: core/validators.py:335 #, python-format -msgid "%(score)d rating by %(user)s" -msgstr "%(score)d punt/s per %(user)s" +msgid "This field must be given if %(field)s is %(value)s" +msgstr "S'ha de proporcionar aquest camps si %(field)s és %(value)s" -#: contrib/comments/models.py:258 +#: core/validators.py:348 #, python-format -msgid "" -"This comment was flagged by %(user)s:\n" -"\n" -"%(text)s" -msgstr "" -"Aquest comentari va ser marcat per %(user)s:\n" -"\n" -"%(text)s" +msgid "This field must be given if %(field)s is not %(value)s" +msgstr "S'ha de proporcionar aquest camps si %(field)s no és %(value)s" -#: contrib/comments/models.py:265 -msgid "flag date" -msgstr "data de la marca" +#: core/validators.py:367 +msgid "Duplicate values are not allowed." +msgstr "No s'admeten valors duplicats." -#: contrib/comments/models.py:268 -msgid "user flag" -msgstr "marca d'usuari" +#: core/validators.py:382 +#, python-format +msgid "This value must be between %(lower)s and %(upper)s." +msgstr "Aquest valor ha de estar comprés entre %(lower)s i %(upper)s." -#: contrib/comments/models.py:269 -msgid "user flags" -msgstr "marques d'usuari" +#: core/validators.py:384 +#, python-format +msgid "This value must be at least %s." +msgstr "Aquest valor ha de ser com a mínim %s." -#: contrib/comments/models.py:273 +#: core/validators.py:386 #, python-format -msgid "Flag by %r" -msgstr "Marca de %r" +msgid "This value must be no more than %s." +msgstr "Aquest valor ha de ser com a màxim %s." -#: contrib/comments/models.py:278 -msgid "deletion date" -msgstr "data d'eliminació" +#: core/validators.py:422 +#, python-format +msgid "This value must be a power of %s." +msgstr "Aquest valor ha de ser una potència de %s." -#: contrib/comments/models.py:280 -msgid "moderator deletion" -msgstr "eliminació del moderador" +#: core/validators.py:432 +msgid "Please enter a valid decimal number." +msgstr "Si us plau, introdueixi un número decimal vàlid." -#: contrib/comments/models.py:281 -msgid "moderator deletions" -msgstr "eliminacions del moderador" +#: core/validators.py:439 +#, python-format +msgid "Please enter a valid decimal number with at most %s total digit." +msgid_plural "Please enter a valid decimal number with at most %s total digits." +msgstr[0] "Si us plau, introdueixi un número decimal vàlid de com a màxim %s digit." +msgstr[1] "Si us plau, introdueixi un número decimal vàlid de com a màxim %s digits." -#: contrib/comments/models.py:285 +#: core/validators.py:442 #, python-format -msgid "Moderator deletion by %r" -msgstr "eliminació del moderador per %r" +msgid "Please enter a valid decimal number with a whole part of at most %s digit." +msgid_plural "Please enter a valid decimal number with a whole part of at most %s digits." +msgstr[0] "Si us plau, introdueixi un número decimal vàlid que la seva part sencera sigui de com a màxim %s digit." +msgstr[1] "Si us plau, introdueixi un número decimal vàlid que la seva part sencera sigui de com a màxim %s digits." -#: contrib/comments/templates/comments/freeform.html:4 -msgid "Your name:" -msgstr "El seu nom:" +#: core/validators.py:445 +#, python-format +msgid "Please enter a valid decimal number with at most %s decimal place." +msgid_plural "Please enter a valid decimal number with at most %s decimal places." +msgstr[0] "Si us plau, introdueixi un número decimal vàlid de com a màxim %s posició decimal." +msgstr[1] "Si us plau, introdueixi un número decimal vàlid de com a màxim %s posicions decimals." -#: contrib/comments/templates/comments/freeform.html:5 -#: contrib/comments/templates/comments/form.html:28 -msgid "Comment:" -msgstr "Comentari:" +#: core/validators.py:453 +msgid "Please enter a valid floating point number." +msgstr "Si us plau, introdueixi un número amb punt de coma flotant vàlid." -#: contrib/comments/templates/comments/freeform.html:10 -#: contrib/comments/templates/comments/form.html:35 -msgid "Preview comment" -msgstr "Previsualitzar comentari" +#: core/validators.py:462 +#, python-format +msgid "Make sure your uploaded file is at least %s bytes big." +msgstr "Asseguris de que el fitxer que ha enviat té, com a mínim, %s bytes." -#: contrib/comments/templates/comments/form.html:6 -#: contrib/comments/templates/comments/form.html:8 -#: contrib/admin/templates/admin/login.html:17 -msgid "Username:" -msgstr "Usuari:" +#: core/validators.py:463 +#, python-format +msgid "Make sure your uploaded file is at most %s bytes big." +msgstr "Asseguris de que el fitxer que ha enviat té, com a màxim %s bytes." -#: contrib/comments/templates/comments/form.html:6 -#: contrib/admin/templates/admin/object_history.html:3 -#: contrib/admin/templates/admin/delete_confirmation.html:3 -#: contrib/admin/templates/admin/change_form.html:10 -#: contrib/admin/templates/admin/change_list.html:5 -#: contrib/admin/templates/admin/base.html:25 -#: contrib/admin/templates/admin/auth/user/change_password.html:9 -#: contrib/admin/templates/registration/password_change_form.html:3 -#: contrib/admin/templates/registration/password_change_done.html:3 -#: contrib/admin/templates/admin_doc/bookmarklets.html:4 -#: contrib/admin/templates/admin_doc/template_tag_index.html:5 -#: contrib/admin/templates/admin_doc/view_detail.html:4 -#: contrib/admin/templates/admin_doc/missing_docutils.html:4 -#: contrib/admin/templates/admin_doc/model_index.html:5 -#: contrib/admin/templates/admin_doc/index.html:4 -#: contrib/admin/templates/admin_doc/template_filter_index.html:5 -#: contrib/admin/templates/admin_doc/model_detail.html:3 -#: contrib/admin/templates/admin_doc/template_detail.html:4 -#: contrib/admin/templates/admin_doc/view_index.html:5 -msgid "Log out" -msgstr "Finalitzar sessió" +#: core/validators.py:480 +msgid "The format for this field is wrong." +msgstr "El format per aquest camp és incorrecte." -#: contrib/comments/templates/comments/form.html:8 -#: contrib/admin/templates/admin/login.html:20 -msgid "Password:" -msgstr "Contrasenya:" +#: core/validators.py:495 +msgid "This field is invalid." +msgstr "El camp no és vàlid." -#: contrib/comments/templates/comments/form.html:8 -msgid "Forgotten your password?" -msgstr "Contrasenya oblidada?" +#: core/validators.py:531 +#, python-format +msgid "Could not retrieve anything from %s." +msgstr "No s'ha pogut obtenir res de %s." -#: contrib/comments/templates/comments/form.html:12 -msgid "Ratings" -msgstr "Qualificacions" +#: core/validators.py:534 +#, python-format +msgid "The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'." +msgstr "La URL %(url)s ha va tornar la capcelera Content-Type '%(contenttype)s', que no és vàlida." -#: contrib/comments/templates/comments/form.html:12 -#: contrib/comments/templates/comments/form.html:23 -msgid "Required" -msgstr "Requerit" +#: core/validators.py:567 +#, python-format +msgid "Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with \"%(start)s\".)" +msgstr "Si us plau, tanqui l'etiqueta %(tag)s des de la línia %(line)s. (La línia comença amb \"%(start)s\".)" -#: contrib/comments/templates/comments/form.html:12 -#: contrib/comments/templates/comments/form.html:23 -msgid "Optional" -msgstr "Opcional" +#: core/validators.py:571 +#, python-format +msgid "Some text starting on line %(line)s is not allowed in that context. (Line starts with \"%(start)s\".)" +msgstr "Part del text que comença en la línia %(line)s no està permès en aquest context. (La línia comença per \"%(start)s\".)" -#: contrib/comments/templates/comments/form.html:23 -msgid "Post a photo" -msgstr "Enviar una fotografia" +#: core/validators.py:576 +#, python-format +msgid "\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%(start)s\".)" +msgstr "El \"%(attr)s\" de la línia %(line)s no és un atribut vàlid. (La línia comença per \"%(start)s\".)" -#: contrib/comments/views/comments.py:27 -msgid "" -"This rating is required because you've entered at least one other rating." -msgstr "Es precisa aquesta puntuació perquè has introduït almenys un altre." +#: core/validators.py:581 +#, python-format +msgid "\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%(start)s\".)" +msgstr "La \"<%(tag)s>\" de la línia %(line)s no és una etiqueta vàlida. (La línia comença per \"%(start)s\".)" -#: contrib/comments/views/comments.py:111 +#: core/validators.py:585 #, python-format -msgid "" -"This comment was posted by a user who has posted fewer than %(count)s " -"comment:\n" -"\n" -"%(text)s" -"This comment was posted by a user who has posted fewer than %(count)s " -"comments:\n" -"\n" -"%(text)s" -msgstr "" -"Aquest comentari el va enviar un usuari que ha enviat menys de %(count)s " -"comentari:\n" -"\n" -"%(text)s" -"Aquest comentari el va enviar un usuari que ha enviat menys de %(count)s " -"comentaris:\n" -"\n" -"%(text)s" +msgid "A tag on line %(line)s is missing one or more required attributes. (Line starts with \"%(start)s\".)" +msgstr "Una etiqueta de la línia %(line)s li falta un o més atributs requerits.(La línia comença per \"%(start)s\".)" -#: contrib/comments/views/comments.py:116 +#: core/validators.py:590 #, python-format -msgid "" -"This comment was posted by a sketchy user:\n" -"\n" -"%(text)s" -msgstr "" -"Aquest comentari va ser publicat per un usuari incomplet\n" -"\n" -"%(text)s" +msgid "The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line starts with \"%(start)s\".)" +msgstr "L'atribut \"%(attr)s\" de la línia %(line)s té un valor que no és vàlid. (La línia comença per \"%(start)s\".)" -#: contrib/comments/views/comments.py:188 -#: contrib/comments/views/comments.py:280 -msgid "Only POSTs are allowed" -msgstr "Només s'admed POST" +#: contrib/auth/forms.py:17 +#: contrib/auth/forms.py:138 +msgid "The two password fields didn't match." +msgstr "Els dos camps de contrasenya no coincideixen." -#: contrib/comments/views/comments.py:192 -#: contrib/comments/views/comments.py:284 -msgid "One or more of the required fields wasn't submitted" -msgstr "Un o més dels caps requerits no ha estat sotmès" +#: contrib/auth/forms.py:25 +msgid "A user with that username already exists." +msgstr "Ja existeix un usuari amb aquest nom." -#: contrib/comments/views/comments.py:196 -#: contrib/comments/views/comments.py:286 -msgid "Somebody tampered with the comment form (security violation)" -msgstr "" -"Algú està jugant amb el formulari de comentaris (violació de seguretat)" +#: contrib/auth/forms.py:53 +msgid "Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in." +msgstr "El seu navegador no sembla tenir les 'cookies' (galetes) activades. Aquestes són necessàries per iniciar la sessió." -#: contrib/comments/views/comments.py:206 -#: contrib/comments/views/comments.py:292 -msgid "" -"The comment form had an invalid 'target' parameter -- the object ID was " -"invalid" -msgstr "" -"El formulari de comentaris tenia un paràmetre 'target' invàlid -- el ID del " -"objecte era invàlid" +#: contrib/auth/forms.py:60 +#: contrib/admin/views/decorators.py:10 +msgid "Please enter a correct username and password. Note that both fields are case-sensitive." +msgstr "Si us plau, introdueixi un nom d'usuari i contrasenya vàlids. Tingui en compte que tots dos camps son sensibles a majúscules i minúscules." -#: contrib/comments/views/comments.py:257 -#: contrib/comments/views/comments.py:321 -msgid "The comment form didn't provide either 'preview' or 'post'" -msgstr "" -"El formulari del comentari no ha proveït ni 'previsualitzar' ni 'enviar'" +#: contrib/auth/forms.py:62 +msgid "This account is inactive." +msgstr "Aquest compte està inactiu" -#: contrib/comments/views/karma.py:19 -msgid "Anonymous users cannot vote" -msgstr "Els usuaris anònims no poden votar" +#: contrib/auth/forms.py:84 +msgid "That e-mail address doesn't have an associated user account. Are you sure you've registered?" +msgstr "Aquesta adreça de correu no té associada cap compte d'usuari. Està segur de que s'ha registrat?" -#: contrib/comments/views/karma.py:23 -msgid "Invalid comment ID" -msgstr "ID del comentari invàlid" +#: contrib/auth/forms.py:117 +msgid "The two 'new password' fields didn't match." +msgstr "Els dos camps de nova contrasenya no coincideixen." -#: contrib/comments/views/karma.py:25 -msgid "No voting for yourself" -msgstr "No pots votar-te a tu mateix" +#: contrib/auth/forms.py:124 +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "La seva antiga contrasenya no és correcte. Si el plau, introdueixi-la de nou." + +#: contrib/auth/models.py:53 +#: contrib/auth/models.py:73 +msgid "name" +msgstr "nom" + +#: contrib/auth/models.py:55 +msgid "codename" +msgstr "nom en clau" + +#: contrib/auth/models.py:58 +msgid "permission" +msgstr "permís" + +#: contrib/auth/models.py:59 +#: contrib/auth/models.py:74 +msgid "permissions" +msgstr "permissos" + +#: contrib/auth/models.py:77 +msgid "group" +msgstr "grup" + +#: contrib/auth/models.py:78 +#: contrib/auth/models.py:121 +msgid "groups" +msgstr "grups" + +#: contrib/auth/models.py:111 +msgid "username" +msgstr "nom d'usuari" + +#: contrib/auth/models.py:111 +msgid "Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores)." +msgstr "Requerit. 30 o menys caracters. Només caracters alfanumèrics (lletres, dígits i guions baixos)." + +#: contrib/auth/models.py:112 +msgid "first name" +msgstr "nom propi" + +#: contrib/auth/models.py:113 +msgid "last name" +msgstr "cognoms" + +#: contrib/auth/models.py:114 +msgid "e-mail address" +msgstr "adreça de correu electrònic" + +#: contrib/auth/models.py:115 +msgid "password" +msgstr "contrasenya" + +#: contrib/auth/models.py:115 +msgid "Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change password form</a>." +msgstr "Utilitzi '[algo]$[salt]$[hexdigest]' o el <a href=\"password/\">formulari de canvi de contrasenya</a>." + +#: contrib/auth/models.py:116 +msgid "staff status" +msgstr "és membre del personal" + +#: contrib/auth/models.py:116 +msgid "Designates whether the user can log into this admin site." +msgstr "Indica si l'usuari pot entrar en el lloc administratiu." + +#: contrib/auth/models.py:117 +msgid "active" +msgstr "actiu" + +#: contrib/auth/models.py:117 +msgid "Designates whether this user can log into the Django admin. Unselect this instead of deleting accounts." +msgstr "Designa si aquest usuari pot iniciar sessió a la interfície administrativa Djano. Deselecciona-ho enlloc de esborrar comptes d'usuari." + +#: contrib/auth/models.py:118 +msgid "superuser status" +msgstr "estat de superusuari" + +#: contrib/auth/models.py:118 +msgid "Designates that this user has all permissions without explicitly assigning them." +msgstr "Designa que aquest usuari té tots els permisos sense assignar-los explícitament." + +#: contrib/auth/models.py:119 +msgid "last login" +msgstr "últim inici de sessió" -#: contrib/admin/models.py:16 +#: contrib/auth/models.py:120 +msgid "date joined" +msgstr "data de creació" + +#: contrib/auth/models.py:122 +msgid "In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in." +msgstr "Junt amb els permissos asignats manualment, aquest usuari tindrà, també, els permissos dels grups dels que sigui membre." + +#: contrib/auth/models.py:123 +msgid "user permissions" +msgstr "permissos de l'usuari" + +#: contrib/auth/models.py:127 +msgid "user" +msgstr "usuari" + +#: contrib/auth/models.py:128 +msgid "users" +msgstr "usuaris" + +#: contrib/auth/models.py:134 +msgid "Personal info" +msgstr "Informaciò personal" + +#: contrib/auth/models.py:135 +msgid "Permissions" +msgstr "permissos" + +#: contrib/auth/models.py:136 +msgid "Important dates" +msgstr "Dates importants" + +#: contrib/auth/models.py:137 +msgid "Groups" +msgstr "Grups" + +#: contrib/auth/models.py:288 +msgid "message" +msgstr "missatge" + +#: contrib/auth/views.py:47 +msgid "Logged out" +msgstr "Sessió finalitzada" + +#: contrib/admin/models.py:17 msgid "action time" msgstr "moment de l'acció" -#: contrib/admin/models.py:19 +#: contrib/admin/models.py:20 msgid "object id" msgstr "id del objecte" -#: contrib/admin/models.py:20 +#: contrib/admin/models.py:21 msgid "object repr" msgstr "'repr' de l'objecte" -#: contrib/admin/models.py:21 +#: contrib/admin/models.py:22 msgid "action flag" msgstr "marca de l'acció" -#: contrib/admin/models.py:22 +#: contrib/admin/models.py:23 msgid "change message" msgstr "missatge del canvi" -#: contrib/admin/models.py:25 +#: contrib/admin/models.py:26 msgid "log entry" msgstr "entrada del registre" -#: contrib/admin/models.py:26 +#: contrib/admin/models.py:27 msgid "log entries" msgstr "entrades del registre" -#: contrib/admin/filterspecs.py:40 +#: contrib/admin/filterspecs.py:42 #, python-format msgid "" "<h3>By %s:</h3>\n" @@ -683,142 +746,419 @@ msgstr "" "<h3>Per %s:</h3>\n" "<ul>\n" -#: contrib/admin/filterspecs.py:70 contrib/admin/filterspecs.py:88 -#: contrib/admin/filterspecs.py:143 contrib/admin/filterspecs.py:169 +#: contrib/admin/filterspecs.py:72 +#: contrib/admin/filterspecs.py:90 +#: contrib/admin/filterspecs.py:145 +#: contrib/admin/filterspecs.py:171 msgid "All" msgstr "Tots" -#: contrib/admin/filterspecs.py:109 +#: contrib/admin/filterspecs.py:111 msgid "Any date" msgstr "Qualsevol data" -#: contrib/admin/filterspecs.py:110 +#: contrib/admin/filterspecs.py:112 msgid "Today" msgstr "Avui" -#: contrib/admin/filterspecs.py:113 +#: contrib/admin/filterspecs.py:115 msgid "Past 7 days" msgstr "Últims 7 dies" -#: contrib/admin/filterspecs.py:115 +#: contrib/admin/filterspecs.py:117 msgid "This month" msgstr "Aquest mes" -#: contrib/admin/filterspecs.py:117 +#: contrib/admin/filterspecs.py:119 msgid "This year" msgstr "Aquest any" -#: contrib/admin/templatetags/admin_list.py:249 +#: contrib/admin/filterspecs.py:145 +#: oldforms/__init__.py:591 +#: newforms/widgets.py:188 +msgid "Yes" +msgstr "Si" + +#: contrib/admin/filterspecs.py:145 +#: oldforms/__init__.py:591 +#: newforms/widgets.py:188 +msgid "No" +msgstr "No" + +#: contrib/admin/filterspecs.py:152 +#: oldforms/__init__.py:591 +#: newforms/widgets.py:188 +msgid "Unknown" +msgstr "Desconegut" + +#: contrib/admin/views/decorators.py:24 +#: contrib/admin/templates/admin/login.html:25 +msgid "Log in" +msgstr "Iniciar sessió" + +#: contrib/admin/views/decorators.py:62 +msgid "Please log in again, because your session has expired. Don't worry: Your submission has been saved." +msgstr "Si us plau, identifiquis de nou doncs la seva sessió ha expirat. No es preocupi, el seu enviament està emmagatzemat." + +#: contrib/admin/views/decorators.py:69 +msgid "Looks like your browser isn't configured to accept cookies. Please enable cookies, reload this page, and try again." +msgstr "Sembla ser que el seu navegador no està configurat per acceptar 'cookies' (galetes). Si us plau, habiliti les 'cookies', recarregui aquesta pàgina i provi-ho de nou. " + +#: contrib/admin/views/decorators.py:83 +msgid "Usernames cannot contain the '@' character." +msgstr "Els noms d'usuari no poden contenir el caracter '@'." + +#: contrib/admin/views/decorators.py:85 +#, python-format +msgid "Your e-mail address is not your username. Try '%s' instead." +msgstr "La seva adreça de correu no és el seu nom d'usuari. Provi '%s' en tot cas." + +#: contrib/admin/views/main.py:230 +msgid "Site administration" +msgstr "Lloc administratiu" + +#: contrib/admin/views/main.py:264 +#: contrib/admin/views/auth.py:20 +#, python-format +msgid "The %(name)s \"%(obj)s\" was added successfully." +msgstr "El/la %(name)s \"%(obj)s\".ha estat agregat/da amb èxit." + +#: contrib/admin/views/main.py:268 +#: contrib/admin/views/main.py:354 +#: contrib/admin/views/auth.py:25 +msgid "You may edit it again below." +msgstr "Pot editar-lo de nou abaix." + +#: contrib/admin/views/main.py:278 +#: contrib/admin/views/main.py:363 +#, python-format +msgid "You may add another %s below." +msgstr "Pot afegir un altre %s a baix." + +#: contrib/admin/views/main.py:296 +#, python-format +msgid "Add %s" +msgstr "Afegir %s" + +#: contrib/admin/views/main.py:342 +#, python-format +msgid "Added %s." +msgstr "Agregat %s." + +#: contrib/admin/views/main.py:344 +#, python-format +msgid "Changed %s." +msgstr "Modificat %s." + +#: contrib/admin/views/main.py:346 +#, python-format +msgid "Deleted %s." +msgstr "Eliminat %s." + +#: contrib/admin/views/main.py:349 +msgid "No fields changed." +msgstr "Cap camp canviat." + +#: contrib/admin/views/main.py:352 +#, python-format +msgid "The %(name)s \"%(obj)s\" was changed successfully." +msgstr "S'ha modificat amb èxist el/la %(name)s \"%(obj)s." + +#: contrib/admin/views/main.py:360 +#, python-format +msgid "The %(name)s \"%(obj)s\" was added successfully. You may edit it again below." +msgstr "S'ha agregat amb èxit el/la %(name)s \"%(obj)s\". Pot editar-lo de nou abaix." + +#: contrib/admin/views/main.py:398 +#, python-format +msgid "Change %s" +msgstr "Modificar %s" + +#: contrib/admin/views/main.py:483 +#, python-format +msgid "One or more %(fieldname)s in %(name)s: %(obj)s" +msgstr "Un o més %(fieldname)s en %(name)s: %(obj)s" + +#: contrib/admin/views/main.py:488 +#, python-format +msgid "One or more %(fieldname)s in %(name)s:" +msgstr "Un o més %(fieldname)s en %(name)s:" + +#: contrib/admin/views/main.py:520 +#, python-format +msgid "The %(name)s \"%(obj)s\" was deleted successfully." +msgstr "El/la %(name)s \"%(obj)s\".ha estat eliminat amb èxit." + +#: contrib/admin/views/main.py:523 +msgid "Are you sure?" +msgstr "Està segur?" + +#: contrib/admin/views/main.py:545 +#, python-format +msgid "Change history: %s" +msgstr "Modificar històric: %s" + +#: contrib/admin/views/main.py:579 +#, python-format +msgid "Select %s" +msgstr "Seleccioni %s" + +#: contrib/admin/views/main.py:579 +#, python-format +msgid "Select %s to change" +msgstr "Seleccioni %s per modificar" + +#: contrib/admin/views/main.py:780 +msgid "Database error" +msgstr "Error de/en la base de dades" + +#: contrib/admin/views/doc.py:47 +#: contrib/admin/views/doc.py:49 +#: contrib/admin/views/doc.py:51 +msgid "tag:" +msgstr "etiqueta:" + +#: contrib/admin/views/doc.py:78 +#: contrib/admin/views/doc.py:80 +#: contrib/admin/views/doc.py:82 +msgid "filter:" +msgstr "filtre:" + +#: contrib/admin/views/doc.py:136 +#: contrib/admin/views/doc.py:138 +#: contrib/admin/views/doc.py:140 +msgid "view:" +msgstr "vista:" + +#: contrib/admin/views/doc.py:165 +#, python-format +msgid "App %r not found" +msgstr "La aplicació %r no s'ha pogut trobar" + +#: contrib/admin/views/doc.py:172 +#, python-format +msgid "Model %(name)r not found in app %(label)r" +msgstr "El model %(name)r no s'ha trobat en la aplicació %(label)r" + +#: contrib/admin/views/doc.py:184 +#, python-format +msgid "the related `%(label)s.%(type)s` object" +msgstr "el objecte relacionat `%(label)s.%(type)s`" + +#: contrib/admin/views/doc.py:184 +#: contrib/admin/views/doc.py:206 +#: contrib/admin/views/doc.py:220 +#: contrib/admin/views/doc.py:225 +msgid "model:" +msgstr "model:" + +#: contrib/admin/views/doc.py:215 +#, python-format +msgid "related `%(label)s.%(name)s` objects" +msgstr "objectes relacionats `%(label)s.%(name)s`" + +#: contrib/admin/views/doc.py:220 +#, python-format +msgid "all %s" +msgstr "tots %s" + +#: contrib/admin/views/doc.py:225 +#, python-format +msgid "number of %s" +msgstr "nombre de %s" + +#: contrib/admin/views/doc.py:230 +#, python-format +msgid "Fields on %s objects" +msgstr "Camps en objectes %s" + +#: contrib/admin/views/doc.py:292 +#: contrib/admin/views/doc.py:303 +#: contrib/admin/views/doc.py:305 +#: contrib/admin/views/doc.py:311 +#: contrib/admin/views/doc.py:312 +#: contrib/admin/views/doc.py:314 +msgid "Integer" +msgstr "Enter" + +#: contrib/admin/views/doc.py:293 +msgid "Boolean (Either True or False)" +msgstr "Booleà (Verdader o Fals)" + +#: contrib/admin/views/doc.py:294 +#: contrib/admin/views/doc.py:313 +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Cadena (de fins a %(max_length)s)" + +#: contrib/admin/views/doc.py:295 +msgid "Comma-separated integers" +msgstr "Enters separats per comes" + +#: contrib/admin/views/doc.py:296 +msgid "Date (without time)" +msgstr "Data (sense hora)" + +#: contrib/admin/views/doc.py:297 +msgid "Date (with time)" +msgstr "Data (amb hora)" + +#: contrib/admin/views/doc.py:298 +msgid "Decimal number" +msgstr "Número decimal" + +#: contrib/admin/views/doc.py:299 +msgid "E-mail address" +msgstr "Adreça de correu electrònic" + +#: contrib/admin/views/doc.py:300 +#: contrib/admin/views/doc.py:301 +#: contrib/admin/views/doc.py:304 +msgid "File path" +msgstr "Ruta del fitxer" + +#: contrib/admin/views/doc.py:302 +msgid "Floating point number" +msgstr "Número amb punt de coma flotant" + +#: contrib/admin/views/doc.py:306 +#: contrib/comments/models.py:85 +msgid "IP address" +msgstr "Adreça IP" + +#: contrib/admin/views/doc.py:308 +msgid "Boolean (Either True, False or None)" +msgstr "Booleà (Verdader, Fals o 'None' (cap))" + +#: contrib/admin/views/doc.py:309 +msgid "Relation to parent model" +msgstr "Relació amb el model pare" + +#: contrib/admin/views/doc.py:310 +msgid "Phone number" +msgstr "Número de telèfon" + +#: contrib/admin/views/doc.py:315 +msgid "Text" +msgstr "Texte" + +#: contrib/admin/views/doc.py:316 +msgid "Time" +msgstr "Hora" + +#: contrib/admin/views/doc.py:317 +#: contrib/flatpages/models.py:7 +msgid "URL" +msgstr "URL" + +#: contrib/admin/views/doc.py:318 +msgid "U.S. state (two uppercase letters)" +msgstr "Estat dels E.U.A. (dos lletres majúscules)" + +#: contrib/admin/views/doc.py:319 +msgid "XML text" +msgstr "Texte XML" + +#: contrib/admin/views/doc.py:345 +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s no sembla ser un objecte 'urlpattern'" + +#: contrib/admin/views/auth.py:31 +msgid "Add user" +msgstr "Afegir usuari" + +#: contrib/admin/views/auth.py:58 +msgid "Password changed successfully." +msgstr "Canvi de clau exitós" + +#: contrib/admin/views/auth.py:65 +#, python-format +msgid "Change password: %s" +msgstr "Canviar clau: %s" + +#: contrib/admin/templatetags/admin_list.py:254 msgid "All dates" msgstr "Totes les dates" -#: contrib/admin/templates/admin/object_history.html:3 +#: contrib/admin/templates/admin/pagination.html:10 +msgid "Show all" +msgstr "Mostrar tots" + #: contrib/admin/templates/admin/delete_confirmation.html:3 #: contrib/admin/templates/admin/change_form.html:10 #: contrib/admin/templates/admin/change_list.html:5 +#: contrib/admin/templates/admin/object_history.html:3 #: contrib/admin/templates/admin/base.html:25 #: contrib/admin/templates/admin/auth/user/change_password.html:9 +#: contrib/admin/templates/admin_doc/bookmarklets.html:3 #: contrib/admin/templates/registration/password_change_form.html:3 #: contrib/admin/templates/registration/password_change_done.html:3 -#: contrib/admin/templates/admin_doc/bookmarklets.html:3 msgid "Documentation" msgstr "Documentació" -#: contrib/admin/templates/admin/object_history.html:3 #: contrib/admin/templates/admin/delete_confirmation.html:3 #: contrib/admin/templates/admin/change_form.html:10 #: contrib/admin/templates/admin/change_list.html:5 +#: contrib/admin/templates/admin/object_history.html:3 #: contrib/admin/templates/admin/base.html:25 #: contrib/admin/templates/admin/auth/user/change_password.html:9 #: contrib/admin/templates/admin/auth/user/change_password.html:15 #: contrib/admin/templates/admin/auth/user/change_password.html:46 -#: contrib/admin/templates/registration/password_change_form.html:3 -#: contrib/admin/templates/registration/password_change_done.html:3 +#: contrib/admin/templates/admin_doc/template_filter_index.html:5 #: contrib/admin/templates/admin_doc/bookmarklets.html:4 #: contrib/admin/templates/admin_doc/template_tag_index.html:5 -#: contrib/admin/templates/admin_doc/view_detail.html:4 -#: contrib/admin/templates/admin_doc/missing_docutils.html:4 -#: contrib/admin/templates/admin_doc/model_index.html:5 #: contrib/admin/templates/admin_doc/index.html:4 -#: contrib/admin/templates/admin_doc/template_filter_index.html:5 #: contrib/admin/templates/admin_doc/model_detail.html:3 +#: contrib/admin/templates/admin_doc/missing_docutils.html:4 #: contrib/admin/templates/admin_doc/template_detail.html:4 #: contrib/admin/templates/admin_doc/view_index.html:5 +#: contrib/admin/templates/admin_doc/model_index.html:5 +#: contrib/admin/templates/admin_doc/view_detail.html:4 +#: contrib/admin/templates/registration/password_change_form.html:3 +#: contrib/admin/templates/registration/password_change_done.html:3 msgid "Change password" msgstr "Canviar clau" -#: contrib/admin/templates/admin/object_history.html:5 -#: contrib/admin/templates/admin/invalid_setup.html:4 +#: contrib/admin/templates/admin/delete_confirmation.html:3 +#: contrib/admin/templates/admin/change_form.html:10 +#: contrib/admin/templates/admin/change_list.html:5 +#: contrib/admin/templates/admin/object_history.html:3 +#: contrib/admin/templates/admin/base.html:25 +#: contrib/admin/templates/admin/auth/user/change_password.html:9 +#: contrib/admin/templates/admin_doc/template_filter_index.html:5 +#: contrib/admin/templates/admin_doc/bookmarklets.html:4 +#: contrib/admin/templates/admin_doc/template_tag_index.html:5 +#: contrib/admin/templates/admin_doc/index.html:4 +#: contrib/admin/templates/admin_doc/model_detail.html:3 +#: contrib/admin/templates/admin_doc/missing_docutils.html:4 +#: contrib/admin/templates/admin_doc/template_detail.html:4 +#: contrib/admin/templates/admin_doc/view_index.html:5 +#: contrib/admin/templates/admin_doc/model_index.html:5 +#: contrib/admin/templates/admin_doc/view_detail.html:4 +#: contrib/admin/templates/registration/password_change_form.html:3 +#: contrib/admin/templates/registration/password_change_done.html:3 +#: contrib/comments/templates/comments/form.html:6 +msgid "Log out" +msgstr "Finalitzar sessió" + #: contrib/admin/templates/admin/delete_confirmation.html:6 #: contrib/admin/templates/admin/change_form.html:13 -#: contrib/admin/templates/admin/500.html:4 #: contrib/admin/templates/admin/change_list.html:6 +#: contrib/admin/templates/admin/object_history.html:5 +#: contrib/admin/templates/admin/500.html:4 +#: contrib/admin/templates/admin/invalid_setup.html:4 #: contrib/admin/templates/admin/base.html:30 #: contrib/admin/templates/admin/auth/user/change_password.html:12 +#: contrib/admin/templates/admin_doc/bookmarklets.html:3 +#: contrib/admin/templates/registration/password_reset_form.html:4 #: contrib/admin/templates/registration/logged_out.html:4 -#: contrib/admin/templates/registration/password_change_form.html:4 #: contrib/admin/templates/registration/password_reset_done.html:4 +#: contrib/admin/templates/registration/password_change_form.html:4 #: contrib/admin/templates/registration/password_change_done.html:4 -#: contrib/admin/templates/registration/password_reset_form.html:4 -#: contrib/admin/templates/admin_doc/bookmarklets.html:3 msgid "Home" msgstr "Inici" -#: contrib/admin/templates/admin/object_history.html:5 -#: contrib/admin/templates/admin/change_form.html:21 -msgid "History" -msgstr "Històric" - -#: contrib/admin/templates/admin/object_history.html:18 -msgid "Date/time" -msgstr "Data/hora" - -#: contrib/admin/templates/admin/object_history.html:19 -msgid "User" -msgstr "Usuari" - -#: contrib/admin/templates/admin/object_history.html:20 -msgid "Action" -msgstr "Acció" - -#: contrib/admin/templates/admin/object_history.html:26 -msgid "DATE_WITH_TIME_FULL" -msgstr "F j, Y, H:i " - -#: contrib/admin/templates/admin/object_history.html:36 -msgid "" -"This object doesn't have a change history. It probably wasn't added via this " -"admin site." -msgstr "" -"Aquest objecte no te historial de canvis. Probablement no va ser afegit " -"utilitzant aquest lloc administratiu." - -#: contrib/admin/templates/admin/invalid_setup.html:8 -msgid "" -"Something's wrong with your database installation. Make sure the appropriate " -"database tables have been created, and make sure the database is readable by " -"the appropriate user." -msgstr "" -"Alguna cosa està malament en la instal·lació de la teva base de dades. " -"Assegurat de que s'han creat les taules, i de que la base de dades és " -"llegible per l'usuari apropiat." - -#: contrib/admin/templates/admin/search_form.html:8 -msgid "Go" -msgstr "Cercar" - -#: contrib/admin/templates/admin/search_form.html:10 -#, python-format -msgid "1 result" -msgid_plural "%(counter)s results" -msgstr[0] "1 resultat" -msgstr[1] "%(counter)s resultats" - -#: contrib/admin/templates/admin/search_form.html:10 -#, python-format -msgid "%(full_result_count)s total" -msgstr "%(full_result_count)s en total" - #: contrib/admin/templates/admin/delete_confirmation.html:9 #: contrib/admin/templates/admin/submit_line.html:3 msgid "Delete" @@ -826,42 +1166,37 @@ msgstr "Eliminar" #: contrib/admin/templates/admin/delete_confirmation.html:14 #, python-format -msgid "" -"Deleting the %(object_name)s '%(escaped_object)s' would result in deleting " -"related objects, but your account doesn't have permission to delete the " -"following types of objects:" -msgstr "" -"Eliminar el/la %(object_name)s '%(escaped_object)s' provocaria l'eliminació " -"d'objectes relacionats, però el seu compte no te permisos per a esborrar els " -"tipus d'objecte següents:" +msgid "Deleting the %(object_name)s '%(escaped_object)s' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" +msgstr "Eliminar el/la %(object_name)s '%(escaped_object)s' provocaria l'eliminació d'objectes relacionats, però el seu compte no te permisos per a esborrar els tipus d'objecte següents:" #: contrib/admin/templates/admin/delete_confirmation.html:21 #, python-format -msgid "" -"Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? " -"All of the following related items will be deleted:" -msgstr "" -"Està segur de voler esborrar els/les %(object_name)s \"%(escaped_object)s\"? " -"S'esborraran els següents elements relacionats:" +msgid "Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? All of the following related items will be deleted:" +msgstr "Està segur de voler esborrar els/les %(object_name)s \"%(escaped_object)s\"? S'esborraran els següents elements relacionats:" #: contrib/admin/templates/admin/delete_confirmation.html:26 msgid "Yes, I'm sure" msgstr "Si, estic segur" -#: contrib/admin/templates/admin/pagination.html:10 -msgid "Show all" -msgstr "Mostrar tots" +#: contrib/admin/templates/admin/404.html:4 +#: contrib/admin/templates/admin/404.html:8 +msgid "Page not found" +msgstr "No s'ha pogut trobar la pàgina" -#: contrib/admin/templates/admin/login.html:25 -#: contrib/admin/views/decorators.py:24 -msgid "Log in" -msgstr "Iniciar sessió" +#: contrib/admin/templates/admin/404.html:10 +msgid "We're sorry, but the requested page could not be found." +msgstr "Ho sentim, però no s'ha pogut trobar la pàgina solicitada" #: contrib/admin/templates/admin/change_form.html:15 #: contrib/admin/templates/admin/index.html:28 msgid "Add" msgstr "Afegir" +#: contrib/admin/templates/admin/change_form.html:21 +#: contrib/admin/templates/admin/object_history.html:5 +msgid "History" +msgstr "Històric" + #: contrib/admin/templates/admin/change_form.html:22 msgid "View on site" msgstr "Veure en el lloc" @@ -881,6 +1216,32 @@ msgstr "Ordre" msgid "Order:" msgstr "Ordre:" +#: contrib/admin/templates/admin/filter.html:2 +#, python-format +msgid " By %(filter_title)s " +msgstr "Per %(filter_title)s " + +#: contrib/admin/templates/admin/submit_line.html:4 +msgid "Save as new" +msgstr "Desar com a nou" + +#: contrib/admin/templates/admin/submit_line.html:5 +msgid "Save and add another" +msgstr "Desar i afegir-ne un de nou" + +#: contrib/admin/templates/admin/submit_line.html:6 +msgid "Save and continue editing" +msgstr "Desar i continuar editant" + +#: contrib/admin/templates/admin/submit_line.html:7 +msgid "Save" +msgstr "Desar" + +#: contrib/admin/templates/admin/change_list.html:12 +#, python-format +msgid "Add %(name)s" +msgstr "Afegir %(name)s" + #: contrib/admin/templates/admin/index.html:17 #, python-format msgid "Models available in the %(name)s application." @@ -911,6 +1272,34 @@ msgstr "Les meves accions" msgid "None available" msgstr "Cap disponible" +#: contrib/admin/templates/admin/base_site.html:4 +msgid "Django site admin" +msgstr "Lloc administratiu de Django" + +#: contrib/admin/templates/admin/base_site.html:7 +msgid "Django administration" +msgstr "Adminsitració de Django" + +#: contrib/admin/templates/admin/object_history.html:18 +msgid "Date/time" +msgstr "Data/hora" + +#: contrib/admin/templates/admin/object_history.html:19 +msgid "User" +msgstr "Usuari" + +#: contrib/admin/templates/admin/object_history.html:20 +msgid "Action" +msgstr "Acció" + +#: contrib/admin/templates/admin/object_history.html:26 +msgid "DATE_WITH_TIME_FULL" +msgstr "F j, Y, H:i " + +#: contrib/admin/templates/admin/object_history.html:36 +msgid "This object doesn't have a change history. It probably wasn't added via this admin site." +msgstr "Aquest objecte no te historial de canvis. Probablement no va ser afegit utilitzant aquest lloc administratiu." + #: contrib/admin/templates/admin/500.html:4 msgid "Server error" msgstr "Error del servidor" @@ -924,71 +1313,51 @@ msgid "Server Error <em>(500)</em>" msgstr "Error del servidor <em>(500)</em>" #: contrib/admin/templates/admin/500.html:10 -msgid "" -"There's been an error. It's been reported to the site administrators via e-" -"mail and should be fixed shortly. Thanks for your patience." -msgstr "" -"Hi ha hagut un error. S'ha informat als administradors del lloc per correu " -"electrònic y hauria d'arreglar-se en breu. Gràcies per la seva paciència." +msgid "There's been an error. It's been reported to the site administrators via e-mail and should be fixed shortly. Thanks for your patience." +msgstr "Hi ha hagut un error. S'ha informat als administradors del lloc per correu electrònic y hauria d'arreglar-se en breu. Gràcies per la seva paciència." -#: contrib/admin/templates/admin/change_list.html:12 -#, python-format -msgid "Add %(name)s" -msgstr "Afegir %(name)s" +#: contrib/admin/templates/admin/invalid_setup.html:8 +msgid "Something's wrong with your database installation. Make sure the appropriate database tables have been created, and make sure the database is readable by the appropriate user." +msgstr "Alguna cosa està malament en la instal·lació de la teva base de dades. Assegurat de que s'han creat les taules, i de que la base de dades és llegible per l'usuari apropiat." -#: contrib/admin/templates/admin/base.html:25 -msgid "Welcome," -msgstr "Benvingut," +#: contrib/admin/templates/admin/search_form.html:8 +msgid "Go" +msgstr "Cercar" -#: contrib/admin/templates/admin/base_site.html:4 -msgid "Django site admin" -msgstr "Lloc administratiu de Django" +#: contrib/admin/templates/admin/search_form.html:10 +#, python-format +msgid "1 result" +msgid_plural "%(counter)s results" +msgstr[0] "1 resultat" +msgstr[1] "%(counter)s resultats" -#: contrib/admin/templates/admin/base_site.html:7 -msgid "Django administration" -msgstr "Adminsitració de Django" +#: contrib/admin/templates/admin/search_form.html:10 +#, python-format +msgid "%(full_result_count)s total" +msgstr "%(full_result_count)s en total" #: contrib/admin/templates/admin/filters.html:4 msgid "Filter" msgstr "Filtre" -#: contrib/admin/templates/admin/submit_line.html:4 -msgid "Save as new" -msgstr "Desar com a nou" - -#: contrib/admin/templates/admin/submit_line.html:5 -msgid "Save and add another" -msgstr "Desar i afegir-ne un de nou" - -#: contrib/admin/templates/admin/submit_line.html:6 -msgid "Save and continue editing" -msgstr "Desar i continuar editant" - -#: contrib/admin/templates/admin/submit_line.html:7 -msgid "Save" -msgstr "Desar" - -#: contrib/admin/templates/admin/404.html:4 -#: contrib/admin/templates/admin/404.html:8 -msgid "Page not found" -msgstr "No s'ha pogut trobar la pàgina" +#: contrib/admin/templates/admin/login.html:17 +#: contrib/comments/templates/comments/form.html:6 +#: contrib/comments/templates/comments/form.html:8 +msgid "Username:" +msgstr "Usuari:" -#: contrib/admin/templates/admin/404.html:10 -msgid "We're sorry, but the requested page could not be found." -msgstr "Ho sentim, però no s'ha pogut trobar la pàgina solicitada" +#: contrib/admin/templates/admin/login.html:20 +#: contrib/comments/templates/comments/form.html:8 +msgid "Password:" +msgstr "Contrasenya:" -#: contrib/admin/templates/admin/filter.html:2 -#, python-format -msgid " By %(filter_title)s " -msgstr "Per %(filter_title)s " +#: contrib/admin/templates/admin/base.html:25 +msgid "Welcome," +msgstr "Benvingut," #: contrib/admin/templates/admin/auth/user/add_form.html:6 -msgid "" -"First, enter a username and password. Then, you'll be able to edit more user " -"options." -msgstr "" -"Primer, entri un usuari i una contrasenya. Després podrà editar més opcions " -"del usuari." +msgid "First, enter a username and password. Then, you'll be able to edit more user options." +msgstr "Primer, entri un usuari i una contrasenya. Després podrà editar més opcions del usuari." #: contrib/admin/templates/admin/auth/user/add_form.html:12 msgid "Username" @@ -1014,140 +1383,6 @@ msgstr "Introdueixi la mateixa contrasenya que a sobre, per a verificació." msgid "Enter a new password for the user <strong>%(username)s</strong>." msgstr "Introdueixi una contrasenya per l'usuari <strong>%(username)s</strong>" -#: contrib/admin/templates/widget/date_time.html:3 -msgid "Date:" -msgstr "Data:" - -#: contrib/admin/templates/widget/date_time.html:4 -msgid "Time:" -msgstr "Hora:" - -#: contrib/admin/templates/widget/file.html:2 -msgid "Currently:" -msgstr "Actualment:" - -#: contrib/admin/templates/widget/file.html:3 -msgid "Change:" -msgstr "Modificar:" - -#: contrib/admin/templates/registration/logged_out.html:8 -msgid "Thanks for spending some quality time with the Web site today." -msgstr "Gràcies per emprar algun temps de cualitat amb el lloc web avui." - -#: contrib/admin/templates/registration/logged_out.html:10 -msgid "Log in again" -msgstr "Iniciar sessió de nou" - -#: contrib/admin/templates/registration/password_change_form.html:4 -#: contrib/admin/templates/registration/password_change_form.html:6 -#: contrib/admin/templates/registration/password_change_form.html:10 -#: contrib/admin/templates/registration/password_change_done.html:4 -msgid "Password change" -msgstr "Canvi de clau" - -#: contrib/admin/templates/registration/password_change_form.html:12 -msgid "" -"Please enter your old password, for security's sake, and then enter your new " -"password twice so we can verify you typed it in correctly." -msgstr "" -"Si us plau, introdueixi la seva contrasenya antiga, per seguretat, i tot " -"seguit introdueixi la seva nova contrasenya dues vegades per verificar que " -"l'ha escrit correctament." - -#: contrib/admin/templates/registration/password_change_form.html:17 -msgid "Old password:" -msgstr "Contrasenya antiga:" - -#: contrib/admin/templates/registration/password_change_form.html:19 -msgid "New password:" -msgstr "Contrasenya nova:" - -#: contrib/admin/templates/registration/password_change_form.html:21 -msgid "Confirm password:" -msgstr "Confirmar contrasenya:" - -#: contrib/admin/templates/registration/password_change_form.html:23 -msgid "Change my password" -msgstr "Canviar la meva clau:" - -#: contrib/admin/templates/registration/password_reset_done.html:4 -#: contrib/admin/templates/registration/password_reset_form.html:4 -#: contrib/admin/templates/registration/password_reset_form.html:6 -#: contrib/admin/templates/registration/password_reset_form.html:10 -msgid "Password reset" -msgstr "Restablir contrasenya" - -#: contrib/admin/templates/registration/password_reset_done.html:6 -#: contrib/admin/templates/registration/password_reset_done.html:10 -msgid "Password reset successful" -msgstr "Contrasenya restaber-ta amb èxit" - -#: contrib/admin/templates/registration/password_reset_done.html:12 -msgid "" -"We've e-mailed a new password to the e-mail address you submitted. You " -"should be receiving it shortly." -msgstr "" -"Li hem enviat una contrasenya nova a l'adreça de correu electrònic que ens " -"ha indicat. L'hauria de rebre en breu." - -#: contrib/admin/templates/registration/password_change_done.html:6 -#: contrib/admin/templates/registration/password_change_done.html:10 -msgid "Password change successful" -msgstr "Canvi de clau exitò" - -#: contrib/admin/templates/registration/password_change_done.html:12 -msgid "Your password was changed." -msgstr "La seva clau ha estat canviada." - -#: contrib/admin/templates/registration/password_reset_email.html:2 -msgid "You're receiving this e-mail because you requested a password reset" -msgstr "" -"Està rebent aquest missatge degut a que va solicitar un restabliment de " -"contrasenya." - -#: contrib/admin/templates/registration/password_reset_email.html:3 -#, python-format -msgid "for your user account at %(site_name)s" -msgstr "del seu compte d'usuari a %(site_name)s." - -#: contrib/admin/templates/registration/password_reset_email.html:5 -#, python-format -msgid "Your new password is: %(new_password)s" -msgstr "La seva nova contrasenya és: %(new_password)s" - -#: contrib/admin/templates/registration/password_reset_email.html:7 -msgid "Feel free to change this password by going to this page:" -msgstr "Sentis lliure de canviar-la en aquesta pàgina:" - -#: contrib/admin/templates/registration/password_reset_email.html:11 -msgid "Your username, in case you've forgotten:" -msgstr "El seu nom d'usuari, en cas d'haver-lo oblidat:" - -#: contrib/admin/templates/registration/password_reset_email.html:13 -msgid "Thanks for using our site!" -msgstr "Gràcies per fer us del nostre lloc!" - -#: contrib/admin/templates/registration/password_reset_email.html:15 -#, python-format -msgid "The %(site_name)s team" -msgstr "L'equip de %(site_name)s" - -#: contrib/admin/templates/registration/password_reset_form.html:12 -msgid "" -"Forgotten your password? Enter your e-mail address below, and we'll reset " -"your password and e-mail the new one to you." -msgstr "" -"Ha oblidat la seva contrasenya? Introdueixi la seva adreça de correu " -"electrònic i crearem una nova que li enviarem per correu." - -#: contrib/admin/templates/registration/password_reset_form.html:16 -msgid "E-mail address:" -msgstr "Adreça de correu electrònic:" - -#: contrib/admin/templates/registration/password_reset_form.html:16 -msgid "Reset my password" -msgstr "Restablir la meva contrasenya" - #: contrib/admin/templates/admin_doc/bookmarklets.html:3 msgid "Bookmarklets" msgstr "'Bookmarklets'" @@ -1167,38 +1402,28 @@ msgid "" "your computer is \"internal\").</p>\n" msgstr "" "\n" -"<p class=\"help\">Per a instalar 'bookmarklets', arrosegui l'enllaç a la " -"seva barra de\n" -"marcadors, o faci click amb el botò dret en l'enllaç i afegeixi'l als " -"marcadors.\n" +"<p class=\"help\">Per a instalar 'bookmarklets', arrosegui l'enllaç a la seva barra de\n" +"marcadors, o faci click amb el botò dret en l'enllaç i afegeixi'l als marcadors.\n" "Ara pot escollir el 'bookmarklet' des de qualsevol pàgina del lloc.\n" "Observi que alguns d'aquests 'bookmarklets' precisen que estigui veient\n" "el lloc des de un ordinador senyalat com a \"intern\" (parli\n" -"amb el seu administrador de sistemes si no està segur de la condició del " -"seu).</p>\n" +"amb el seu administrador de sistemes si no està segur de la condició del seu).</p>\n" #: contrib/admin/templates/admin_doc/bookmarklets.html:19 msgid "Documentation for this page" msgstr "Documentació d'aquesta pàgina" #: contrib/admin/templates/admin_doc/bookmarklets.html:20 -msgid "" -"Jumps you from any page to the documentation for the view that generates " -"that page." -msgstr "" -"El porta des de qualsevol pàgina de la documentació a la vista que la genera." +msgid "Jumps you from any page to the documentation for the view that generates that page." +msgstr "El porta des de qualsevol pàgina de la documentació a la vista que la genera." #: contrib/admin/templates/admin_doc/bookmarklets.html:22 msgid "Show object ID" msgstr "Mostra el ID de l'objecte" #: contrib/admin/templates/admin_doc/bookmarklets.html:23 -msgid "" -"Shows the content-type and unique ID for pages that represent a single " -"object." -msgstr "" -"Mostra el 'content-type' (tipus de contingut) i el ID inequívoc de les " -"pàgines que representen un únic objecte." +msgid "Shows the content-type and unique ID for pages that represent a single object." +msgstr "Mostra el 'content-type' (tipus de contingut) i el ID inequívoc de les pàgines que representen un únic objecte." #: contrib/admin/templates/admin_doc/bookmarklets.html:25 msgid "Edit this object (current window)" @@ -1206,9 +1431,7 @@ msgstr "Editar aquest objecte (finestra actual)" #: contrib/admin/templates/admin_doc/bookmarklets.html:26 msgid "Jumps to the admin page for pages that represent a single object." -msgstr "" -"El porta a la pàgina d'administració de pàgines que representen un únic " -"objecte." +msgstr "El porta a la pàgina d'administració de pàgines que representen un únic objecte." #: contrib/admin/templates/admin_doc/bookmarklets.html:28 msgid "Edit this object (new window)" @@ -1218,424 +1441,229 @@ msgstr "Editar aquest objecte (nova finestra)" msgid "As above, but opens the admin page in a new window." msgstr "Com abans, però obre la pàgina d'administració en una nova finestra." -#: contrib/admin/views/auth.py:19 contrib/admin/views/main.py:262 -#, python-format -msgid "The %(name)s \"%(obj)s\" was added successfully." -msgstr "El/la %(name)s \"%(obj)s\".ha estat agregat/da amb èxit." - -#: contrib/admin/views/auth.py:24 contrib/admin/views/main.py:266 -#: contrib/admin/views/main.py:352 -msgid "You may edit it again below." -msgstr "Pot editar-lo de nou abaix." - -#: contrib/admin/views/auth.py:30 -msgid "Add user" -msgstr "Afegir usuari" - -#: contrib/admin/views/auth.py:57 -msgid "Password changed successfully." -msgstr "Canvi de clau exitós" - -#: contrib/admin/views/auth.py:64 -#, python-format -msgid "Change password: %s" -msgstr "Canviar clau: %s" - -#: contrib/admin/views/main.py:228 -msgid "Site administration" -msgstr "Lloc administratiu" - -#: contrib/admin/views/main.py:276 contrib/admin/views/main.py:361 -#, python-format -msgid "You may add another %s below." -msgstr "Pot afegir un altre %s a baix." - -#: contrib/admin/views/main.py:294 -#, python-format -msgid "Add %s" -msgstr "Afegir %s" - -#: contrib/admin/views/main.py:340 -#, python-format -msgid "Added %s." -msgstr "Agregat %s." - -#: contrib/admin/views/main.py:340 contrib/admin/views/main.py:342 -#: contrib/admin/views/main.py:344 db/models/manipulators.py:308 -msgid "and" -msgstr "i" - -#: contrib/admin/views/main.py:342 -#, python-format -msgid "Changed %s." -msgstr "Modificat %s." - -#: contrib/admin/views/main.py:344 -#, python-format -msgid "Deleted %s." -msgstr "Eliminat %s." - -#: contrib/admin/views/main.py:347 -msgid "No fields changed." -msgstr "Cap camp canviat." - -#: contrib/admin/views/main.py:350 -#, python-format -msgid "The %(name)s \"%(obj)s\" was changed successfully." -msgstr "S'ha modificat amb èxist el/la %(name)s \"%(obj)s." - -#: contrib/admin/views/main.py:358 -#, python-format -msgid "" -"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below." -msgstr "" -"S'ha agregat amb èxit el/la %(name)s \"%(obj)s\". Pot editar-lo de nou abaix." - -#: contrib/admin/views/main.py:396 -#, python-format -msgid "Change %s" -msgstr "Modificar %s" - -#: contrib/admin/views/main.py:481 -#, python-format -msgid "One or more %(fieldname)s in %(name)s: %(obj)s" -msgstr "Un o més %(fieldname)s en %(name)s: %(obj)s" - -#: contrib/admin/views/main.py:486 -#, python-format -msgid "One or more %(fieldname)s in %(name)s:" -msgstr "Un o més %(fieldname)s en %(name)s:" - -#: contrib/admin/views/main.py:518 -#, python-format -msgid "The %(name)s \"%(obj)s\" was deleted successfully." -msgstr "El/la %(name)s \"%(obj)s\".ha estat eliminat amb èxit." - -#: contrib/admin/views/main.py:521 -msgid "Are you sure?" -msgstr "Està segur?" - -#: contrib/admin/views/main.py:543 -#, python-format -msgid "Change history: %s" -msgstr "Modificar històric: %s" - -#: contrib/admin/views/main.py:577 -#, python-format -msgid "Select %s" -msgstr "Seleccioni %s" - -#: contrib/admin/views/main.py:577 -#, python-format -msgid "Select %s to change" -msgstr "Seleccioni %s per modificar" - -#: contrib/admin/views/main.py:772 -msgid "Database error" -msgstr "Error de/en la base de dades" +#: contrib/admin/templates/widget/date_time.html:3 +msgid "Date:" +msgstr "Data:" -#: contrib/admin/views/doc.py:46 contrib/admin/views/doc.py:48 -#: contrib/admin/views/doc.py:50 -msgid "tag:" -msgstr "etiqueta:" +#: contrib/admin/templates/widget/date_time.html:4 +msgid "Time:" +msgstr "Hora:" -#: contrib/admin/views/doc.py:77 contrib/admin/views/doc.py:79 -#: contrib/admin/views/doc.py:81 -msgid "filter:" -msgstr "filtre:" +#: contrib/admin/templates/widget/file.html:2 +msgid "Currently:" +msgstr "Actualment:" -#: contrib/admin/views/doc.py:135 contrib/admin/views/doc.py:137 -#: contrib/admin/views/doc.py:139 -msgid "view:" -msgstr "vista:" +#: contrib/admin/templates/widget/file.html:3 +msgid "Change:" +msgstr "Modificar:" -#: contrib/admin/views/doc.py:164 -#, python-format -msgid "App %r not found" -msgstr "La aplicació %r no s'ha pogut trobar" +#: contrib/admin/templates/registration/password_reset_form.html:4 +#: contrib/admin/templates/registration/password_reset_form.html:6 +#: contrib/admin/templates/registration/password_reset_form.html:10 +#: contrib/admin/templates/registration/password_reset_done.html:4 +msgid "Password reset" +msgstr "Restablir contrasenya" -#: contrib/admin/views/doc.py:171 -#, python-format -msgid "Model %(name)r not found in app %(label)r" -msgstr "El model %(name)r no s'ha trobat en la aplicació %(label)r" +#: contrib/admin/templates/registration/password_reset_form.html:12 +msgid "Forgotten your password? Enter your e-mail address below, and we'll reset your password and e-mail the new one to you." +msgstr "Ha oblidat la seva contrasenya? Introdueixi la seva adreça de correu electrònic i crearem una nova que li enviarem per correu." -#: contrib/admin/views/doc.py:183 -#, python-format -msgid "the related `%(label)s.%(type)s` object" -msgstr "el objecte relacionat `%(label)s.%(type)s`" +#: contrib/admin/templates/registration/password_reset_form.html:16 +msgid "E-mail address:" +msgstr "Adreça de correu electrònic:" -#: contrib/admin/views/doc.py:183 contrib/admin/views/doc.py:205 -#: contrib/admin/views/doc.py:219 contrib/admin/views/doc.py:224 -msgid "model:" -msgstr "model:" +#: contrib/admin/templates/registration/password_reset_form.html:16 +msgid "Reset my password" +msgstr "Restablir la meva contrasenya" -#: contrib/admin/views/doc.py:214 -#, python-format -msgid "related `%(label)s.%(name)s` objects" -msgstr "objectes relacionats `%(label)s.%(name)s`" +#: contrib/admin/templates/registration/password_reset_email.html:2 +msgid "You're receiving this e-mail because you requested a password reset" +msgstr "Està rebent aquest missatge degut a que va solicitar un restabliment de contrasenya." -#: contrib/admin/views/doc.py:219 +#: contrib/admin/templates/registration/password_reset_email.html:3 #, python-format -msgid "all %s" -msgstr "tots %s" +msgid "for your user account at %(site_name)s" +msgstr "del seu compte d'usuari a %(site_name)s." -#: contrib/admin/views/doc.py:224 +#: contrib/admin/templates/registration/password_reset_email.html:5 #, python-format -msgid "number of %s" -msgstr "nombre de %s" +msgid "Your new password is: %(new_password)s" +msgstr "La seva nova contrasenya és: %(new_password)s" -#: contrib/admin/views/doc.py:229 -#, python-format -msgid "Fields on %s objects" -msgstr "Camps en objectes %s" +#: contrib/admin/templates/registration/password_reset_email.html:7 +msgid "Feel free to change this password by going to this page:" +msgstr "Sentis lliure de canviar-la en aquesta pàgina:" -#: contrib/admin/views/doc.py:291 contrib/admin/views/doc.py:302 -#: contrib/admin/views/doc.py:304 contrib/admin/views/doc.py:310 -#: contrib/admin/views/doc.py:311 contrib/admin/views/doc.py:313 -msgid "Integer" -msgstr "Enter" +#: contrib/admin/templates/registration/password_reset_email.html:11 +msgid "Your username, in case you've forgotten:" +msgstr "El seu nom d'usuari, en cas d'haver-lo oblidat:" -#: contrib/admin/views/doc.py:292 -msgid "Boolean (Either True or False)" -msgstr "Booleà (Verdader o Fals)" +#: contrib/admin/templates/registration/password_reset_email.html:13 +msgid "Thanks for using our site!" +msgstr "Gràcies per fer us del nostre lloc!" -#: contrib/admin/views/doc.py:293 contrib/admin/views/doc.py:312 +#: contrib/admin/templates/registration/password_reset_email.html:15 #, python-format -msgid "String (up to %(maxlength)s)" -msgstr "Cadena (fins a %(maxlength)s)" - -#: contrib/admin/views/doc.py:294 -msgid "Comma-separated integers" -msgstr "Enters separats per comes" - -#: contrib/admin/views/doc.py:295 -msgid "Date (without time)" -msgstr "Data (sense hora)" - -#: contrib/admin/views/doc.py:296 -msgid "Date (with time)" -msgstr "Data (amb hora)" - -#: contrib/admin/views/doc.py:297 -msgid "Decimal number" -msgstr "Número decimal" - -#: contrib/admin/views/doc.py:298 -msgid "E-mail address" -msgstr "Adreça de correu electrònic" - -#: contrib/admin/views/doc.py:299 contrib/admin/views/doc.py:300 -#: contrib/admin/views/doc.py:303 -msgid "File path" -msgstr "Ruta del fitxer" - -#: contrib/admin/views/doc.py:301 -msgid "Floating point number" -msgstr "Número amb punt de coma flotant" - -#: contrib/admin/views/doc.py:307 -msgid "Boolean (Either True, False or None)" -msgstr "Booleà (Verdader, Fals o 'None' (cap))" - -#: contrib/admin/views/doc.py:308 -msgid "Relation to parent model" -msgstr "Relació amb el model pare" - -#: contrib/admin/views/doc.py:309 -msgid "Phone number" -msgstr "Número de telèfon" +msgid "The %(site_name)s team" +msgstr "L'equip de %(site_name)s" -#: contrib/admin/views/doc.py:314 -msgid "Text" -msgstr "Texte" +#: contrib/admin/templates/registration/logged_out.html:8 +msgid "Thanks for spending some quality time with the Web site today." +msgstr "Gràcies per emprar algun temps de cualitat amb el lloc web avui." -#: contrib/admin/views/doc.py:315 -msgid "Time" -msgstr "Hora" +#: contrib/admin/templates/registration/logged_out.html:10 +msgid "Log in again" +msgstr "Iniciar sessió de nou" -#: contrib/admin/views/doc.py:316 contrib/flatpages/models.py:7 -msgid "URL" -msgstr "URL" +#: contrib/admin/templates/registration/password_reset_done.html:6 +#: contrib/admin/templates/registration/password_reset_done.html:10 +msgid "Password reset successful" +msgstr "Contrasenya restaber-ta amb èxit" -#: contrib/admin/views/doc.py:317 -msgid "U.S. state (two uppercase letters)" -msgstr "Estat dels E.U.A. (dos lletres majúscules)" +#: contrib/admin/templates/registration/password_reset_done.html:12 +msgid "We've e-mailed a new password to the e-mail address you submitted. You should be receiving it shortly." +msgstr "Li hem enviat una contrasenya nova a l'adreça de correu electrònic que ens ha indicat. L'hauria de rebre en breu." -#: contrib/admin/views/doc.py:318 -msgid "XML text" -msgstr "Texte XML" +#: contrib/admin/templates/registration/password_change_form.html:4 +#: contrib/admin/templates/registration/password_change_form.html:6 +#: contrib/admin/templates/registration/password_change_form.html:10 +#: contrib/admin/templates/registration/password_change_done.html:4 +msgid "Password change" +msgstr "Canvi de clau" -#: contrib/admin/views/doc.py:344 -#, python-format -msgid "%s does not appear to be a urlpattern object" -msgstr "%s no sembla ser un objecte 'urlpattern'" +#: contrib/admin/templates/registration/password_change_form.html:12 +msgid "Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly." +msgstr "Si us plau, introdueixi la seva contrasenya antiga, per seguretat, i tot seguit introdueixi la seva nova contrasenya dues vegades per verificar que l'ha escrit correctament." -#: contrib/admin/views/decorators.py:10 contrib/auth/forms.py:60 -msgid "" -"Please enter a correct username and password. Note that both fields are case-" -"sensitive." -msgstr "" -"Si us plau, introdueixi un nom d'usuari i contrasenya vàlids. Tingui en " -"compte que tots dos camps son sensibles a majúscules i minúscules." +#: contrib/admin/templates/registration/password_change_form.html:17 +msgid "Old password:" +msgstr "Contrasenya antiga:" -#: contrib/admin/views/decorators.py:62 -msgid "" -"Please log in again, because your session has expired. Don't worry: Your " -"submission has been saved." -msgstr "" -"Si us plau, identifiquis de nou doncs la seva sessió ha expirat. No es " -"preocupi, el seu enviament està emmagatzemat." +#: contrib/admin/templates/registration/password_change_form.html:19 +msgid "New password:" +msgstr "Contrasenya nova:" -#: contrib/admin/views/decorators.py:69 -msgid "" -"Looks like your browser isn't configured to accept cookies. Please enable " -"cookies, reload this page, and try again." -msgstr "" -"Sembla ser que el seu navegador no està configurat per acceptar " -"'cookies' (galetes). Si us plau, habiliti les 'cookies', recarregui aquesta " -"pàgina i provi-ho de nou. " +#: contrib/admin/templates/registration/password_change_form.html:21 +msgid "Confirm password:" +msgstr "Confirmar contrasenya:" -#: contrib/admin/views/decorators.py:83 -msgid "Usernames cannot contain the '@' character." -msgstr "Els noms d'usuari no poden contenir el caracter '@'." +#: contrib/admin/templates/registration/password_change_form.html:23 +msgid "Change my password" +msgstr "Canviar la meva clau:" -#: contrib/admin/views/decorators.py:85 -#, python-format -msgid "Your e-mail address is not your username. Try '%s' instead." -msgstr "" -"La seva adreça de correu no és el seu nom d'usuari. Provi '%s' en tot cas." +#: contrib/admin/templates/registration/password_change_done.html:6 +#: contrib/admin/templates/registration/password_change_done.html:10 +msgid "Password change successful" +msgstr "Canvi de clau exitò" -#: contrib/sessions/models.py:68 -msgid "session key" -msgstr "clau de la sessió" +#: contrib/admin/templates/registration/password_change_done.html:12 +msgid "Your password was changed." +msgstr "La seva clau ha estat canviada." -#: contrib/sessions/models.py:69 -msgid "session data" -msgstr "dades de la sessió" +#: contrib/sites/models.py:33 +msgid "domain name" +msgstr "nom del domini" -#: contrib/sessions/models.py:70 -msgid "expire date" -msgstr "data de caducitat" +#: contrib/sites/models.py:34 +msgid "display name" +msgstr "nom per mostrar" -#: contrib/sessions/models.py:74 -msgid "session" -msgstr "sessió" +#: contrib/sites/models.py:38 +msgid "site" +msgstr "lloc" -#: contrib/sessions/models.py:75 -msgid "sessions" -msgstr "sessions" +#: contrib/sites/models.py:39 +msgid "sites" +msgstr "llocs" -#: contrib/humanize/templatetags/humanize.py:17 +#: contrib/humanize/templatetags/humanize.py:20 msgid "th" msgstr "rt" -#: contrib/humanize/templatetags/humanize.py:17 +#: contrib/humanize/templatetags/humanize.py:20 msgid "st" msgstr "r" -#: contrib/humanize/templatetags/humanize.py:17 +#: contrib/humanize/templatetags/humanize.py:20 msgid "nd" msgstr "n" -#: contrib/humanize/templatetags/humanize.py:17 +#: contrib/humanize/templatetags/humanize.py:20 msgid "rd" msgstr "r" -#: contrib/humanize/templatetags/humanize.py:47 +#: contrib/humanize/templatetags/humanize.py:50 #, python-format msgid "%(value).1f million" msgid_plural "%(value).1f million" msgstr[0] "%(value).1f milió" msgstr[1] "%(value).1f milions" -#: contrib/humanize/templatetags/humanize.py:50 +#: contrib/humanize/templatetags/humanize.py:53 #, python-format msgid "%(value).1f billion" msgid_plural "%(value).1f billion" msgstr[0] "%(value).1f bilió" msgstr[1] "%(value).1f bilions" -#: contrib/humanize/templatetags/humanize.py:53 +#: contrib/humanize/templatetags/humanize.py:56 #, python-format msgid "%(value).1f trillion" msgid_plural "%(value).1f trillion" msgstr[0] "%(value).1f trilió" msgstr[1] "%(value).1f trilions" -#: contrib/humanize/templatetags/humanize.py:68 +#: contrib/humanize/templatetags/humanize.py:71 msgid "one" msgstr "un" -#: contrib/humanize/templatetags/humanize.py:68 +#: contrib/humanize/templatetags/humanize.py:71 msgid "two" msgstr "dos" -#: contrib/humanize/templatetags/humanize.py:68 +#: contrib/humanize/templatetags/humanize.py:71 msgid "three" msgstr "tres" -#: contrib/humanize/templatetags/humanize.py:68 +#: contrib/humanize/templatetags/humanize.py:71 msgid "four" msgstr "cuatre" -#: contrib/humanize/templatetags/humanize.py:68 +#: contrib/humanize/templatetags/humanize.py:71 msgid "five" msgstr "cinc" -#: contrib/humanize/templatetags/humanize.py:68 +#: contrib/humanize/templatetags/humanize.py:71 msgid "six" msgstr "sis" -#: contrib/humanize/templatetags/humanize.py:68 +#: contrib/humanize/templatetags/humanize.py:71 msgid "seven" msgstr "set" -#: contrib/humanize/templatetags/humanize.py:68 +#: contrib/humanize/templatetags/humanize.py:71 msgid "eight" msgstr "vuit" -#: contrib/humanize/templatetags/humanize.py:68 +#: contrib/humanize/templatetags/humanize.py:71 msgid "nine" msgstr "nou" -#: contrib/redirects/models.py:7 -msgid "redirect from" -msgstr "redreçar des de" - -#: contrib/redirects/models.py:8 -msgid "" -"This should be an absolute path, excluding the domain name. Example: '/" -"events/search/'." -msgstr "" -"Aquesta ruta hauria de ser el camí absolut, excloent-ne el nom del domini. " -"Exemple '/events/search/'." - -#: contrib/redirects/models.py:9 -msgid "redirect to" -msgstr "redreçar a" +#: contrib/humanize/templatetags/humanize.py:90 +msgid "today" +msgstr "avui" -#: contrib/redirects/models.py:10 -msgid "" -"This can be either an absolute path (as above) or a full URL starting with " -"'http://'." -msgstr "" -"Això pot ser bé una ruta absoluta (com abans) o una URL completa que comenci " -"per http:// ." - -#: contrib/redirects/models.py:13 -msgid "redirect" -msgstr "redreçament" +#: contrib/humanize/templatetags/humanize.py:92 +msgid "tomorrow" +msgstr "demà" -#: contrib/redirects/models.py:14 -msgid "redirects" -msgstr "redreçaments" +#: contrib/humanize/templatetags/humanize.py:94 +msgid "yesterday" +msgstr "ahir" #: contrib/flatpages/models.py:8 -msgid "" -"Example: '/about/contact/'. Make sure to have leading and trailing slashes." -msgstr "" -"Exemple: '/about/contact/'. Asseguri's de posar les barres al principi i al " -"final." +msgid "Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "Exemple: '/about/contact/'. Asseguri's de posar les barres al principi i al final." #: contrib/flatpages/models.py:9 msgid "title" @@ -1654,12 +1682,8 @@ msgid "template name" msgstr "nom de la plantilla" #: contrib/flatpages/models.py:13 -msgid "" -"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " -"will use 'flatpages/default.html'." -msgstr "" -"Exemple: 'flatpages/contact_page.html'. Si no el proporciona, el sistema " -"utilitzarà 'flatpages/defaula.htmlt'." +msgid "Example: 'flatpages/contact_page.html'. If this isn't provided, the system will use 'flatpages/default.html'." +msgstr "Exemple: 'flatpages/contact_page.html'. Si no el proporciona, el sistema utilitzarà 'flatpages/defaula.htmlt'." #: contrib/flatpages/models.py:14 msgid "registration required" @@ -1677,218 +1701,378 @@ msgstr "pàgina estàtica" msgid "flat pages" msgstr "pàgines estàtiques" -#: contrib/sites/models.py:10 -msgid "domain name" -msgstr "nom del domini" +#: contrib/redirects/models.py:7 +msgid "redirect from" +msgstr "redreçar des de" -#: contrib/sites/models.py:11 -msgid "display name" -msgstr "nom per mostrar" +#: contrib/redirects/models.py:8 +msgid "This should be an absolute path, excluding the domain name. Example: '/events/search/'." +msgstr "Aquesta ruta hauria de ser el camí absolut, excloent-ne el nom del domini. Exemple '/events/search/'." -#: contrib/sites/models.py:15 -msgid "site" -msgstr "lloc" +#: contrib/redirects/models.py:9 +msgid "redirect to" +msgstr "redreçar a" -#: contrib/sites/models.py:16 -msgid "sites" -msgstr "llocs" +#: contrib/redirects/models.py:10 +msgid "This can be either an absolute path (as above) or a full URL starting with 'http://'." +msgstr "Això pot ser bé una ruta absoluta (com abans) o una URL completa que comenci per http:// ." -#: contrib/auth/views.py:40 -msgid "Logged out" -msgstr "Sessió finalitzada" +#: contrib/redirects/models.py:13 +msgid "redirect" +msgstr "redreçament" -#: contrib/auth/models.py:49 contrib/auth/models.py:69 -msgid "name" -msgstr "nom" +#: contrib/redirects/models.py:14 +msgid "redirects" +msgstr "redreçaments" -#: contrib/auth/models.py:51 -msgid "codename" -msgstr "nom en clau" +#: contrib/comments/models.py:67 +#: contrib/comments/models.py:169 +msgid "object ID" +msgstr "ID de l'objecte" -#: contrib/auth/models.py:54 -msgid "permission" -msgstr "permís" +#: contrib/comments/models.py:68 +msgid "headline" +msgstr "encapçalament" -#: contrib/auth/models.py:55 contrib/auth/models.py:70 -msgid "permissions" -msgstr "permissos" +#: contrib/comments/models.py:69 +#: contrib/comments/models.py:90 +#: contrib/comments/models.py:170 +msgid "comment" +msgstr "comentari" -#: contrib/auth/models.py:73 -msgid "group" -msgstr "grup" +#: contrib/comments/models.py:70 +msgid "rating #1" +msgstr "qualificació #1" -#: contrib/auth/models.py:74 contrib/auth/models.py:114 -msgid "groups" -msgstr "grups" +#: contrib/comments/models.py:71 +msgid "rating #2" +msgstr "qualificació #2" -#: contrib/auth/models.py:104 -msgid "username" -msgstr "nom d'usuari" +#: contrib/comments/models.py:72 +msgid "rating #3" +msgstr "qualificació #3" -#: contrib/auth/models.py:104 -msgid "" -"Required. 30 characters or fewer. Alphanumeric characters only (letters, " -"digits and underscores)." -msgstr "" -"Requerit. 30 o menys caracters. Només caracters alfanumèrics (lletres, " -"dígits i guions baixos)." +#: contrib/comments/models.py:73 +msgid "rating #4" +msgstr "qualificació #4" -#: contrib/auth/models.py:105 -msgid "first name" -msgstr "nom propi" +#: contrib/comments/models.py:74 +msgid "rating #5" +msgstr "qualificació #5" -#: contrib/auth/models.py:106 -msgid "last name" -msgstr "cognoms" +#: contrib/comments/models.py:75 +msgid "rating #6" +msgstr "qualificació #6" -#: contrib/auth/models.py:107 -msgid "e-mail address" -msgstr "adreça de correu electrònic" +#: contrib/comments/models.py:76 +msgid "rating #7" +msgstr "qualificació #7" -#: contrib/auth/models.py:108 -msgid "password" -msgstr "contrasenya" +#: contrib/comments/models.py:77 +msgid "rating #8" +msgstr "qualificació #8" -#: contrib/auth/models.py:108 -msgid "" -"Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change " -"password form</a>." -msgstr "" -"Utilitzi '[algo]$[salt]$[hexdigest]' o el <a href=\"password/\">formulari de " -"canvi de contrasenya</a>." +#: contrib/comments/models.py:82 +msgid "is valid rating" +msgstr "és qualificació vàlida" -#: contrib/auth/models.py:109 -msgid "staff status" -msgstr "és membre del personal" +#: contrib/comments/models.py:83 +#: contrib/comments/models.py:172 +msgid "date/time submitted" +msgstr "data/hora d'enviament" -#: contrib/auth/models.py:109 -msgid "Designates whether the user can log into this admin site." -msgstr "Indica si l'usuari pot entrar en el lloc administratiu." +#: contrib/comments/models.py:84 +#: contrib/comments/models.py:173 +msgid "is public" +msgstr "és públic" -#: contrib/auth/models.py:110 -msgid "active" -msgstr "actiu" +#: contrib/comments/models.py:86 +msgid "is removed" +msgstr "està eliminat" -#: contrib/auth/models.py:110 -msgid "" -"Designates whether this user can log into the Django admin. Unselect this " -"instead of deleting accounts." -msgstr "" -"Designa si aquest usuari pot iniciar sessió a la interfície administrativa " -"Djano. Deselecciona-ho enlloc de esborrar comptes d'usuari." +#: contrib/comments/models.py:86 +msgid "Check this box if the comment is inappropriate. A \"This comment has been removed\" message will be displayed instead." +msgstr "Marqui aquesta caixa si el comentari no és apropiat. En lloc seu es mostrarà \"Aquest comentari ha estat eliminat\" " -#: contrib/auth/models.py:111 -msgid "superuser status" -msgstr "estat de superusuari" +#: contrib/comments/models.py:91 +msgid "comments" +msgstr "comentaris" -#: contrib/auth/models.py:111 +#: contrib/comments/models.py:134 +#: contrib/comments/models.py:213 +msgid "Content object" +msgstr "Objecte Contingut" + +#: contrib/comments/models.py:162 +#, python-format msgid "" -"Designates that this user has all permissions without explicitly assigning " -"them." +"Posted by %(user)s at %(date)s\n" +"\n" +"%(comment)s\n" +"\n" +"http://%(domain)s%(url)s" msgstr "" -"Designa que aquest usuari té tots els permisos sense assignar-los " -"explícitament." +"Enviat per %(user)s el %(date)s\n" +"\n" +"%(comment)s\n" +"\n" +"http://%(domain)s%(url)s" -#: contrib/auth/models.py:112 -msgid "last login" -msgstr "últim inici de sessió" +#: contrib/comments/models.py:171 +msgid "person's name" +msgstr "nom de la persona" -#: contrib/auth/models.py:113 -msgid "date joined" -msgstr "data de creació" +#: contrib/comments/models.py:174 +msgid "ip address" +msgstr "adreça ip" -#: contrib/auth/models.py:115 +#: contrib/comments/models.py:176 +msgid "approved by staff" +msgstr "aprovat per el \"staff\"" + +#: contrib/comments/models.py:179 +msgid "free comment" +msgstr "comentari lliure" + +#: contrib/comments/models.py:180 +msgid "free comments" +msgstr "comentaris lliures" + +#: contrib/comments/models.py:239 +msgid "score" +msgstr "puntuació" + +#: contrib/comments/models.py:240 +msgid "score date" +msgstr "data de la puntuació" + +#: contrib/comments/models.py:243 +msgid "karma score" +msgstr "puntuació de karma" + +#: contrib/comments/models.py:244 +msgid "karma scores" +msgstr "punts de karma" + +#: contrib/comments/models.py:248 +#, python-format +msgid "%(score)d rating by %(user)s" +msgstr "%(score)d punt/s per %(user)s" + +#: contrib/comments/models.py:264 +#, python-format msgid "" -"In addition to the permissions manually assigned, this user will also get " -"all permissions granted to each group he/she is in." +"This comment was flagged by %(user)s:\n" +"\n" +"%(text)s" msgstr "" -"Junt amb els permissos asignats manualment, aquest usuari tindrà, també, els " -"permissos dels grups dels que sigui membre." +"Aquest comentari va ser marcat per %(user)s:\n" +"\n" +"%(text)s" -#: contrib/auth/models.py:116 -msgid "user permissions" -msgstr "permissos de l'usuari" +#: contrib/comments/models.py:271 +msgid "flag date" +msgstr "data de la marca" -#: contrib/auth/models.py:120 -msgid "user" -msgstr "usuari" +#: contrib/comments/models.py:274 +msgid "user flag" +msgstr "marca d'usuari" -#: contrib/auth/models.py:121 -msgid "users" -msgstr "usuaris" +#: contrib/comments/models.py:275 +msgid "user flags" +msgstr "marques d'usuari" -#: contrib/auth/models.py:127 -msgid "Personal info" -msgstr "Informaciò personal" +#: contrib/comments/models.py:279 +#, python-format +msgid "Flag by %r" +msgstr "Marca de %r" -#: contrib/auth/models.py:128 -msgid "Permissions" -msgstr "permissos" +#: contrib/comments/models.py:284 +msgid "deletion date" +msgstr "data d'eliminació" -#: contrib/auth/models.py:129 -msgid "Important dates" -msgstr "Dates importants" +#: contrib/comments/models.py:286 +msgid "moderator deletion" +msgstr "eliminació del moderador" -#: contrib/auth/models.py:130 -msgid "Groups" -msgstr "Grups" +#: contrib/comments/models.py:287 +msgid "moderator deletions" +msgstr "eliminacions del moderador" -#: contrib/auth/models.py:273 -msgid "message" -msgstr "missatge" +#: contrib/comments/models.py:291 +#, python-format +msgid "Moderator deletion by %r" +msgstr "eliminació del moderador per %r" -#: contrib/auth/models.py:286 -msgid "AnonymousUser" -msgstr "AnonymousUser" +#: contrib/comments/views/karma.py:20 +msgid "Anonymous users cannot vote" +msgstr "Els usuaris anònims no poden votar" -#: contrib/auth/forms.py:17 contrib/auth/forms.py:138 -msgid "The two password fields didn't match." -msgstr "Els dos camps de contrasenya no coincideixen." +#: contrib/comments/views/karma.py:24 +msgid "Invalid comment ID" +msgstr "ID del comentari invàlid" -#: contrib/auth/forms.py:25 -msgid "A user with that username already exists." -msgstr "Ja existeix un usuari amb aquest nom." +#: contrib/comments/views/karma.py:26 +msgid "No voting for yourself" +msgstr "No pots votar-te a tu mateix" -#: contrib/auth/forms.py:53 -msgid "" -"Your Web browser doesn't appear to have cookies enabled. Cookies are " -"required for logging in." -msgstr "" -"El seu navegador no sembla tenir les 'cookies' (galetes) activades. Aquestes " -"són necessàries per iniciar la sessió." +#: contrib/comments/views/comments.py:28 +msgid "This rating is required because you've entered at least one other rating." +msgstr "Es precisa aquesta puntuació perquè has introduït almenys un altre." -#: contrib/auth/forms.py:62 -msgid "This account is inactive." -msgstr "Aquest compte està inactiu" +#: contrib/comments/views/comments.py:112 +#, python-format +msgid "" +"This comment was posted by a user who has posted fewer than %(count)s comment:\n" +"\n" +"%(text)s" +msgid_plural "" +"This comment was posted by a user who has posted fewer than %(count)s comments:\n" +"\n" +"%(text)s" +msgstr[0] "" +"Aquest comentari ha estat publicat per un usuari que ha publicat menys de %(count)s comentari:\n" +"\n" +"%(text)s" +msgstr[1] "" +"Aquest comentari ha estat publicat per un usuari que ha publicat menys de %(count)s comentaris:\n" +"\n" +"%(text)s" -#: contrib/auth/forms.py:84 +#: contrib/comments/views/comments.py:117 +#, python-format msgid "" -"That e-mail address doesn't have an associated user account. Are you sure " -"you've registered?" +"This comment was posted by a sketchy user:\n" +"\n" +"%(text)s" msgstr "" -"Aquesta adreça de correu no té associada cap compte d'usuari. Està segur de " -"que s'ha registrat?" +"Aquest comentari va ser publicat per un usuari incomplet\n" +"\n" +"%(text)s" -#: contrib/auth/forms.py:117 -msgid "The two 'new password' fields didn't match." -msgstr "Els dos camps de nova contrasenya no coincideixen." +#: contrib/comments/views/comments.py:189 +#: contrib/comments/views/comments.py:281 +msgid "Only POSTs are allowed" +msgstr "Només s'admed POST" -#: contrib/auth/forms.py:124 -msgid "Your old password was entered incorrectly. Please enter it again." -msgstr "" -"La seva antiga contrasenya no és correcte. Si el plau, introdueixi-la de nou." +#: contrib/comments/views/comments.py:193 +#: contrib/comments/views/comments.py:285 +msgid "One or more of the required fields wasn't submitted" +msgstr "Un o més dels caps requerits no ha estat sotmès" -#: contrib/contenttypes/models.py:36 -msgid "python model class name" -msgstr "nom de la classe del model en python" +#: contrib/comments/views/comments.py:197 +#: contrib/comments/views/comments.py:287 +msgid "Somebody tampered with the comment form (security violation)" +msgstr "Algú està jugant amb el formulari de comentaris (violació de seguretat)" -#: contrib/contenttypes/models.py:39 -msgid "content type" -msgstr "tipus de contingut" +#: contrib/comments/views/comments.py:207 +#: contrib/comments/views/comments.py:293 +msgid "The comment form had an invalid 'target' parameter -- the object ID was invalid" +msgstr "El formulari de comentaris tenia un paràmetre 'target' invàlid -- el ID del objecte era invàlid" -#: contrib/contenttypes/models.py:40 -msgid "content types" -msgstr "tipus de continguts" +#: contrib/comments/views/comments.py:258 +#: contrib/comments/views/comments.py:322 +msgid "The comment form didn't provide either 'preview' or 'post'" +msgstr "El formulari del comentari no ha proveït ni 'previsualitzar' ni 'enviar'" + +#: contrib/comments/templates/comments/form.html:8 +msgid "Forgotten your password?" +msgstr "Contrasenya oblidada?" + +#: contrib/comments/templates/comments/form.html:12 +msgid "Ratings" +msgstr "Qualificacions" + +#: contrib/comments/templates/comments/form.html:12 +#: contrib/comments/templates/comments/form.html:23 +msgid "Required" +msgstr "Requerit" + +#: contrib/comments/templates/comments/form.html:12 +#: contrib/comments/templates/comments/form.html:23 +msgid "Optional" +msgstr "Opcional" + +#: contrib/comments/templates/comments/form.html:23 +msgid "Post a photo" +msgstr "Enviar una fotografia" + +#: contrib/comments/templates/comments/form.html:28 +#: contrib/comments/templates/comments/freeform.html:5 +msgid "Comment:" +msgstr "Comentari:" + +#: contrib/comments/templates/comments/form.html:35 +#: contrib/comments/templates/comments/freeform.html:10 +msgid "Preview comment" +msgstr "Previsualitzar comentari" + +#: contrib/comments/templates/comments/freeform.html:4 +msgid "Your name:" +msgstr "El seu nom:" + +#: contrib/localflavor/ar/forms.py:30 +#: contrib/localflavor/ar/forms.py:38 +msgid "Enter a postal code in the format NNNN or ANNNNAAA." +msgstr "Introdueixi un codi postal en el format NNNN or ANNNNAAA." + +#: contrib/localflavor/ar/forms.py:61 +#: contrib/localflavor/br/forms.py:103 +msgid "This field requires only numbers." +msgstr "Aquest camps requereix només números." + +#: contrib/localflavor/ar/forms.py:64 +msgid "This field requires 7 or 8 digits." +msgstr "Aquest camp requereix 7 o 8 dígits." + +#: contrib/localflavor/ar/forms.py:75 +msgid "Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format." +msgstr "Introdueixi un número CUIT vàlid en el format XX-XXXXXXXX-X o XXXXXXXXXXXX." + +#: contrib/localflavor/ar/forms.py:88 +msgid "Invalid CUIT." +msgstr "Invàlid CUIT." + +#: contrib/localflavor/au/forms.py:18 +msgid "Enter a 4 digit post code." +msgstr "Introdueixi un codi postal de 4 dígits." + +#: contrib/localflavor/br/forms.py:23 +msgid "Enter a zip code in the format XXXXX-XXX." +msgstr "Introdueixi un codi zip en el format XXXXX-XXX." + +#: contrib/localflavor/br/forms.py:35 +msgid "Phone numbers must be in XX-XXXX-XXXX format." +msgstr "El número de telèfon ha de ser en el format XX-XXXX-XXXX." + +#: contrib/localflavor/br/forms.py:68 +msgid "Select a valid brazilian state. That state is not one of the available states." +msgstr "Seleccioni un estat brasiler vàlid. Aquest estat no és un dels estats disponibles." + +#: contrib/localflavor/br/forms.py:105 +msgid "This field requires at most 11 digits or 14 characters." +msgstr "Aquest camp requereix com a màxim 11 dígits o 14 caracters." + +#: contrib/localflavor/br/forms.py:115 +msgid "Invalid CPF number." +msgstr "Número CPF invàlid." + +#: contrib/localflavor/br/forms.py:137 +msgid "This field requires at least 14 digits" +msgstr "Aquest camp requereix almenys 14 dígits." + +#: contrib/localflavor/br/forms.py:147 +msgid "Invalid CNPJ number." +msgstr "Número CNPJ invàlid." + +#: contrib/localflavor/ch/forms.py:18 +#: contrib/localflavor/no/forms.py:14 +msgid "Enter a zip code in the format XXXX." +msgstr "Introdueixi un codi zip en el format XXXX." + +#: contrib/localflavor/ch/forms.py:90 +msgid "Enter a valid Swiss identity or passport card number in X1234567<0 or 1234567890 format." +msgstr "Introdueixi un número de identificació o de passaport Suïssos en els formats 1234567890 o X1234567<0." #: contrib/localflavor/ch/ch_states.py:5 msgid "Aargau" @@ -1994,66 +2178,23 @@ msgstr "Zug" msgid "Zurich" msgstr "Zurich" -#: contrib/localflavor/ch/forms.py:18 contrib/localflavor/no/forms.py:15 -msgid "Enter a zip code in the format XXXX." -msgstr "Introdueixi un codi zip en el format XXXX." - -#: contrib/localflavor/ch/forms.py:90 -msgid "" -"Enter a valid Swiss identity or passport card number in X1234567<0 or " -"1234567890 format." -msgstr "" -"Introdueixi un número de identificació o de passaport Suïssos en els formats " -"1234567890 o X1234567<0." - -#: contrib/localflavor/it/forms.py:16 -msgid "Enter a valid zip code." -msgstr "Introdueixi un codi zip vàlid." - -#: contrib/localflavor/it/forms.py:41 -msgid "Enter a valid Social Security number." -msgstr "Introdueixi un número valid de la Seguretat Social." - -#: contrib/localflavor/it/forms.py:68 -msgid "Enter a valid VAT number." -msgstr "Introdueixi un número de IVA (VAT) vàlid." - -#: contrib/localflavor/uk/forms.py:18 -msgid "Enter a postcode. A space is required between the two postcode parts." -msgstr "" -"Introdueixi un codi postal. És necessari un espai entre les dues parts del " -"codi postal." - -#: contrib/localflavor/us/forms.py:18 -msgid "Enter a zip code in the format XXXXX or XXXXX-XXXX." -msgstr "Introdueixi un codi zip en el format XXXXX o XXXXX-XXXX." +#: contrib/localflavor/cl/forms.py:32 +msgid "Enter valid a Chilean RUT. The format is XX.XXX.XXX-X." +msgstr "Introdueixi un RUT Xilè vàlid. El format és XX.XXX.XXX-X" -#: contrib/localflavor/us/forms.py:51 -msgid "Enter a valid U.S. Social Security number in XXX-XX-XXXX format." -msgstr "" -"Introdueixi un número vàlid de la Seguretat Social dels E.U.A. en el format " -"XXX-XX-XXXX." +#: contrib/localflavor/cl/forms.py:37 +msgid "Enter valid a Chilean RUT" +msgstr "Introdueixi un RUT Xilè vàlid." -#: contrib/localflavor/fi/forms.py:14 contrib/localflavor/de/forms.py:16 +#: contrib/localflavor/de/forms.py:16 +#: contrib/localflavor/fi/forms.py:14 #: contrib/localflavor/fr/forms.py:17 msgid "Enter a zip code in the format XXXXX." msgstr "Introdueixi un codi zip en el format XXXXX." -#: contrib/localflavor/fi/forms.py:40 contrib/localflavor/fi/forms.py:45 -msgid "Enter a valid Finnish social security number." -msgstr "Introdueixi un número vàlid de la seguretat social finlandesa." - -#: contrib/localflavor/no/forms.py:36 -msgid "Enter a valid Norwegian social security number." -msgstr "Introdueixi un número de la seguretat social Noruega vàlid." - -#: contrib/localflavor/cl/forms.py:21 -msgid "Enter valid a Chilean RUT. The format is XX.XXX.XXX-X." -msgstr "Introdueixi un RUT Xilè vàlid. El format és XX.XXX.XXX-X" - -#: contrib/localflavor/cl/forms.py:26 -msgid "Enter valid a Chilean RUT" -msgstr "Introdueixi un RUT Xilè vàlid." +#: contrib/localflavor/de/forms.py:60 +msgid "Enter a valid German identity card number in XXXXXXXXXXX-XXXXXXX-XXXXXXX-X format." +msgstr "Introdueixi un número de tarjeta d'identificació alemany vàlid en el format XXXXXXXXXXX-XXXXXXX-XXXXXXX-X." #: contrib/localflavor/de/de_states.py:5 msgid "Baden-Wuerttemberg" @@ -2119,17 +2260,26 @@ msgstr "Schleswig-Holstein" msgid "Thuringia" msgstr "Thuringia" -#: contrib/localflavor/de/forms.py:60 -msgid "" -"Enter a valid German identity card number in XXXXXXXXXXX-XXXXXXX-XXXXXXX-X " -"format." -msgstr "" -"Introdueixi un número de tarjeta d'identificació alemany vàlid en el format " -"XXXXXXXXXXX-XXXXXXX-XXXXXXX-X." +#: contrib/localflavor/fi/forms.py:40 +#: contrib/localflavor/fi/forms.py:45 +msgid "Enter a valid Finnish social security number." +msgstr "Introdueixi un número vàlid de la seguretat social finlandesa." -#: contrib/localflavor/au/forms.py:18 -msgid "Enter a 4 digit post code." -msgstr "Introdueixi un codi postal de 4 dígits." +#: contrib/localflavor/it/forms.py:16 +msgid "Enter a valid zip code." +msgstr "Introdueixi un codi zip vàlid." + +#: contrib/localflavor/it/forms.py:41 +msgid "Enter a valid Social Security number." +msgstr "Introdueixi un número valid de la Seguretat Social." + +#: contrib/localflavor/it/forms.py:68 +msgid "Enter a valid VAT number." +msgstr "Introdueixi un número de IVA (VAT) vàlid." + +#: contrib/localflavor/jp/forms.py:21 +msgid "Enter a postal code in the format XXXXXXX or XXX-XXXX." +msgstr "Introdueixi un codi postal en el format XXXXXXX o XX-XXXX." #: contrib/localflavor/jp/jp_prefectures.py:4 msgid "Hokkaido" @@ -2319,359 +2469,607 @@ msgstr "Kagoshima" msgid "Okinawa" msgstr "Okinawa" -#: contrib/localflavor/jp/forms.py:21 -msgid "Enter a postal code in the format XXXXXXX or XXX-XXXX." -msgstr "Introdueixi un codi postal en el format XXXXXXX o XX-XXXX." +#: contrib/localflavor/nl/forms.py:25 +msgid "Enter a valid postal code" +msgstr "Introdueixi un codi postal vàlid." -#: contrib/localflavor/br/forms.py:18 -msgid "Enter a zip code in the format XXXXX-XXX." -msgstr "Introdueixi un codi zip en el format XXXXX-XXX." +#: contrib/localflavor/nl/forms.py:53 +msgid "Enter a valid phone number" +msgstr "Introdueixi un número de telèfon vàlid." -#: contrib/localflavor/br/forms.py:30 -msgid "Phone numbers must be in XX-XXXX-XXXX format." -msgstr "El número de telèfon ha de ser en el format XX-XXXX-XXXX." +#: contrib/localflavor/nl/forms.py:76 +msgid "Enter a valid SoFi number" +msgstr "Introdueixi un número SoFi vàlid." -#: contrib/localflavor/br/forms.py:72 -msgid "This field requires only numbers." -msgstr "Aquest camps requereix només números." +#: contrib/localflavor/nl/nl_provinces.py:4 +msgid "Drente" +msgstr "Drente" -#: contrib/localflavor/br/forms.py:74 -msgid "This field requires at most 11 digits or 14 characters." -msgstr "Aquest camp requereix com a màxim 11 dígits o 14 caracters." +#: contrib/localflavor/nl/nl_provinces.py:5 +msgid "Flevoland" +msgstr "Flevoland" -#: contrib/localflavor/br/forms.py:84 -msgid "Invalid CPF number." -msgstr "Número CPF invàlid." +#: contrib/localflavor/nl/nl_provinces.py:6 +msgid "Friesland" +msgstr "Friesland" -#: contrib/localflavor/br/forms.py:106 -msgid "This field requires at least 14 digits" -msgstr "Aquest camp requereix almenys 14 dígits." +#: contrib/localflavor/nl/nl_provinces.py:7 +msgid "Gelderland" +msgstr "Gelderland" -#: contrib/localflavor/br/forms.py:116 -msgid "Invalid CNPJ number." -msgstr "Número CNPJ invàlid." +#: contrib/localflavor/nl/nl_provinces.py:8 +msgid "Groningen" +msgstr "Groningen" -#: contrib/localflavor/is_/forms.py:16 -msgid "" -"Enter a valid Icelandic identification number. The format is XXXXXX-XXXX." -msgstr "" -"Introdueixi un número de identificació d'Islàndia. El format és XXXXXX-XXXX." +#: contrib/localflavor/nl/nl_provinces.py:9 +msgid "Limburg" +msgstr "Limburg" -#: contrib/localflavor/is_/forms.py:30 -msgid "The Icelandic identification number is not valid." -msgstr "El número de identificació d'Islàndia no és vàlid." +#: contrib/localflavor/nl/nl_provinces.py:10 +msgid "Noord-Brabant" +msgstr "Noord-Brabant" -#: core/validators.py:65 -msgid "This value must contain only letters, numbers and underscores." -msgstr "Aquest valor ha de contenir només números, guions, i guions baixos." +#: contrib/localflavor/nl/nl_provinces.py:11 +msgid "Noord-Holland" +msgstr "Noord-Holland" -#: core/validators.py:69 -msgid "" -"This value must contain only letters, numbers, underscores, dashes or " -"slashes." -msgstr "" -"Aquest valor ha de contenir només lletres, números, guions, guions baixos, i " -"barres (/)." +#: contrib/localflavor/nl/nl_provinces.py:12 +msgid "Overijssel" +msgstr "Overijssel" -#: core/validators.py:73 -msgid "This value must contain only letters, numbers, underscores or hyphens." -msgstr "" -"Aquest valor ha de contenir només lletres, números, guions o guions baixos" +#: contrib/localflavor/nl/nl_provinces.py:13 +msgid "Utrecht" +msgstr "Utrecht" -#: core/validators.py:77 -msgid "Uppercase letters are not allowed here." -msgstr "No es permeten majúscules aquí." +#: contrib/localflavor/nl/nl_provinces.py:14 +msgid "Zeeland" +msgstr "Zeeland" -#: core/validators.py:81 -msgid "Lowercase letters are not allowed here." -msgstr "No es permeten minúscules aquí." +#: contrib/localflavor/nl/nl_provinces.py:15 +msgid "Zuid-Holland" +msgstr "Zuid-Holland" -#: core/validators.py:88 -msgid "Enter only digits separated by commas." -msgstr "Introdueixi només dígits separats per comes." +#: contrib/localflavor/no/forms.py:35 +msgid "Enter a valid Norwegian social security number." +msgstr "Introdueixi un número de la seguretat social Noruega vàlid." -#: core/validators.py:100 -msgid "Enter valid e-mail addresses separated by commas." -msgstr "Introdueixi adreces de correu electrònic vàlides separades per comes." +#: contrib/localflavor/pl/forms.py:53 +msgid "National Identification Number consists of 11 digits." +msgstr "El número d'identidicació nacional està compost de 11 digits." -#: core/validators.py:104 -msgid "Please enter a valid IP address." -msgstr "Per favor introdueixi una adreça IP vàlida." +#: contrib/localflavor/pl/forms.py:59 +msgid "Wrong checksum for the National Identification Number." +msgstr "Validació invàlida del número d'identificació nacional." -#: core/validators.py:108 -msgid "Empty values are not allowed here." -msgstr "No s'admeten valor buits." +#: contrib/localflavor/pl/forms.py:71 +msgid "Enter a tax number field (NIP) in the format XXX-XXX-XX-XX or XX-XX-XXX-XXX." +msgstr "Introdueixi un número NIP en el format XXX-XXX-XX-XX o XX-XX-XXX-XXX." -#: core/validators.py:112 -msgid "Non-numeric characters aren't allowed here." -msgstr "No s'admeten caracters no numèrics." +#: contrib/localflavor/pl/forms.py:82 +msgid "Enter a postal code in the format XX-XXX." +msgstr "Introdueixi un codi postal en el format XX-XXX." -#: core/validators.py:116 -msgid "This value can't be comprised solely of digits." -msgstr "Aquest valor no pot contenir només dígits." +#: contrib/localflavor/pl/pl_voivodeships.py:8 +msgid "Lower Silesia" +msgstr "Lower Silesia" -#: core/validators.py:125 -msgid "Only alphabetical characters are allowed here." -msgstr "Només s'admeted caracters alfabètics aquí." +#: contrib/localflavor/pl/pl_voivodeships.py:9 +msgid "Kuyavia-Pomerania" +msgstr "Kuyavia-Pomerania" -#: core/validators.py:140 -msgid "Year must be 1900 or later." -msgstr "L'any ha de ser posterior al 1900" +#: contrib/localflavor/pl/pl_voivodeships.py:10 +msgid "Lublin" +msgstr "Lublin" -#: core/validators.py:144 -#, python-format -msgid "Invalid date: %s" -msgstr "Data invàlida: %s" +#: contrib/localflavor/pl/pl_voivodeships.py:11 +msgid "Lubusz" +msgstr "Lubusz" -#: core/validators.py:149 db/models/fields/__init__.py:468 -msgid "Enter a valid date in YYYY-MM-DD format." -msgstr "Introdueixi una data vàlida en el forma AAAA-MM-DD." +#: contrib/localflavor/pl/pl_voivodeships.py:12 +msgid "Lodz" +msgstr "Lodz" -#: core/validators.py:154 -msgid "Enter a valid time in HH:MM format." -msgstr "Introdueixi una hora vàlida en el format HH:MM." +#: contrib/localflavor/pl/pl_voivodeships.py:13 +msgid "Lesser Poland" +msgstr "Lesser Poland" -#: core/validators.py:158 db/models/fields/__init__.py:537 -msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format." -msgstr "Introdueixi un data/hora vàlida en format YYYY-MM-DD HH:MM." +#: contrib/localflavor/pl/pl_voivodeships.py:14 +msgid "Masovia" +msgstr "Masovia" -#: core/validators.py:175 core/validators.py:453 oldforms/__init__.py:672 -msgid "No file was submitted. Check the encoding type on the form." -msgstr "" -"No s'ha enviat cap fitxer. Comprovi el tipus de codificació del formulari." +#: contrib/localflavor/pl/pl_voivodeships.py:15 +msgid "Opole" +msgstr "Opole" -#: core/validators.py:179 -msgid "" -"Upload a valid image. The file you uploaded was either not an image or a " -"corrupted image." -msgstr "" -"Envii una imatge vàilda. El fitxer que ha enviat no era una imatge o estaba " -"corrupte." +#: contrib/localflavor/pl/pl_voivodeships.py:16 +msgid "Subcarpatia" +msgstr "Subcarpatia" -#: core/validators.py:186 -#, python-format -msgid "The URL %s does not point to a valid image." -msgstr "La URL %s no apunta una imatge vàlida." +#: contrib/localflavor/pl/pl_voivodeships.py:17 +msgid "Podlasie" +msgstr "Podlasie" -#: core/validators.py:190 -#, python-format -msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid." -msgstr "" -"El números de telèfon han de guardar-se en el format XXX-XXX-XXXX. \"%s\" no " -"és vàlid." +#: contrib/localflavor/pl/pl_voivodeships.py:18 +msgid "Pomerania" +msgstr "Pomerania" -#: core/validators.py:198 -#, python-format -msgid "The URL %s does not point to a valid QuickTime video." -msgstr "La URL %s no apunta a un video QuickTime vàlid." +#: contrib/localflavor/pl/pl_voivodeships.py:19 +msgid "Silesia" +msgstr "Silesia" -#: core/validators.py:202 -msgid "A valid URL is required." -msgstr "Es precisa d'una URL vàlida." +#: contrib/localflavor/pl/pl_voivodeships.py:20 +msgid "Swietokrzyskie" +msgstr "Swietokrzyskie" -#: core/validators.py:216 -#, python-format -msgid "" -"Valid HTML is required. Specific errors are:\n" -"%s" -msgstr "" -"Es precisa HTML vàlid. Els errors específics sòn:\n" -"%s" +#: contrib/localflavor/pl/pl_voivodeships.py:21 +msgid "Warmia-Masuria" +msgstr "Warmia-Masuria" -#: core/validators.py:223 -#, python-format -msgid "Badly formed XML: %s" -msgstr "XML incorrectament formatejat: %s" +#: contrib/localflavor/pl/pl_voivodeships.py:22 +msgid "Greater Poland" +msgstr "Greater Poland" -#: core/validators.py:240 -#, python-format -msgid "Invalid URL: %s" -msgstr "URL invalida: %s" +#: contrib/localflavor/pl/pl_voivodeships.py:23 +msgid "West Pomerania" +msgstr "West Pomerania" -#: core/validators.py:245 core/validators.py:247 -#, python-format -msgid "The URL %s is a broken link." -msgstr "La URL %sés un enllaç trencat." +#: contrib/localflavor/sk/forms.py:32 +msgid "Enter a postal code in the format XXXXX or XXX XX." +msgstr "Introdueixi un codi postal en el format XXXXX or XXX XX." -#: core/validators.py:253 -msgid "Enter a valid U.S. state abbreviation." -msgstr "Introdueixi una abreviatura vàlida d'estat d'els E.U.A.." +#: contrib/localflavor/sk/sk_districts.py:8 +msgid "Banska Bystrica" +msgstr "Banska Bystrica" -#: core/validators.py:267 -#, python-format -msgid "Watch your mouth! The word %s is not allowed here." -msgid_plural "Watch your mouth! The words %s are not allowed here." -msgstr[0] "Vigili la seva boca! Aquí no admetem la paraula: %s." -msgstr[1] "Vigili la seva boca! Aquí no admetem les paraules: %s." +#: contrib/localflavor/sk/sk_districts.py:9 +msgid "Banska Stiavnica" +msgstr "Banska Stiavnica" -#: core/validators.py:274 -#, python-format -msgid "This field must match the '%s' field." -msgstr "Aquest camp ha de concordar amb el camp '%s'." +#: contrib/localflavor/sk/sk_districts.py:10 +msgid "Bardejov" +msgstr "Bardejov" -#: core/validators.py:293 -msgid "Please enter something for at least one field." -msgstr "Si us plau, introdueixi alguna cosa alemnys en un camp." +#: contrib/localflavor/sk/sk_districts.py:11 +msgid "Banovce nad Bebravou" +msgstr "Banovce nad Bebravou" -#: core/validators.py:302 core/validators.py:313 -msgid "Please enter both fields or leave them both empty." -msgstr "Si us plau, ompli els dos camps o deixi'ls tots dos en blanc." +#: contrib/localflavor/sk/sk_districts.py:12 +msgid "Brezno" +msgstr "Brezno" -#: core/validators.py:321 -#, python-format -msgid "This field must be given if %(field)s is %(value)s" -msgstr "S'ha de proporcionar aquest camps si %(field)s és %(value)s" +#: contrib/localflavor/sk/sk_districts.py:13 +msgid "Bratislava I" +msgstr "Bratislava I" -#: core/validators.py:334 -#, python-format -msgid "This field must be given if %(field)s is not %(value)s" -msgstr "S'ha de proporcionar aquest camps si %(field)s no és %(value)s" +#: contrib/localflavor/sk/sk_districts.py:14 +msgid "Bratislava II" +msgstr "Bratislava II" -#: core/validators.py:353 -msgid "Duplicate values are not allowed." -msgstr "No s'admeten valors duplicats." +#: contrib/localflavor/sk/sk_districts.py:15 +msgid "Bratislava III" +msgstr "Bratislava III" -#: core/validators.py:368 -#, python-format -msgid "This value must be between %(lower)s and %(upper)s." -msgstr "Aquest valor ha de estar comprés entre %(lower)s i %(upper)s." +#: contrib/localflavor/sk/sk_districts.py:16 +msgid "Bratislava IV" +msgstr "Bratislava IV" -#: core/validators.py:370 -#, python-format -msgid "This value must be at least %s." -msgstr "Aquest valor ha de ser com a mínim %s." +#: contrib/localflavor/sk/sk_districts.py:17 +msgid "Bratislava V" +msgstr "Bratislava V" -#: core/validators.py:372 -#, python-format -msgid "This value must be no more than %s." -msgstr "Aquest valor ha de ser com a màxim %s." +#: contrib/localflavor/sk/sk_districts.py:18 +msgid "Bytca" +msgstr "Bytca" -#: core/validators.py:408 -#, python-format -msgid "This value must be a power of %s." -msgstr "Aquest valor ha de ser una potència de %s." +#: contrib/localflavor/sk/sk_districts.py:19 +msgid "Cadca" +msgstr "Cadca" -#: core/validators.py:417 -msgid "Please enter a valid decimal number." -msgstr "Si us plau, introdueixi un número decimal vàlid." +#: contrib/localflavor/sk/sk_districts.py:20 +msgid "Detva" +msgstr "Detva" -#: core/validators.py:423 -#, python-format -msgid "Please enter a valid decimal number with at most %s total digit." -"Please enter a valid decimal number with at most %s total digits." -msgstr "" -"Si us plau, introdueixi un número decimal vàlid amb no més de %s digit." -"Si us plau, introdueixi un número decimal vàlid amb no més de %s digits." +#: contrib/localflavor/sk/sk_districts.py:21 +msgid "Dolny Kubin" +msgstr "Dolny Kubin" -#: core/validators.py:426 -#, python-format -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 digits." -msgstr "" -"Si us plau, introdueixi un número decimal vàlid amb la part entera amb com a " -"màxim %s dígit." -"Si us plau, introdueixi un número decimal vàlid amb la part entera amb com a " -"màxim %s dígits." +#: contrib/localflavor/sk/sk_districts.py:22 +msgid "Dunajska Streda" +msgstr "Dunajska Streda" -#: core/validators.py:429 -#, python-format -msgid "Please enter a valid decimal number with at most %s decimal place." -"Please enter a valid decimal number with at most %s decimal places." -msgstr "" -"Si us plau, introdueixi un número decimal vàlid amb no més de %s dígit en la " -"part decimal." -"Si us plau, introdueixi un número decimal vàlid amb no més de %s dígits en " -"la part decimal." +#: contrib/localflavor/sk/sk_districts.py:23 +msgid "Galanta" +msgstr "Galanta" -#: core/validators.py:437 -msgid "Please enter a valid floating point number." -msgstr "Si us plau, introdueixi un número amb punt de coma flotant vàlid." +#: contrib/localflavor/sk/sk_districts.py:24 +msgid "Gelnica" +msgstr "Gelnica" -#: core/validators.py:446 -#, python-format -msgid "Make sure your uploaded file is at least %s bytes big." -msgstr "Asseguris de que el fitxer que ha enviat té, com a mínim, %s bytes." +#: contrib/localflavor/sk/sk_districts.py:25 +msgid "Hlohovec" +msgstr "Hlohovec" -#: core/validators.py:447 -#, python-format -msgid "Make sure your uploaded file is at most %s bytes big." -msgstr "Asseguris de que el fitxer que ha enviat té, com a màxim %s bytes." +#: contrib/localflavor/sk/sk_districts.py:26 +msgid "Humenne" +msgstr "Humenne" -#: core/validators.py:464 -msgid "The format for this field is wrong." -msgstr "El format per aquest camp és incorrecte." +#: contrib/localflavor/sk/sk_districts.py:27 +msgid "Ilava" +msgstr "Ilava" -#: core/validators.py:479 -msgid "This field is invalid." -msgstr "El camp no és vàlid." +#: contrib/localflavor/sk/sk_districts.py:28 +msgid "Kezmarok" +msgstr "Kezmarok" -#: core/validators.py:515 -#, python-format -msgid "Could not retrieve anything from %s." -msgstr "No s'ha pogut obtenir res de %s." +#: contrib/localflavor/sk/sk_districts.py:29 +msgid "Komarno" +msgstr "Komarno" -#: core/validators.py:518 -#, python-format -msgid "" -"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'." -msgstr "" -"La URL %(url)s ha va tornar la capcelera Content-Type '%(contenttype)s', que " -"no és vàlida." +#: contrib/localflavor/sk/sk_districts.py:30 +msgid "Kosice I" +msgstr "Kosice I" -#: core/validators.py:551 -#, python-format -msgid "" -"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with " -"\"%(start)s\".)" -msgstr "" -"Si us plau, tanqui l'etiqueta %(tag)s des de la línia %(line)s. (La línia " -"comença amb \"%(start)s\".)" +#: contrib/localflavor/sk/sk_districts.py:31 +msgid "Kosice II" +msgstr "Kosice II" + +#: contrib/localflavor/sk/sk_districts.py:32 +msgid "Kosice III" +msgstr "Kosice III" + +#: contrib/localflavor/sk/sk_districts.py:33 +msgid "Kosice IV" +msgstr "Kosice IV" + +#: contrib/localflavor/sk/sk_districts.py:34 +msgid "Kosice - okolie" +msgstr "Kosice - okolie" + +#: contrib/localflavor/sk/sk_districts.py:35 +msgid "Krupina" +msgstr "Krupina" + +#: contrib/localflavor/sk/sk_districts.py:36 +msgid "Kysucke Nove Mesto" +msgstr "Kysucke Nove Mesto" + +#: contrib/localflavor/sk/sk_districts.py:37 +msgid "Levice" +msgstr "Levice" + +#: contrib/localflavor/sk/sk_districts.py:38 +msgid "Levoca" +msgstr "Levoca" + +#: contrib/localflavor/sk/sk_districts.py:39 +msgid "Liptovsky Mikulas" +msgstr "Liptovsky Mikulas" + +#: contrib/localflavor/sk/sk_districts.py:40 +msgid "Lucenec" +msgstr "Lucenec" + +#: contrib/localflavor/sk/sk_districts.py:41 +msgid "Malacky" +msgstr "Malacky" + +#: contrib/localflavor/sk/sk_districts.py:42 +msgid "Martin" +msgstr "Martin" + +#: contrib/localflavor/sk/sk_districts.py:43 +msgid "Medzilaborce" +msgstr "Medzilaborce" + +#: contrib/localflavor/sk/sk_districts.py:44 +msgid "Michalovce" +msgstr "Michalovce" + +#: contrib/localflavor/sk/sk_districts.py:45 +msgid "Myjava" +msgstr "Myjava" + +#: contrib/localflavor/sk/sk_districts.py:46 +msgid "Namestovo" +msgstr "Namestovo" + +#: contrib/localflavor/sk/sk_districts.py:47 +msgid "Nitra" +msgstr "Nitra" + +#: contrib/localflavor/sk/sk_districts.py:48 +msgid "Nove Mesto nad Vahom" +msgstr "Nove Mesto nad Vahom" + +#: contrib/localflavor/sk/sk_districts.py:49 +msgid "Nove Zamky" +msgstr "Nove Zamky" + +#: contrib/localflavor/sk/sk_districts.py:50 +msgid "Partizanske" +msgstr "Partizanske" + +#: contrib/localflavor/sk/sk_districts.py:51 +msgid "Pezinok" +msgstr "Pezinok" + +#: contrib/localflavor/sk/sk_districts.py:52 +msgid "Piestany" +msgstr "Piestany" + +#: contrib/localflavor/sk/sk_districts.py:53 +msgid "Poltar" +msgstr "Poltar" + +#: contrib/localflavor/sk/sk_districts.py:54 +msgid "Poprad" +msgstr "Poprad" + +#: contrib/localflavor/sk/sk_districts.py:55 +msgid "Povazska Bystrica" +msgstr "Povazska Bystrica" + +#: contrib/localflavor/sk/sk_districts.py:56 +msgid "Presov" +msgstr "Presov" + +#: contrib/localflavor/sk/sk_districts.py:57 +msgid "Prievidza" +msgstr "Prievidza" + +#: contrib/localflavor/sk/sk_districts.py:58 +msgid "Puchov" +msgstr "Puchov" + +#: contrib/localflavor/sk/sk_districts.py:59 +msgid "Revuca" +msgstr "Revuca" + +#: contrib/localflavor/sk/sk_districts.py:60 +msgid "Rimavska Sobota" +msgstr "Rimavska Sobota" + +#: contrib/localflavor/sk/sk_districts.py:61 +msgid "Roznava" +msgstr "Roznava" + +#: contrib/localflavor/sk/sk_districts.py:62 +msgid "Ruzomberok" +msgstr "Ruzomberok" + +#: contrib/localflavor/sk/sk_districts.py:63 +msgid "Sabinov" +msgstr "Sabinov" + +#: contrib/localflavor/sk/sk_districts.py:64 +msgid "Senec" +msgstr "Senec" + +#: contrib/localflavor/sk/sk_districts.py:65 +msgid "Senica" +msgstr "Senica" + +#: contrib/localflavor/sk/sk_districts.py:66 +msgid "Skalica" +msgstr "Skalica" + +#: contrib/localflavor/sk/sk_districts.py:67 +msgid "Snina" +msgstr "Snina" + +#: contrib/localflavor/sk/sk_districts.py:68 +msgid "Sobrance" +msgstr "Sobrance" + +#: contrib/localflavor/sk/sk_districts.py:69 +msgid "Spisska Nova Ves" +msgstr "Spisska Nova Ves" + +#: contrib/localflavor/sk/sk_districts.py:70 +msgid "Stara Lubovna" +msgstr "Stara Lubovna" + +#: contrib/localflavor/sk/sk_districts.py:71 +msgid "Stropkov" +msgstr "Stropkov" + +#: contrib/localflavor/sk/sk_districts.py:72 +msgid "Svidnik" +msgstr "Svidnik" + +#: contrib/localflavor/sk/sk_districts.py:73 +msgid "Sala" +msgstr "Sala" + +#: contrib/localflavor/sk/sk_districts.py:74 +msgid "Topolcany" +msgstr "Topolcany" + +#: contrib/localflavor/sk/sk_districts.py:75 +msgid "Trebisov" +msgstr "Trebisov" + +#: contrib/localflavor/sk/sk_districts.py:76 +msgid "Trencin" +msgstr "Trencin" + +#: contrib/localflavor/sk/sk_districts.py:77 +msgid "Trnava" +msgstr "Trnava" + +#: contrib/localflavor/sk/sk_districts.py:78 +msgid "Turcianske Teplice" +msgstr "Turcianske Teplice" + +#: contrib/localflavor/sk/sk_districts.py:79 +msgid "Tvrdosin" +msgstr "Tvrdosin" + +#: contrib/localflavor/sk/sk_districts.py:80 +msgid "Velky Krtis" +msgstr "Velky Krtis" + +#: contrib/localflavor/sk/sk_districts.py:81 +msgid "Vranov nad Toplou" +msgstr "Vranov nad Toplou" + +#: contrib/localflavor/sk/sk_districts.py:82 +msgid "Zlate Moravce" +msgstr "Zlate Moravce" + +#: contrib/localflavor/sk/sk_districts.py:83 +msgid "Zvolen" +msgstr "Zvolen" + +#: contrib/localflavor/sk/sk_districts.py:84 +msgid "Zarnovica" +msgstr "Zarnovica" + +#: contrib/localflavor/sk/sk_districts.py:85 +msgid "Ziar nad Hronom" +msgstr "Ziar nad Hronom" + +#: contrib/localflavor/sk/sk_districts.py:86 +msgid "Zilina" +msgstr "Zilina" + +#: contrib/localflavor/sk/sk_regions.py:8 +msgid "Banska Bystrica region" +msgstr "Regió de Banska Bystrica" + +#: contrib/localflavor/sk/sk_regions.py:9 +msgid "Bratislava region" +msgstr "Regió de Bratislava" + +#: contrib/localflavor/sk/sk_regions.py:10 +msgid "Kosice region" +msgstr "Regió de Kosice" + +#: contrib/localflavor/sk/sk_regions.py:11 +msgid "Nitra region" +msgstr "Regió de Nitra" + +#: contrib/localflavor/sk/sk_regions.py:12 +msgid "Presov region" +msgstr "Regió de Presov" + +#: contrib/localflavor/sk/sk_regions.py:13 +msgid "Trencin region" +msgstr "Regió de Trencin" -#: core/validators.py:555 +#: contrib/localflavor/sk/sk_regions.py:14 +msgid "Trnava region" +msgstr "Regió de Trnava" + +#: contrib/localflavor/sk/sk_regions.py:15 +msgid "Zilina region" +msgstr "Regió de Zilina" + +#: contrib/localflavor/uk/forms.py:18 +msgid "Enter a postcode. A space is required between the two postcode parts." +msgstr "Introdueixi un codi postal. És necessari un espai entre les dues parts del codi postal." + +#: contrib/localflavor/us/forms.py:18 +msgid "Enter a zip code in the format XXXXX or XXXXX-XXXX." +msgstr "Introdueixi un codi zip en el format XXXXX o XXXXX-XXXX." + +#: contrib/localflavor/us/forms.py:51 +msgid "Enter a valid U.S. Social Security number in XXX-XX-XXXX format." +msgstr "Introdueixi un número vàlid de la Seguretat Social dels E.U.A. en el format XXX-XX-XXXX." + +#: contrib/localflavor/in_/forms.py:16 +msgid "Enter a zip code in the format XXXXXXX." +msgstr "Introdueixi un codi zip en el format XXXXXXX." + +#: contrib/localflavor/is_/forms.py:17 +msgid "Enter a valid Icelandic identification number. The format is XXXXXX-XXXX." +msgstr "Introdueixi un número de identificació d'Islàndia. El format és XXXXXX-XXXX." + +#: contrib/localflavor/is_/forms.py:31 +msgid "The Icelandic identification number is not valid." +msgstr "El número de identificació d'Islàndia no és vàlid." + +#: contrib/sessions/models.py:68 +msgid "session key" +msgstr "clau de la sessió" + +#: contrib/sessions/models.py:69 +msgid "session data" +msgstr "dades de la sessió" + +#: contrib/sessions/models.py:70 +msgid "expire date" +msgstr "data de caducitat" + +#: contrib/sessions/models.py:74 +msgid "session" +msgstr "sessió" + +#: contrib/sessions/models.py:75 +msgid "sessions" +msgstr "sessions" + +#: contrib/contenttypes/models.py:37 +msgid "python model class name" +msgstr "nom de la classe del model en python" + +#: contrib/contenttypes/models.py:40 +msgid "content type" +msgstr "tipus de contingut" + +#: contrib/contenttypes/models.py:41 +msgid "content types" +msgstr "tipus de continguts" + +#: oldforms/__init__.py:408 #, python-format -msgid "" -"Some text starting on line %(line)s is not allowed in that context. (Line " -"starts with \"%(start)s\".)" -msgstr "" -"Part del text que comença en la línia %(line)s no està permès en aquest " -"context. (La línia comença per \"%(start)s\".)" +msgid "Ensure your text is less than %s character." +msgid_plural "Ensure your text is less than %s characters." +msgstr[0] "Asseguris de que el seu texte té menys de %s caracter." +msgstr[1] "Asseguris de que el seu texte té menys de %s caracters." + +#: oldforms/__init__.py:413 +msgid "Line breaks are not allowed here." +msgstr "No es permeten salts de línia." -#: core/validators.py:560 +#: oldforms/__init__.py:511 +#: oldforms/__init__.py:585 +#: oldforms/__init__.py:624 #, python-format -msgid "" -"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%" -"(start)s\".)" -msgstr "" -"El \"%(attr)s\" de la línia %(line)s no és un atribut vàlid. (La línia " -"comença per \"%(start)s\".)" +msgid "Select a valid choice; '%(data)s' is not in %(choices)s." +msgstr "Esculli una opció vàlida; %(data)s' no està dintre de %(choices)s." + +#: oldforms/__init__.py:688 +#: newforms/fields.py:381 +msgid "The submitted file is empty." +msgstr "El fitxer enviat està buit." + +#: oldforms/__init__.py:744 +msgid "Enter a whole number between -32,768 and 32,767." +msgstr "Introdueixi un número enter entre -32,768 i 32,767." + +#: oldforms/__init__.py:754 +msgid "Enter a positive number." +msgstr "Introdueixi un número positiu." -#: core/validators.py:565 +#: oldforms/__init__.py:764 +msgid "Enter a whole number between 0 and 32,767." +msgstr "Introdueixi un número entre 0 i 32,767." + +#: views/generic/create_update.py:43 #, python-format -msgid "" -"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%" -"(start)s\".)" -msgstr "" -"La \"<%(tag)s>\" de la línia %(line)s no és una etiqueta vàlida. (La línia " -"comença per \"%(start)s\".)" +msgid "The %(verbose_name)s was created successfully." +msgstr "El/La %(verbose_name)s s'ha creat amb èxit." -#: core/validators.py:569 +#: views/generic/create_update.py:117 #, python-format -msgid "" -"A tag on line %(line)s is missing one or more required attributes. (Line " -"starts with \"%(start)s\".)" -msgstr "" -"Una etiqueta de la línia %(line)s li falta un o més atributs requerits.(La " -"línia comença per \"%(start)s\".)" +msgid "The %(verbose_name)s was updated successfully." +msgstr "El/La %(verbose_name)s s'ha actualtzat amb èxit." -#: core/validators.py:574 +#: views/generic/create_update.py:184 #, python-format -msgid "" -"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line " -"starts with \"%(start)s\".)" -msgstr "" -"L'atribut \"%(attr)s\" de la línia %(line)s té un valor que no és vàlid. (La " -"línia comença per \"%(start)s\".)" +msgid "The %(verbose_name)s was deleted." +msgstr "El %(verbose_name)s s'ha eliminat." #: utils/dates.py:6 msgid "Monday" @@ -2701,130 +3099,167 @@ msgstr "Dissabte" msgid "Sunday" msgstr "Diumenge" -#: utils/dates.py:14 +#: utils/dates.py:10 +msgid "Mon" +msgstr "Dl" + +#: utils/dates.py:10 +msgid "Tue" +msgstr "Dt" + +#: utils/dates.py:10 +msgid "Wed" +msgstr "Dc" + +#: utils/dates.py:10 +msgid "Thu" +msgstr "Dj" + +#: utils/dates.py:10 +msgid "Fri" +msgstr "Dv" + +#: utils/dates.py:11 +msgid "Sat" +msgstr "Db" + +#: utils/dates.py:11 +msgid "Sun" +msgstr "Dg" + +#: utils/dates.py:18 msgid "January" msgstr "Gener" -#: utils/dates.py:14 +#: utils/dates.py:18 msgid "February" msgstr "Febrer" -#: utils/dates.py:14 utils/dates.py:27 +#: utils/dates.py:18 +#: utils/dates.py:31 msgid "March" msgstr "Març" -#: utils/dates.py:14 utils/dates.py:27 +#: utils/dates.py:18 +#: utils/dates.py:31 msgid "April" msgstr "Abril" -#: utils/dates.py:14 utils/dates.py:27 +#: utils/dates.py:18 +#: utils/dates.py:31 msgid "May" msgstr "Maig" -#: utils/dates.py:14 utils/dates.py:27 +#: utils/dates.py:18 +#: utils/dates.py:31 msgid "June" msgstr "Juny" -#: utils/dates.py:15 utils/dates.py:27 +#: utils/dates.py:19 +#: utils/dates.py:31 msgid "July" msgstr "Juliol" -#: utils/dates.py:15 +#: utils/dates.py:19 msgid "August" msgstr "Agost" -#: utils/dates.py:15 +#: utils/dates.py:19 msgid "September" msgstr "Setembre" -#: utils/dates.py:15 +#: utils/dates.py:19 msgid "October" msgstr "Octubre" -#: utils/dates.py:15 +#: utils/dates.py:19 msgid "November" msgstr "Novembre" -#: utils/dates.py:16 +#: utils/dates.py:20 msgid "December" msgstr "Desembre" -#: utils/dates.py:19 +#: utils/dates.py:23 msgid "jan" msgstr "gen" -#: utils/dates.py:19 +#: utils/dates.py:23 msgid "feb" msgstr "feb" -#: utils/dates.py:19 +#: utils/dates.py:23 msgid "mar" msgstr "mar" -#: utils/dates.py:19 +#: utils/dates.py:23 msgid "apr" msgstr "abr" -#: utils/dates.py:19 +#: utils/dates.py:23 msgid "may" msgstr "mai" -#: utils/dates.py:19 +#: utils/dates.py:23 msgid "jun" msgstr "jun" -#: utils/dates.py:20 +#: utils/dates.py:24 msgid "jul" msgstr "jul" -#: utils/dates.py:20 +#: utils/dates.py:24 msgid "aug" msgstr "ago" -#: utils/dates.py:20 +#: utils/dates.py:24 msgid "sep" msgstr "set" -#: utils/dates.py:20 +#: utils/dates.py:24 msgid "oct" msgstr "oct" -#: utils/dates.py:20 +#: utils/dates.py:24 msgid "nov" msgstr "nov" -#: utils/dates.py:20 +#: utils/dates.py:24 msgid "dec" msgstr "des" -#: utils/dates.py:27 +#: utils/dates.py:31 msgid "Jan." msgstr "Gen." -#: utils/dates.py:27 +#: utils/dates.py:31 msgid "Feb." msgstr "Feb." -#: utils/dates.py:28 +#: utils/dates.py:32 msgid "Aug." msgstr "Ago." -#: utils/dates.py:28 +#: utils/dates.py:32 msgid "Sept." msgstr "Set." -#: utils/dates.py:28 +#: utils/dates.py:32 msgid "Oct." msgstr "Oct." -#: utils/dates.py:28 +#: utils/dates.py:32 msgid "Nov." msgstr "Nov." -#: utils/dates.py:28 +#: utils/dates.py:32 msgid "Dec." msgstr "Des." +#: utils/text.py:127 +msgid "or" +msgstr "o" + #: utils/timesince.py:12 msgid "year" msgid_plural "years" @@ -2861,167 +3296,211 @@ msgid_plural "minutes" msgstr[0] "minut" msgstr[1] "minuts" -#: utils/timesince.py:40 -#, python-format -msgid "%d milliseconds" -msgstr "%d milisegons" - -#: utils/timesince.py:41 +#: utils/timesince.py:39 #, python-format msgid "%(number)d %(type)s" msgstr "%(number)d %(type)s" -#: utils/timesince.py:47 +#: utils/timesince.py:45 #, python-format msgid ", %(number)d %(type)s" msgstr ", %(number)d %(type)s" -#: utils/dateformat.py:40 +#: utils/dateformat.py:41 msgid "p.m." msgstr "p.m." -#: utils/dateformat.py:41 +#: utils/dateformat.py:42 msgid "a.m." msgstr "a.m." -#: utils/dateformat.py:46 +#: utils/dateformat.py:47 msgid "PM" msgstr "PM" -#: utils/dateformat.py:47 +#: utils/dateformat.py:48 msgid "AM" msgstr "AM" -#: utils/dateformat.py:95 +#: utils/dateformat.py:97 msgid "midnight" msgstr "mitja nit" -#: utils/dateformat.py:97 +#: utils/dateformat.py:99 msgid "noon" msgstr "mig dia" -#: utils/translation/trans_real.py:358 +#: utils/translation/trans_real.py:391 msgid "DATE_FORMAT" msgstr "F j, Y" -#: utils/translation/trans_real.py:359 +#: utils/translation/trans_real.py:392 msgid "DATETIME_FORMAT" msgstr "F j, Y, H:i" -#: utils/translation/trans_real.py:360 +#: utils/translation/trans_real.py:393 msgid "TIME_FORMAT" msgstr "H:i" -#: utils/translation/trans_real.py:376 +#: utils/translation/trans_real.py:409 msgid "YEAR_MONTH_FORMAT" msgstr "j de/d' F del Y" -#: utils/translation/trans_real.py:377 +#: utils/translation/trans_real.py:410 msgid "MONTH_DAY_FORMAT" msgstr "j de/d' F del Y" -#: oldforms/__init__.py:392 -#, python-format -msgid "Ensure your text is less than %s character." -msgid_plural "Ensure your text is less than %s characters." -msgstr[0] "Asseguris de que el seu texte té menys de %s caracter." -msgstr[1] "Asseguris de que el seu texte té menys de %s caracters." +#: template/defaultfilters.py:532 +msgid "yes,no,maybe" +msgstr "si,no,potser" -#: oldforms/__init__.py:397 -msgid "Line breaks are not allowed here." -msgstr "No es permeten salts de línia." +#: template/defaultfilters.py:561 +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d byte" +msgstr[1] "%(size)d bytes" -#: oldforms/__init__.py:498 oldforms/__init__.py:571 oldforms/__init__.py:610 +#: template/defaultfilters.py:563 #, python-format -msgid "Select a valid choice; '%(data)s' is not in %(choices)s." -msgstr "Esculli una opció vàlida; %(data)s' no està dintre de %(choices)s." +msgid "%.1f KB" +msgstr "%.1f KB" -#: oldforms/__init__.py:674 -msgid "The submitted file is empty." -msgstr "El fitxer enviat està buit." +#: template/defaultfilters.py:565 +#, python-format +msgid "%.1f MB" +msgstr "%.1f MB" -#: oldforms/__init__.py:730 -msgid "Enter a whole number between -32,768 and 32,767." -msgstr "Introdueixi un número enter entre -32,768 i 32,767." +#: template/defaultfilters.py:566 +#, python-format +msgid "%.1f GB" +msgstr "%.1f GB" -#: oldforms/__init__.py:740 -msgid "Enter a positive number." -msgstr "Introdueixi un número positiu." +#: newforms/fields.py:123 +#, python-format +msgid "Ensure this value has at most %(max)d characters (it has %(length)d)." +msgstr "Asseguris de que el valor té com a màxim %(max)d caràcters (en té %(length)d)." -#: oldforms/__init__.py:750 -msgid "Enter a whole number between 0 and 32,767." -msgstr "Introdueixi un número entre 0 i 32,767." +#: newforms/fields.py:125 +#, python-format +msgid "Ensure this value has at least %(min)d characters (it has %(length)d)." +msgstr "Asseguris de que el valor té com a mínim %(min)d caràcters (en té %(length)d)." -#: views/generic/create_update.py:43 +#: newforms/fields.py:151 +#: newforms/fields.py:174 +#: newforms/fields.py:204 #, python-format -msgid "The %(verbose_name)s was created successfully." -msgstr "El/La %(verbose_name)s s'ha creat amb èxit." +msgid "Ensure this value is less than or equal to %s." +msgstr "Aquest valor ha de ser menor o igual a %s." -#: views/generic/create_update.py:117 +#: newforms/fields.py:153 +#: newforms/fields.py:176 +#: newforms/fields.py:206 #, python-format -msgid "The %(verbose_name)s was updated successfully." -msgstr "El/La %(verbose_name)s s'ha actualtzat amb èxit." +msgid "Ensure this value is greater than or equal to %s." +msgstr "Asseguris de que aquest valor sigui superior o igual a %s." -#: views/generic/create_update.py:184 +#: newforms/fields.py:172 +#: newforms/fields.py:199 +msgid "Enter a number." +msgstr "Introdueixi un número." + +#: newforms/fields.py:208 #, python-format -msgid "The %(verbose_name)s was deleted." -msgstr "El %(verbose_name)s s'ha eliminat." +msgid "Ensure that there are no more than %s digits in total." +msgstr "Asseguris de que no hi ha més de %s dígits en total." -#: db/models/manipulators.py:307 +#: newforms/fields.py:210 #, python-format -msgid "%(object)s with this %(type)s already exists for the given %(field)s." -msgstr "Ja existeix un %(object)s del tipus %(type)s amb aquest %(field)s." +msgid "Ensure that there are no more than %s decimal places." +msgstr "Asseguris de que no hi ha més de %s decimals." -#: db/models/fields/__init__.py:46 +#: newforms/fields.py:212 #, python-format -msgid "%(optname)s with this %(fieldname)s already exists." -msgstr "Ja existeix %(optname)s amb auqest %(fieldname)s." +msgid "Ensure that there are no more than %s digits before the decimal point." +msgstr "Asseguris de que no hia ha més de %s dígits decimals." -#: db/models/fields/__init__.py:378 -msgid "This value must be an integer." -msgstr "Aquest valor ha de ser un enter." +#: newforms/fields.py:245 +#: newforms/fields.py:629 +msgid "Enter a valid date." +msgstr "Introdueixi una data vàlida." -#: db/models/fields/__init__.py:413 -msgid "This value must be either True or False." -msgstr "Aquest valor ha de ser True (Veritat) o False (Fals)" +#: newforms/fields.py:272 +#: newforms/fields.py:631 +msgid "Enter a valid time." +msgstr "Introdueixi una hora vàlida." -#: db/models/fields/__init__.py:434 -msgid "This field cannot be null." -msgstr "Aquest camp no pot ser null (estar buit)." +#: newforms/fields.py:308 +msgid "Enter a valid date/time." +msgstr "Introdueixi una data/hora vàlides." -#: db/models/fields/__init__.py:597 -msgid "This value must be a decimal number." -msgstr "Aquest valor ha de ser un número decimal." +#: newforms/fields.py:321 +msgid "Enter a valid value." +msgstr "Introdueixi un valor vàlid." -#: db/models/fields/__init__.py:700 -msgid "Enter a valid filename." -msgstr "Introdueixi un nom de fitxer vàlid." +#: newforms/fields.py:379 +msgid "No file was submitted." +msgstr "No s'ha enviat cap fitxer." -#: db/models/fields/__init__.py:824 -msgid "This value must be either None, True or False." -msgstr "Aquest valor ha de ser None (Cap), True (Veritat) o False (Fals)" +#: newforms/fields.py:419 +#: newforms/fields.py:444 +msgid "Enter a valid URL." +msgstr "Introdueixi una URL vàlida." -#: db/models/fields/related.py:54 -#, python-format -msgid "Please enter a valid %s." -msgstr "Si us plau, introdueixi un %s vàlid." +#: newforms/fields.py:446 +msgid "This URL appears to be a broken link." +msgstr "Aquesta URL sembla ser un enllaç trencat." -#: db/models/fields/related.py:640 -msgid "Separate multiple IDs with commas." -msgstr "Separi múltiples IDs amb comes." +#: newforms/fields.py:497 +#: newforms/models.py:180 +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Esculli una opció vàlida; Aquesta opció no és una de les opcions disponibles." -#: db/models/fields/related.py:642 -msgid "" -"Hold down \"Control\", or \"Command\" on a Mac, to select more than one." -msgstr "Premi \"Control\" o \"Command\" en un Mac per escollir més d'un." +#: newforms/fields.py:513 +#: newforms/fields.py:589 +#: newforms/models.py:197 +msgid "Enter a list of values." +msgstr "Introdueixi una llista de valors." -#: db/models/fields/related.py:689 +#: newforms/fields.py:519 +#: newforms/models.py:203 #, python-format -msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid." -"Please enter valid %(self)s IDs. The values %(value)r are invalid." -msgstr "" -"Si us plau, introdueixi IDs de %(self)s vàlids. El valor %(value)r és " -"invàlid." -"Si us plau, introdueixi IDs de %(self)s vàlids. Els valors %(value)r són " -"invàlids." +msgid "Select a valid choice. %s is not one of the available choices." +msgstr "Esculli una opció vàlida; %s' no és una de les opcions vàlides." + +#~ msgid "" +#~ "This comment was posted by a user who has posted fewer than %(count)s " +#~ "comment:\n" +#~ "\n" +#~ "%(text)sThis comment was posted by a user who has posted fewer than %" +#~ "(count)s comments:\n" +#~ "\n" +#~ "%(text)s" +#~ msgstr "" +#~ "Aquest comentari el va enviar un usuari que ha enviat menys de %(count)s " +#~ "comentari:\n" +#~ "\n" +#~ "%(text)sAquest comentari el va enviar un usuari que ha enviat menys de %" +#~ "(count)s comentaris:\n" +#~ "\n" +#~ "%(text)s" +#~ msgid "AnonymousUser" +#~ msgstr "AnonymousUser" +#~ 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 " +#~ "digits." +#~ msgstr "" +#~ "Si us plau, introdueixi un número decimal vàlid amb la part entera amb " +#~ "com a màxim %s dígit.Si us plau, introdueixi un número decimal vàlid amb " +#~ "la part entera amb com a màxim %s dígits." +#~ msgid "" +#~ "Please enter a valid decimal number with at most %s decimal place.Please " +#~ "enter a valid decimal number with at most %s decimal places." +#~ msgstr "" +#~ "Si us plau, introdueixi un número decimal vàlid amb no més de %s dígit en " +#~ "la part decimal.Si us plau, introdueixi un número decimal vàlid amb no " +#~ "més de %s dígits en la part decimal." +#~ msgid "%d milliseconds" +#~ msgstr "%d milisegons" diff --git a/django/conf/locale/el/LC_MESSAGES/django.mo b/django/conf/locale/el/LC_MESSAGES/django.mo Binary files differindex a048d87976..cfd591b051 100644 --- a/django/conf/locale/el/LC_MESSAGES/django.mo +++ b/django/conf/locale/el/LC_MESSAGES/django.mo diff --git a/django/conf/locale/el/LC_MESSAGES/django.po b/django/conf/locale/el/LC_MESSAGES/django.po index d041a275e5..cc14eee072 100644 --- a/django/conf/locale/el/LC_MESSAGES/django.po +++ b/django/conf/locale/el/LC_MESSAGES/django.po @@ -1,20 +1,1220 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) 2006 and beyond -# This file is distributed under the same license as the PACKAGE package. +# translation of django.po to el +# Copyright (C) 2006 and beyond +# This file is distributed under the same license as the DJANGO package. # Panos Laganakos <panos.laganakos@gmail.com>, Mar 2006. # -#, fuzzy +# Dimitris Glezos <dimitris@glezos.com>, 2007. msgid "" msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" +"Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2006-05-16 10:13+0200\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: Orestis Markou <orestis@orestis.gr>\n" -"Language-Team: Greek\n" +"POT-Creation-Date: 2007-04-05 01:32+1000\n" +"PO-Revision-Date: 2007-09-03 04:19+0100\n" +"Last-Translator: Dimitris Glezos <dimitris@glezos.com>\n" +"Language-Team: el <fedora-trans-el@redhat.com>\n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" +"Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"X-Generator: KBabel 1.11.4\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: db/models/manipulators.py:307 +#, fuzzy, python-format +msgid "%(object)s with this %(type)s already exists for the given %(field)s." +msgstr "αντικείμενο με τύπος για πεδίο." + +#: db/models/manipulators.py:308 contrib/admin/views/main.py:335 +#: contrib/admin/views/main.py:337 contrib/admin/views/main.py:339 +msgid "and" +msgstr "και" + +#: db/models/fields/related.py:53 +#, python-format +msgid "Please enter a valid %s." +msgstr "Παρακαλούμε εισάγετε ένα έγκυρο %s." + +#: db/models/fields/related.py:642 +msgid "Separate multiple IDs with commas." +msgstr "Ξεχωρίστε πολλαπλά ΙD με κόμματα." + +#: db/models/fields/related.py:644 +#, fuzzy +msgid "Hold down \"Control\", or \"Command\" on a Mac, to select more than one." +msgstr "Αναμονή Έλεγχος ή Εντολή ενεργό a επιλογή περισσότερα ένα." + +#: db/models/fields/related.py:691 +#, python-format +msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid." +msgid_plural "Please enter valid %(self)s IDs. The values %(value)r are invalid." +msgstr[0] "" +"Παρακαλούμε εισάγετε ένα έγκυρο %(self)s IDs. Η τιμή %(value)r δεν είναι " +"έγκυρη." +msgstr[1] "" +"Παρακαλούμε εισάγετε ένα έγκυρο %(self)s IDs. Οι τιμές %(value)r δεν είναι " +"έγκυρες." + +#: db/models/fields/__init__.py:42 +#, fuzzy, python-format +msgid "%(optname)s with this %(fieldname)s already exists." +msgstr "με." + +#: db/models/fields/__init__.py:117 db/models/fields/__init__.py:274 +#: db/models/fields/__init__.py:610 db/models/fields/__init__.py:621 +#: oldforms/__init__.py:357 newforms/fields.py:80 newforms/fields.py:376 +#: newforms/fields.py:452 newforms/fields.py:463 newforms/models.py:178 +msgid "This field is required." +msgstr "Αυτό το πεδίο είναι απαραίτητο." + +#: db/models/fields/__init__.py:367 +msgid "This value must be an integer." +msgstr "Αυτή η τιμή πρέπει να είναι ένας ακέραιος." + +#: db/models/fields/__init__.py:402 +msgid "This value must be either True or False." +msgstr "Αυτή η τιμή πρέπει να είναι Αληθές ή Ψευδές." + +#: db/models/fields/__init__.py:423 +msgid "This field cannot be null." +msgstr "Αυτό το πεδίο δεν μπορεί να είναι κενό (null)." + +#: db/models/fields/__init__.py:457 core/validators.py:148 +msgid "Enter a valid date in YYYY-MM-DD format." +msgstr "Εισάγετε μία έγκυρη ημερομηνία στη μορφή ΧΧΧΧ-MM-ΗΗ." + +#: db/models/fields/__init__.py:526 core/validators.py:157 +msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format." +msgstr "Εισάγετε μία έγκυρη ημερομηνία/ώρα στη μορφή ΧΧΧΧ-MM-ΗΗ ΩΩ:ΛΛ." + +#: db/models/fields/__init__.py:630 +msgid "Enter a valid filename." +msgstr "Εισάγετε ένα έγκυρο όνομα αρχείου." + +#: db/models/fields/__init__.py:751 +#, fuzzy +msgid "This value must be either None, True or False." +msgstr "Αυτή η τιμή πρέπει να είναι Αληθές ή Ψευδές." + +#: conf/global_settings.py:39 +msgid "Arabic" +msgstr "Αραβικά" + +#: conf/global_settings.py:40 +msgid "Bengali" +msgstr "Μπενγκάλι" + +#: conf/global_settings.py:41 +msgid "Catalan" +msgstr "Καταλανικά" + +#: conf/global_settings.py:42 +msgid "Czech" +msgstr "Τσέχικα" + +#: conf/global_settings.py:43 +msgid "Welsh" +msgstr "Ουαλικά" + +#: conf/global_settings.py:44 +msgid "Danish" +msgstr "Δανέζικα" + +#: conf/global_settings.py:45 +msgid "German" +msgstr "Γερμανικά" + +#: conf/global_settings.py:46 +msgid "Greek" +msgstr "Ελληνικά" + +#: conf/global_settings.py:47 +msgid "English" +msgstr "Αγγλικά" + +#: conf/global_settings.py:48 +msgid "Spanish" +msgstr "Ισπανικά" + +#: conf/global_settings.py:49 +msgid "Argentinean Spanish" +msgstr "Ισπανικά Αργεντινής" + +#: conf/global_settings.py:50 +msgid "Finnish" +msgstr "Φινλανδικά" + +#: conf/global_settings.py:51 +msgid "French" +msgstr "Γαλλικά" + +#: conf/global_settings.py:52 +msgid "Galician" +msgstr "" + +#: conf/global_settings.py:53 +msgid "Hungarian" +msgstr "Ουγγρικά" + +#: conf/global_settings.py:54 +msgid "Hebrew" +msgstr "Εβραϊκά" + +#: conf/global_settings.py:55 +msgid "Icelandic" +msgstr "Ισλανδικά" + +#: conf/global_settings.py:56 +msgid "Italian" +msgstr "Ιταλικά" + +#: conf/global_settings.py:57 +msgid "Japanese" +msgstr "Γιαπωνέζικα" + +#: conf/global_settings.py:58 +msgid "Kannada" +msgstr "" + +#: conf/global_settings.py:59 +msgid "Latvian" +msgstr "" + +#: conf/global_settings.py:60 +msgid "Macedonian" +msgstr "Μακεδονικά" + +#: conf/global_settings.py:61 +msgid "Dutch" +msgstr "Ολλανδικά" + +#: conf/global_settings.py:62 +msgid "Norwegian" +msgstr "Νορβηγικά" + +#: conf/global_settings.py:63 +msgid "Polish" +msgstr "Πολωνικά" + +#: conf/global_settings.py:64 +msgid "Portugese" +msgstr "Πορτογαλικά" + +#: conf/global_settings.py:65 +msgid "Brazilian" +msgstr "Βραζιλιάνικα" + +#: conf/global_settings.py:66 +msgid "Romanian" +msgstr "Ρουμανικά" + +#: conf/global_settings.py:67 +msgid "Russian" +msgstr "Ρωσικά" + +#: conf/global_settings.py:68 +msgid "Slovak" +msgstr "Σλοβακικά" + +#: conf/global_settings.py:69 +msgid "Slovenian" +msgstr "Σλοβενικά" + +#: conf/global_settings.py:70 +msgid "Serbian" +msgstr "Σερβικά" + +#: conf/global_settings.py:71 +msgid "Swedish" +msgstr "Σουηδικά" + +#: conf/global_settings.py:72 +msgid "Tamil" +msgstr "Ταμιλικά" + +#: conf/global_settings.py:73 +msgid "Telugu" +msgstr "" + +#: conf/global_settings.py:74 +msgid "Turkish" +msgstr "Τουρκικά" + +#: conf/global_settings.py:75 +msgid "Ukrainian" +msgstr "Ουκρανικά" + +#: conf/global_settings.py:76 +msgid "Simplified Chinese" +msgstr "Απλοποιημένα Κινέζικα" + +#: conf/global_settings.py:77 +msgid "Traditional Chinese" +msgstr "Παραδοσιακά Κινέζικα" + +#: utils/timesince.py:12 +msgid "year" +msgid_plural "years" +msgstr[0] "χρόνος" +msgstr[1] "χρόνια" + +#: utils/timesince.py:13 +msgid "month" +msgid_plural "months" +msgstr[0] "μήνας" +msgstr[1] "μήνες" + +#: utils/timesince.py:14 +msgid "week" +msgid_plural "weeks" +msgstr[0] "εβδομάδα" +msgstr[1] "εβδομάδες" + +#: utils/timesince.py:15 +msgid "day" +msgid_plural "days" +msgstr[0] "ημέρα" +msgstr[1] "ημέρες" + +#: utils/timesince.py:16 +msgid "hour" +msgid_plural "hours" +msgstr[0] "ώρα" +msgstr[1] "ώρες" + +#: utils/timesince.py:17 +msgid "minute" +msgid_plural "minutes" +msgstr[0] "λεπτό" +msgstr[1] "λεπτά" + +#: utils/dates.py:6 +msgid "Monday" +msgstr "Δευτέρα" + +#: utils/dates.py:6 +msgid "Tuesday" +msgstr "Τρίτη" + +#: utils/dates.py:6 +msgid "Wednesday" +msgstr "Τετάρτη" + +#: utils/dates.py:6 +msgid "Thursday" +msgstr "Πέμπτη" + +#: utils/dates.py:6 +msgid "Friday" +msgstr "Παρασκευή" + +#: utils/dates.py:7 +msgid "Saturday" +msgstr "Σάββατο" + +#: utils/dates.py:7 +msgid "Sunday" +msgstr "Κυριακή" + +#: utils/dates.py:14 +msgid "January" +msgstr "Ιανουάριος" + +#: utils/dates.py:14 +msgid "February" +msgstr "Φεβρουάριος" + +#: utils/dates.py:14 utils/dates.py:27 +msgid "March" +msgstr "Μάρτιος" + +#: utils/dates.py:14 utils/dates.py:27 +msgid "April" +msgstr "Απρίλιος" + +#: utils/dates.py:14 utils/dates.py:27 +msgid "May" +msgstr "Μάιος" + +#: utils/dates.py:14 utils/dates.py:27 +msgid "June" +msgstr "Ιούνιος" + +#: utils/dates.py:15 utils/dates.py:27 +msgid "July" +msgstr "Ιούλιος" + +#: utils/dates.py:15 +msgid "August" +msgstr "Αύγουστος" + +#: utils/dates.py:15 +msgid "September" +msgstr "Σεπτέμβριος" + +#: utils/dates.py:15 +msgid "October" +msgstr "Οκτώβριος" + +#: utils/dates.py:15 +msgid "November" +msgstr "Νοέμβριος" + +#: utils/dates.py:16 +msgid "December" +msgstr "Δεκέμβριος" + +#: utils/dates.py:19 +msgid "jan" +msgstr "Ιαν" + +#: utils/dates.py:19 +msgid "feb" +msgstr "Φεβ" + +#: utils/dates.py:19 +msgid "mar" +msgstr "Μάρ" + +#: utils/dates.py:19 +msgid "apr" +msgstr "Απρ" + +#: utils/dates.py:19 +msgid "may" +msgstr "Μάι" + +#: utils/dates.py:19 +msgid "jun" +msgstr "Ιούν" + +#: utils/dates.py:20 +msgid "jul" +msgstr "Ιούλ" + +#: utils/dates.py:20 +msgid "aug" +msgstr "Αύγ" + +#: utils/dates.py:20 +msgid "sep" +msgstr "Σεπ" + +#: utils/dates.py:20 +msgid "oct" +msgstr "Οκτ" + +#: utils/dates.py:20 +msgid "nov" +msgstr "Νοέ" + +#: utils/dates.py:20 +msgid "dec" +msgstr "Δεκ" + +#: utils/dates.py:27 +msgid "Jan." +msgstr "Ιάν." + +#: utils/dates.py:27 +msgid "Feb." +msgstr "Φεβ." + +#: utils/dates.py:28 +msgid "Aug." +msgstr "Αύγ." + +#: utils/dates.py:28 +msgid "Sept." +msgstr "Σεπτ." + +#: utils/dates.py:28 +msgid "Oct." +msgstr "Οκτ." + +#: utils/dates.py:28 +msgid "Nov." +msgstr "Νοέ." + +#: utils/dates.py:28 +msgid "Dec." +msgstr "Δεκ." + +#: utils/dateformat.py:40 +msgid "p.m." +msgstr "μμ." + +#: utils/dateformat.py:41 +msgid "a.m." +msgstr "πμ." + +#: utils/dateformat.py:46 +msgid "PM" +msgstr "ΜΜ" + +#: utils/dateformat.py:47 +msgid "AM" +msgstr "ΠΜ" + +#: utils/dateformat.py:95 +msgid "midnight" +msgstr "μεσάνυχτα" + +#: utils/dateformat.py:97 +msgid "noon" +msgstr "μεσημέρι" + +#: utils/translation/trans_real.py:358 +msgid "DATE_FORMAT" +msgstr "j N Y" + +#: utils/translation/trans_real.py:359 +msgid "DATETIME_FORMAT" +msgstr "j N Y, P" + +#: utils/translation/trans_real.py:360 +msgid "TIME_FORMAT" +msgstr "P" + +#: utils/translation/trans_real.py:376 +msgid "YEAR_MONTH_FORMAT" +msgstr "F Y" + +#: utils/translation/trans_real.py:377 +msgid "MONTH_DAY_FORMAT" +msgstr "j F" + +#: oldforms/__init__.py:392 +#, python-format +msgid "Ensure your text is less than %s character." +msgid_plural "Ensure your text is less than %s characters." +msgstr[0] "Βεβαιωθείτε ότι το κείμενο σας έχει μέγεθος μικρότερο από %s χαρακτήρα." +msgstr[1] "Βεβαιωθείτε ότι το κείμενο σας έχει μέγεθος μικρότερο από %s χαρακτήρες." + +#: oldforms/__init__.py:397 +msgid "Line breaks are not allowed here." +msgstr "Δεν επιτρέπονται αλλαγές γραμμών εδώ." + +#: oldforms/__init__.py:498 oldforms/__init__.py:571 oldforms/__init__.py:610 +#, python-format +msgid "Select a valid choice; '%(data)s' is not in %(choices)s." +msgstr "Επιλέξτε μια έγκυρη επιλογή; Το '%(data)s' δεν είναι στα %(choices)s." + +#: oldforms/__init__.py:577 contrib/admin/filterspecs.py:150 +#: newforms/widgets.py:174 +msgid "Unknown" +msgstr "Άγνωστο" + +#: oldforms/__init__.py:577 contrib/admin/filterspecs.py:143 +#: newforms/widgets.py:174 +msgid "Yes" +msgstr "Ναι" + +#: oldforms/__init__.py:577 contrib/admin/filterspecs.py:143 +#: newforms/widgets.py:174 +msgid "No" +msgstr "Όχι" + +#: oldforms/__init__.py:672 core/validators.py:174 core/validators.py:445 +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" + +#: oldforms/__init__.py:674 +msgid "The submitted file is empty." +msgstr "Το αρχείο που υποβλήθηκε είναι κενό." + +#: oldforms/__init__.py:730 +msgid "Enter a whole number between -32,768 and 32,767." +msgstr "Εισάγετε έναν ακέραιο αριθμό μεταξύ -32,768 και 32,767." + +#: oldforms/__init__.py:740 +msgid "Enter a positive number." +msgstr "Εισάγετε ένα θετικό αριθμό." + +#: oldforms/__init__.py:750 +msgid "Enter a whole number between 0 and 32,767." +msgstr "Εισάγετε έναν ακέραιο αριθμό μεταξύ 0 και 32,767." + +#: contrib/localflavor/no/forms.py:15 +#, fuzzy +msgid "Enter a zip code in the format XXXX." +msgstr "Εισάγετε μία έγκυρη ώρα στη μορφή ΩΩ-ΛΛ." + +#: contrib/localflavor/no/forms.py:36 +#, fuzzy +msgid "Enter a valid Norwegian social security number." +msgstr "Παρακαλούμε εισάγετε έναν έγκυρο δεκαδικό αριθμό." + +#: contrib/localflavor/it/forms.py:14 contrib/localflavor/fr/forms.py:17 +#: contrib/localflavor/fi/forms.py:14 contrib/localflavor/de/forms.py:16 +#, fuzzy +msgid "Enter a zip code in the format XXXXX." +msgstr "Εισάγετε μία έγκυρη ώρα στη μορφή ΩΩ-ΛΛ." + +#: contrib/localflavor/jp/forms.py:21 +msgid "Enter a postal code in the format XXXXXXX or XXX-XXXX." +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:4 +msgid "Hokkaido" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:5 +msgid "Aomori" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:6 +#, fuzzy +msgid "Iwate" +msgstr "Ημ/νία:" + +#: contrib/localflavor/jp/jp_prefectures.py:7 +msgid "Miyagi" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:8 +msgid "Akita" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:9 +msgid "Yamagata" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:10 +msgid "Fukushima" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:11 +msgid "Ibaraki" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:12 +msgid "Tochigi" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:13 +msgid "Gunma" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:14 +msgid "Saitama" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:15 +msgid "Chiba" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:16 +#, fuzzy +msgid "Tokyo" +msgstr "Σήμερα" + +#: contrib/localflavor/jp/jp_prefectures.py:17 +msgid "Kanagawa" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:18 +msgid "Yamanashi" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:19 +msgid "Nagano" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:20 +msgid "Niigata" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:21 +msgid "Toyama" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:22 +msgid "Ishikawa" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:23 +msgid "Fukui" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:24 +msgid "Gifu" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:25 +msgid "Shizuoka" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:26 +msgid "Aichi" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:27 +msgid "Mie" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:28 +msgid "Shiga" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:29 +msgid "Kyoto" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:30 +msgid "Osaka" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:31 +msgid "Hyogo" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:32 +msgid "Nara" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:33 +msgid "Wakayama" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:34 +msgid "Tottori" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:35 +msgid "Shimane" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:36 +msgid "Okayama" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:37 +msgid "Hiroshima" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:38 +msgid "Yamaguchi" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:39 +msgid "Tokushima" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:40 +msgid "Kagawa" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:41 +msgid "Ehime" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:42 +msgid "Kochi" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:43 +msgid "Fukuoka" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:44 +msgid "Saga" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:45 +msgid "Nagasaki" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:46 +msgid "Kumamoto" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:47 +msgid "Oita" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:48 +msgid "Miyazaki" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:49 +msgid "Kagoshima" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:50 +msgid "Okinawa" +msgstr "" + +#: contrib/localflavor/br/forms.py:18 +#, fuzzy +msgid "Enter a zip code in the format XXXXX-XXX." +msgstr "Εισάγετε μία έγκυρη ώρα στη μορφή ΩΩ-ΛΛ." + +#: contrib/localflavor/br/forms.py:30 +#, fuzzy +msgid "Phone numbers must be in XX-XXXX-XXXX format." +msgstr "Τηλέφωνο μέσα είναι." + +#: contrib/localflavor/fi/forms.py:40 contrib/localflavor/fi/forms.py:46 +#, fuzzy +msgid "Enter a valid Finnish social security number." +msgstr "Εισάγετε ένα έγκυρο όνομα αρχείου." + +#: contrib/localflavor/uk/forms.py:18 +msgid "Enter a postcode. A space is required between the two postcode parts." +msgstr "" + +#: contrib/localflavor/de/forms.py:63 +#, fuzzy +msgid "" +"Enter a valid German identity card number in XXXXXXXXXXX-XXXXXXX-XXXXXXX-X " +"format" +msgstr "Γερμανικά" + +#: contrib/localflavor/de/de_states.py:5 +msgid "Baden-Wuerttemberg" +msgstr "" + +#: contrib/localflavor/de/de_states.py:6 +msgid "Bavaria" +msgstr "" + +#: contrib/localflavor/de/de_states.py:7 +#, fuzzy +msgid "Berlin" +msgstr "Βραζιλιάνικα" + +#: contrib/localflavor/de/de_states.py:8 +msgid "Brandenburg" +msgstr "" + +#: contrib/localflavor/de/de_states.py:9 +msgid "Bremen" +msgstr "" + +#: contrib/localflavor/de/de_states.py:10 +#, fuzzy +msgid "Hamburg" +msgstr "Αύγ" + +#: contrib/localflavor/de/de_states.py:11 +#, fuzzy +msgid "Hessen" +msgstr "μήνυμα" + +#: contrib/localflavor/de/de_states.py:12 +msgid "Mecklenburg-Western Pomerania" +msgstr "" + +#: contrib/localflavor/de/de_states.py:13 +msgid "Lower Saxony" +msgstr "" + +#: contrib/localflavor/de/de_states.py:14 +msgid "North Rhine-Westphalia" +msgstr "" + +#: contrib/localflavor/de/de_states.py:15 +msgid "Rhineland-Palatinate" +msgstr "" + +#: contrib/localflavor/de/de_states.py:16 +msgid "Saarland" +msgstr "" + +#: contrib/localflavor/de/de_states.py:17 +msgid "Saxony" +msgstr "" + +#: contrib/localflavor/de/de_states.py:18 +msgid "Saxony-Anhalt" +msgstr "" + +#: contrib/localflavor/de/de_states.py:19 +msgid "Schleswig-Holstein" +msgstr "" + +#: contrib/localflavor/de/de_states.py:20 +msgid "Thuringia" +msgstr "" + +#: contrib/localflavor/usa/forms.py:18 +msgid "Enter a zip code in the format XXXXX or XXXXX-XXXX." +msgstr "" + +#: contrib/localflavor/usa/forms.py:51 +msgid "Enter a valid U.S. Social Security number in XXX-XX-XXXX format." +msgstr "" + +#: contrib/sessions/models.py:68 +msgid "session key" +msgstr "κλειδί συνεδρίας" + +#: contrib/sessions/models.py:69 +msgid "session data" +msgstr "δεδομένα συνεδρίας" + +#: contrib/sessions/models.py:70 +msgid "expire date" +msgstr "ημερομηνία λήξης" + +#: contrib/sessions/models.py:74 +msgid "session" +msgstr "συνεδρία" + +#: contrib/sessions/models.py:75 +msgid "sessions" +msgstr "συνεδρίες" + +#: contrib/auth/forms.py:17 contrib/auth/forms.py:138 +msgid "The two password fields didn't match." +msgstr "Τα δύο πεδία συνθηματικών δεν ταιριάζουν." + +#: contrib/auth/forms.py:25 +msgid "A user with that username already exists." +msgstr "Ένας χρήστης με αυτό το όνομα χρήστη υπάρχει ήδη." + +#: contrib/auth/forms.py:53 +msgid "" +"Your Web browser doesn't appear to have cookies enabled. Cookies are " +"required for logging in." +msgstr "" +"Ο πλοηγητής σας δεν φαίνεται να έχει ενεργοποιημένα τα αρχεία cookie. Τα " +"αρχεία cookie απαιτούνται για να συνδεθείτε." + +#: contrib/auth/forms.py:60 contrib/admin/views/decorators.py:10 +msgid "" +"Please enter a correct username and password. Note that both fields are case-" +"sensitive." +msgstr "" +"Παρακαλούμε εισάγετε ένα σωστό όνομα χρήστη και συνθηματικό. Να σημειωθεί " +"ότι και τα δύο πεδία κάνουν διάκριση μεταξύ πεζών και κεφαλαίων." + +#: contrib/auth/forms.py:62 +msgid "This account is inactive." +msgstr "Αυτός ο λογαριασμός είναι ανενεργός." + +#: contrib/auth/forms.py:85 +#, fuzzy +msgid "" +"That e-mail address doesn't have an associated user account. Are you sure " +"you've registered?" +msgstr "χρήστης?" + +#: contrib/auth/forms.py:117 +#, fuzzy +msgid "The two 'new password' fields didn't match." +msgstr "συνθηματικό." + +#: contrib/auth/forms.py:124 +#, fuzzy +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "συνθηματικό." + +#: contrib/auth/views.py:39 +msgid "Logged out" +msgstr "Έγινε αποσύνδεση" + +#: contrib/auth/models.py:38 contrib/auth/models.py:57 +msgid "name" +msgstr "όνομα" + +#: contrib/auth/models.py:40 +msgid "codename" +msgstr "κωδικό όνομα" + +#: contrib/auth/models.py:42 +msgid "permission" +msgstr "δικαίωμα" + +#: contrib/auth/models.py:43 contrib/auth/models.py:58 +msgid "permissions" +msgstr "διακαιώματα" + +#: contrib/auth/models.py:60 +msgid "group" +msgstr "ομάδα" + +#: contrib/auth/models.py:61 contrib/auth/models.py:100 +msgid "groups" +msgstr "ομάδες" + +#: contrib/auth/models.py:90 +msgid "username" +msgstr "όνομα χρήστη" + +#: contrib/auth/models.py:90 +#, fuzzy +msgid "" +"Required. 30 characters or fewer. Alphanumeric characters only (letters, " +"digits and underscores)." +msgstr "Απαραίτητο." + +#: contrib/auth/models.py:91 +msgid "first name" +msgstr "όνομα" + +#: contrib/auth/models.py:92 +msgid "last name" +msgstr "επώνυμο" + +#: contrib/auth/models.py:93 +msgid "e-mail address" +msgstr "ηλεκτρονική διεύθυνση" + +#: contrib/auth/models.py:94 +msgid "password" +msgstr "συνθηματικό" + +#: contrib/auth/models.py:94 +#, fuzzy +msgid "" +"Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change " +"password form</a>." +msgstr "<a href=\"password/\"> συνθηματικό</a>." + +#: contrib/auth/models.py:95 +msgid "staff status" +msgstr "Κατάσταση προσωπικού" + +#: contrib/auth/models.py:95 +msgid "Designates whether the user can log into this admin site." +msgstr "Ορίζει αν ο χρήστης μπορεί να συνδεθεί στο χώρο διαχείρισης." + +#: contrib/auth/models.py:96 +msgid "active" +msgstr "ενεργό" + +#: contrib/auth/models.py:96 +#, fuzzy +msgid "" +"Designates whether this user can log into the Django admin. Unselect this " +"instead of deleting accounts." +msgstr "Ορίζει αν ο χρήστης μπορεί να συνδεθεί στο χώρο διαχείρισης." + +#: contrib/auth/models.py:97 +msgid "superuser status" +msgstr "κατάσταση υπερχρήστη" + +#: contrib/auth/models.py:97 +#, fuzzy +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "χρήστης διακαιώματα." + +#: contrib/auth/models.py:98 +msgid "last login" +msgstr "τελευταία σύνδεση" + +#: contrib/auth/models.py:99 +msgid "date joined" +msgstr "ημερομηνία σύνδεσης" + +#: contrib/auth/models.py:101 +#, fuzzy +msgid "" +"In addition to the permissions manually assigned, this user will also get " +"all permissions granted to each group he/she is in." +msgstr "Μέσα διακαιώματα χειρωνακτικά χρήστης get όλα διακαιώματα ομάδα είναι μέσα." + +#: contrib/auth/models.py:102 +msgid "user permissions" +msgstr "δικαιώματα χρήστη" + +#: contrib/auth/models.py:105 +msgid "user" +msgstr "χρήστης" + +#: contrib/auth/models.py:106 +msgid "users" +msgstr "χρήστες" + +#: contrib/auth/models.py:111 +msgid "Personal info" +msgstr "Προσωπικές πληροφορίες" + +#: contrib/auth/models.py:112 +msgid "Permissions" +msgstr "Δικαιώματα" + +#: contrib/auth/models.py:113 +msgid "Important dates" +msgstr "Σημαντικές ημερομηνίες" + +#: contrib/auth/models.py:114 +msgid "Groups" +msgstr "Ομάδες" + +#: contrib/auth/models.py:258 +msgid "message" +msgstr "μήνυμα" + +#: contrib/humanize/templatetags/humanize.py:17 +msgid "th" +msgstr "η" + +#: contrib/humanize/templatetags/humanize.py:17 +msgid "st" +msgstr "η" + +#: contrib/humanize/templatetags/humanize.py:17 +msgid "nd" +msgstr "η" + +#: contrib/humanize/templatetags/humanize.py:17 +msgid "rd" +msgstr "η" + +#: contrib/humanize/templatetags/humanize.py:47 +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f εκατομμύριο" +msgstr[1] "%(value).1f εκατομμύρια" + +#: contrib/humanize/templatetags/humanize.py:50 +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f δισεκατομμύριο" +msgstr[1] "%(value).1f δισεκατομμύρια" + +#: contrib/humanize/templatetags/humanize.py:53 +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f τρισεκατομμύριο" +msgstr[1] "%(value).1f τρισεκατομμύρια" + +#: contrib/humanize/templatetags/humanize.py:68 +msgid "one" +msgstr "ένα" + +#: contrib/humanize/templatetags/humanize.py:68 +msgid "two" +msgstr "δύο" + +#: contrib/humanize/templatetags/humanize.py:68 +msgid "three" +msgstr "τρία" + +#: contrib/humanize/templatetags/humanize.py:68 +msgid "four" +msgstr "τέσσερα" + +#: contrib/humanize/templatetags/humanize.py:68 +msgid "five" +msgstr "πέντε" + +#: contrib/humanize/templatetags/humanize.py:68 +msgid "six" +msgstr "έξι" + +#: contrib/humanize/templatetags/humanize.py:68 +msgid "seven" +msgstr "εφτά" + +#: contrib/humanize/templatetags/humanize.py:68 +msgid "eight" +msgstr "οκτώ" + +#: contrib/humanize/templatetags/humanize.py:68 +msgid "nine" +msgstr "εννιά" + +#: contrib/contenttypes/models.py:36 +msgid "python model class name" +msgstr "όνομα python model class" + +#: contrib/contenttypes/models.py:39 +msgid "content type" +msgstr "τύπος περιεχομένου" + +#: contrib/contenttypes/models.py:40 +msgid "content types" +msgstr "τύποι περιεχομένου" + +#: contrib/redirects/models.py:7 +msgid "redirect from" +msgstr "ανακατεύθυνση από" + +#: contrib/redirects/models.py:8 +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" +"Αυτό πρέπει να είναι ένα απόλυτο μονοπάτι, με εξαίρεση το όνομα χώρου. " +"Παράδειγμα: '/events/search/'." + +#: contrib/redirects/models.py:9 +msgid "redirect to" +msgstr "ανακατεύθυνση προς" + +#: contrib/redirects/models.py:10 +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"Αυτό πρέπει να είναι ένα απόλυτο μονοπάτι (όπως παραπάνω), ή ένα πλήρες URL " +"που αρχίζει με 'http://'." + +#: contrib/redirects/models.py:13 +msgid "redirect" +msgstr "ανακατεύθυνση" + +#: contrib/redirects/models.py:14 +msgid "redirects" +msgstr "ανακατευθύνσεις" + +#: contrib/flatpages/models.py:7 contrib/admin/views/doc.py:315 +msgid "URL" +msgstr "URL" + +#: contrib/flatpages/models.py:8 +msgid "Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" +"Παράδειγμα: '/about/contact/'. Βεβαιωθείτε ότι περιέχει καθέτους στην αρχή " +"και το τέλος." + +#: contrib/flatpages/models.py:9 +msgid "title" +msgstr "τίτλος" + +#: contrib/flatpages/models.py:10 +msgid "content" +msgstr "περιεχόμενο" + +#: contrib/flatpages/models.py:11 +msgid "enable comments" +msgstr "ενεργοποίηση σχολίων" + +#: contrib/flatpages/models.py:12 +msgid "template name" +msgstr "όνομα προτύπου" + +#: contrib/flatpages/models.py:13 +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"Παράδειγμα: 'flatpages/contact_page.html'. Αν δεν εισαχθεί, το σύστημα θα " +"χρησιμοποιήσει το 'flatpages/default.html'." + +#: contrib/flatpages/models.py:14 +msgid "registration required" +msgstr "απαιτείται εγγραφή" + +#: contrib/flatpages/models.py:14 +#, fuzzy +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "είναι μέσα χρήστες σελίδα." + +#: contrib/flatpages/models.py:18 +msgid "flat page" +msgstr "απλή σελίδα" + +#: contrib/flatpages/models.py:19 +msgid "flat pages" +msgstr "απλές σελίδες" #: contrib/comments/models.py:67 contrib/comments/models.py:166 msgid "object ID" @@ -31,7 +1231,7 @@ msgstr "σχόλιο" #: contrib/comments/models.py:70 msgid "rating #1" -msgstr "κατάταξη #1" +msgstr "βαθμολογία #1" #: contrib/comments/models.py:71 msgid "rating #2" @@ -73,30 +1273,29 @@ msgstr "ημερομηνία/ώρα υποβολής" msgid "is public" msgstr "είναι δημόσιο" -#: contrib/comments/models.py:85 contrib/admin/views/doc.py:289 +#: contrib/comments/models.py:85 contrib/admin/views/doc.py:304 msgid "IP address" -msgstr "IP διεύθυνση" +msgstr "διεύθυνση IP" #: contrib/comments/models.py:86 msgid "is removed" -msgstr "είναι διεγραμμένο" +msgstr "είναι διαγραμμένο" #: contrib/comments/models.py:86 msgid "" "Check this box if the comment is inappropriate. A \"This comment has been " "removed\" message will be displayed instead." msgstr "" -"Σημειώστε αυτό το κουτί εάν το σχόλιο είναι ανάρμοστο. Ένα Αυτό το σχόλιο " -"εσβήσθει\" μήνυμα θα εμφανιστεί αντί αυτού." +"Επιλέξτε αυτό το κουτί ελέγχου εάν το σχόλιο είναι ανάρμοστο. Ένα μήνυμα " +"\"Αυτό το σχόλιο διαγράφηκε\" θα εμφανιστεί στη θέση του." #: contrib/comments/models.py:91 -#, fuzzy msgid "comments" -msgstr "σχόλιο" +msgstr "σχόλια" #: contrib/comments/models.py:131 contrib/comments/models.py:207 msgid "Content object" -msgstr "" +msgstr "Αντικείμενο περιεχομένου" #: contrib/comments/models.py:159 #, python-format @@ -107,7 +1306,7 @@ msgid "" "\n" "http://%(domain)s%(url)s" msgstr "" -"Σχόλιο από τον/την %(user)s την %(date)s\n" +"Σχόλιο από %(user)s στις %(date)s\n" "\n" "%(comment)s\n" "\n" @@ -119,21 +1318,19 @@ msgstr "όνομα ατόμου" #: contrib/comments/models.py:171 msgid "ip address" -msgstr "ip διεύθυνση" +msgstr "διεύθυνση ip" #: contrib/comments/models.py:173 msgid "approved by staff" msgstr "εγκεκριμένο από το προσωπικό" #: contrib/comments/models.py:176 -#, fuzzy msgid "free comment" -msgstr "Ελεύθερο σχόλιο" +msgstr "ελεύθερο σχόλιο" #: contrib/comments/models.py:177 -#, fuzzy msgid "free comments" -msgstr "Ελεύθερα σχόλια" +msgstr "ελεύθερα σχόλια" #: contrib/comments/models.py:233 msgid "score" @@ -141,21 +1338,20 @@ msgstr "βαθμολογία" #: contrib/comments/models.py:234 msgid "score date" -msgstr "ημερομηνία βαθμολογίας" +msgstr "ημερομηνία βαθμολόγησης" #: contrib/comments/models.py:237 -#, fuzzy msgid "karma score" -msgstr "karma" +msgstr "σκορ κάρμα" #: contrib/comments/models.py:238 msgid "karma scores" -msgstr "karma" +msgstr "σκορ κάρμα" #: contrib/comments/models.py:242 #, python-format msgid "%(score)d rating by %(user)s" -msgstr "" +msgstr "%(score)d βαθμολογία από %(user)s" #: contrib/comments/models.py:258 #, python-format @@ -164,26 +1360,26 @@ msgid "" "\n" "%(text)s" msgstr "" -"Αυτο το σχόλιο σημειώθηκε απο %(user)s\n" +"Αυτό το σχόλιο σημειώθηκε από %(user)s\n" "\n" "%(text)s" #: contrib/comments/models.py:265 msgid "flag date" -msgstr "" +msgstr "ημερομηνία σημείωσης" #: contrib/comments/models.py:268 msgid "user flag" -msgstr "" +msgstr "σημείωση χρήστη" #: contrib/comments/models.py:269 msgid "user flags" -msgstr "" +msgstr "σημειώσεις χρήστη" #: contrib/comments/models.py:273 #, python-format msgid "Flag by %r" -msgstr "" +msgstr "Σημείωση από %r" #: contrib/comments/models.py:278 msgid "deletion date" @@ -191,35 +1387,105 @@ msgstr "ημερομηνία διαγραφής" #: contrib/comments/models.py:280 msgid "moderator deletion" -msgstr "" +msgstr "διαγραφή συντονιστή" #: contrib/comments/models.py:281 msgid "moderator deletions" -msgstr "" +msgstr "διαγραφές συντονιστή" #: contrib/comments/models.py:285 #, python-format msgid "Moderator deletion by %r" -msgstr "" +msgstr "Διαγραφή συντονιστή από %r" + +#: contrib/comments/templates/comments/form.html:6 +#: contrib/comments/templates/comments/form.html:8 +#: contrib/admin/templates/admin/login.html:17 +msgid "Username:" +msgstr "Όνομα χρήστη:" + +#: contrib/comments/templates/comments/form.html:6 +#: contrib/admin/templates/admin_doc/bookmarklets.html:4 +#: contrib/admin/templates/admin_doc/missing_docutils.html:4 +#: contrib/admin/templates/admin_doc/view_detail.html:4 +#: contrib/admin/templates/admin_doc/template_filter_index.html:5 +#: contrib/admin/templates/admin_doc/view_index.html:5 +#: contrib/admin/templates/admin_doc/template_tag_index.html:5 +#: contrib/admin/templates/admin_doc/model_detail.html:3 +#: contrib/admin/templates/admin_doc/model_index.html:5 +#: contrib/admin/templates/admin_doc/index.html:4 +#: contrib/admin/templates/admin_doc/template_detail.html:4 +#: contrib/admin/templates/admin/object_history.html:3 +#: contrib/admin/templates/admin/delete_confirmation.html:3 +#: contrib/admin/templates/admin/change_list.html:5 +#: contrib/admin/templates/admin/change_form.html:10 +#: contrib/admin/templates/admin/base.html:25 +#: contrib/admin/templates/admin/auth/user/change_password.html:9 +#: contrib/admin/templates/registration/password_change_form.html:3 +#: contrib/admin/templates/registration/password_change_done.html:3 +msgid "Log out" +msgstr "Αποσύνδεση" + +#: contrib/comments/templates/comments/form.html:8 +#: contrib/admin/templates/admin/login.html:20 +msgid "Password:" +msgstr "Συνθηματικό:" + +#: contrib/comments/templates/comments/form.html:8 +msgid "Forgotten your password?" +msgstr "Ξεχάσατε το συνθηματικό σας;" + +#: contrib/comments/templates/comments/form.html:12 +msgid "Ratings" +msgstr "Βαθμολογίες" + +#: contrib/comments/templates/comments/form.html:12 +#: contrib/comments/templates/comments/form.html:23 +msgid "Required" +msgstr "Απαραίτητο" + +#: contrib/comments/templates/comments/form.html:12 +#: contrib/comments/templates/comments/form.html:23 +msgid "Optional" +msgstr "Προαιρετικό" + +#: contrib/comments/templates/comments/form.html:23 +msgid "Post a photo" +msgstr "Στείλτε μια φωτογραφία" + +#: contrib/comments/templates/comments/form.html:28 +#: contrib/comments/templates/comments/freeform.html:5 +msgid "Comment:" +msgstr "Σχόλιο:" + +#: contrib/comments/templates/comments/form.html:35 +#: contrib/comments/templates/comments/freeform.html:10 +msgid "Preview comment" +msgstr "Προεπισκόπηση σχολίου" + +#: contrib/comments/templates/comments/freeform.html:4 +msgid "Your name:" +msgstr "Το όνομα σας:" #: contrib/comments/views/karma.py:19 msgid "Anonymous users cannot vote" -msgstr "Ανώνυμοι χρήστες δέν μπορούν να ψηφήσουν" +msgstr "Ανώνυμοι χρήστες δεν μπορούν να ψηφίσουν" #: contrib/comments/views/karma.py:23 msgid "Invalid comment ID" -msgstr "" +msgstr "Μη έγκυρο ID σχολίου" #: contrib/comments/views/karma.py:25 msgid "No voting for yourself" -msgstr "" +msgstr "Δεν επιτρέπεται ψήφος για τον εαυτό σας" -#: contrib/comments/views/comments.py:28 -msgid "" -"This rating is required because you've entered at least one other rating." -msgstr "Αυτή η βαθμολογία απαιτείται επειδή τουλάχιστον ακόμα μια βαθμολογία" +#: contrib/comments/views/comments.py:27 +msgid "This rating is required because you've entered at least one other rating." +msgstr "" +"Αυτή η βαθμολογία απαιτείται επειδή έχετε εισάγει τουλάχιστον μία ακόμη " +"βαθμολογία." -#: contrib/comments/views/comments.py:112 +#: contrib/comments/views/comments.py:111 #, python-format msgid "" "This comment was posted by a user who has posted fewer than %(count)s " @@ -232,110 +1498,71 @@ msgid_plural "" "\n" "%(text)s" msgstr[0] "" +"Αυτό το σχόλιο έχει αναρτηθεί από ένα χρήστη με λιγότερα από %(count)s " +"σχόλιο:\n" +"\n" +"%(text)s" msgstr[1] "" +"Αυτό το σχόλιο έχει αναρτηθεί από ένα χρήστη με λιγότερα από %(count)s " +"σχόλια:\n" +"\n" +"%(text)s" -#: contrib/comments/views/comments.py:117 +#: contrib/comments/views/comments.py:116 #, python-format msgid "" "This comment was posted by a sketchy user:\n" "\n" "%(text)s" msgstr "" +"Αυτό το σχόλιο αναρτήθηκε από έναν sketchy χρήστη:\n" +"\n" +"%(text)s" -#: contrib/comments/views/comments.py:189 +#: contrib/comments/views/comments.py:188 #: contrib/comments/views/comments.py:280 msgid "Only POSTs are allowed" -msgstr "" +msgstr "Επιτρέπονται μόνο POST υποβολές" -#: contrib/comments/views/comments.py:193 +#: contrib/comments/views/comments.py:192 #: contrib/comments/views/comments.py:284 msgid "One or more of the required fields wasn't submitted" -msgstr "Ένα ή περισσότερα από τα απαιτούμενα πεδία δεν υπεβλήθει" +msgstr "Ένα ή περισσότερα από τα απαιτούμενα πεδία δεν έχουν υποβληθεί" -#: contrib/comments/views/comments.py:197 +#: contrib/comments/views/comments.py:196 #: contrib/comments/views/comments.py:286 msgid "Somebody tampered with the comment form (security violation)" -msgstr "" +msgstr "Κάποιος έχει πειράξει τη φόρμα σχολιασμού (παραβίαση ασφάλειας)" -#: contrib/comments/views/comments.py:207 +#: contrib/comments/views/comments.py:206 #: contrib/comments/views/comments.py:292 +#, fuzzy msgid "" "The comment form had an invalid 'target' parameter -- the object ID was " "invalid" -msgstr "" +msgstr "σχόλιο αντικείμενο ID" #: contrib/comments/views/comments.py:257 #: contrib/comments/views/comments.py:321 +#, fuzzy msgid "The comment form didn't provide either 'preview' or 'post'" -msgstr "" - -#: contrib/comments/templates/comments/form.html:6 -#: contrib/comments/templates/comments/form.html:8 -#: contrib/admin/templates/admin/login.html:17 -msgid "Username:" -msgstr "Όνομα χρήστη:" +msgstr "σχόλιο t προεπισκόπηση ή" -#: contrib/comments/templates/comments/form.html:6 -#: contrib/admin/templates/admin/login.html:20 -msgid "Password:" -msgstr "Κωδικός" - -#: contrib/comments/templates/comments/form.html:6 -msgid "Forgotten your password?" -msgstr "Ξεχάσατε τον κωδικό σας;" - -#: contrib/comments/templates/comments/form.html:8 -#: contrib/admin/templates/admin/object_history.html:3 -#: contrib/admin/templates/admin/change_list.html:5 -#: contrib/admin/templates/admin/base.html:23 -#: contrib/admin/templates/admin/delete_confirmation.html:3 -#: contrib/admin/templates/admin/change_form.html:10 -#: contrib/admin/templates/registration/password_change_done.html:3 -#: contrib/admin/templates/registration/password_change_form.html:3 -#: contrib/admin/templates/admin_doc/bookmarklets.html:4 -#: contrib/admin/templates/admin_doc/view_detail.html:4 -#: contrib/admin/templates/admin_doc/template_tag_index.html:5 -#: contrib/admin/templates/admin_doc/template_detail.html:4 -#: contrib/admin/templates/admin_doc/template_filter_index.html:5 -#: contrib/admin/templates/admin_doc/missing_docutils.html:4 -#: contrib/admin/templates/admin_doc/view_index.html:5 -#: contrib/admin/templates/admin_doc/model_detail.html:3 -#: contrib/admin/templates/admin_doc/index.html:4 -#: contrib/admin/templates/admin_doc/model_index.html:5 -msgid "Log out" -msgstr "Αποσύνδεση" - -#: contrib/comments/templates/comments/form.html:12 -msgid "Ratings" -msgstr "Βαθμολογίες" - -#: contrib/comments/templates/comments/form.html:12 -#: contrib/comments/templates/comments/form.html:23 -msgid "Required" -msgstr "Απαραίτητο" - -#: contrib/comments/templates/comments/form.html:12 -#: contrib/comments/templates/comments/form.html:23 -msgid "Optional" -msgstr "Προαιρετικό" - -#: contrib/comments/templates/comments/form.html:23 -msgid "Post a photo" -msgstr "" +#: contrib/sites/models.py:10 +msgid "domain name" +msgstr "όνομα χώρου" -#: contrib/comments/templates/comments/form.html:27 -#: contrib/comments/templates/comments/freeform.html:5 -msgid "Comment:" -msgstr "Σχόλιο:" +#: contrib/sites/models.py:11 +msgid "display name" +msgstr "εμφανιζόμενο όνομα" -#: contrib/comments/templates/comments/form.html:32 -#: contrib/comments/templates/comments/freeform.html:9 -msgid "Preview comment" -msgstr "Προεπισκόπηση σχολίου" +#: contrib/sites/models.py:15 +msgid "site" +msgstr "ιστότοπος" -#: contrib/comments/templates/comments/freeform.html:4 -msgid "Your name:" -msgstr "Το όνομα σας:" +#: contrib/sites/models.py:16 +msgid "sites" +msgstr "ιστότοποι" #: contrib/admin/filterspecs.py:40 #, python-format @@ -347,13 +1574,13 @@ msgstr "" "<ul>\n" #: contrib/admin/filterspecs.py:70 contrib/admin/filterspecs.py:88 -#: contrib/admin/filterspecs.py:143 +#: contrib/admin/filterspecs.py:143 contrib/admin/filterspecs.py:169 msgid "All" msgstr "Όλα" #: contrib/admin/filterspecs.py:109 msgid "Any date" -msgstr "Όλες οι ημερομηνίες" +msgstr "Οποιαδήποτε ημερομηνία" #: contrib/admin/filterspecs.py:110 msgid "Today" @@ -361,325 +1588,247 @@ msgstr "Σήμερα" #: contrib/admin/filterspecs.py:113 msgid "Past 7 days" -msgstr "Τις προηγούμενες 7 ημέρες" +msgstr "Τελευταίες 7 ημέρες" #: contrib/admin/filterspecs.py:115 msgid "This month" -msgstr "Αυτό το μήνα" +msgstr "Αυτόν το μήνα" #: contrib/admin/filterspecs.py:117 msgid "This year" -msgstr "Αυτό το χρόνο" - -#: contrib/admin/filterspecs.py:143 -msgid "Yes" -msgstr "Ναί" - -#: contrib/admin/filterspecs.py:143 -msgid "No" -msgstr "Όχι" - -#: contrib/admin/filterspecs.py:150 -msgid "Unknown" -msgstr "Άγνωστο" +msgstr "Αυτόν το χρόνο" #: contrib/admin/models.py:16 msgid "action time" -msgstr "" +msgstr "ώρα ενέργειας" #: contrib/admin/models.py:19 msgid "object id" -msgstr "" +msgstr "id αντικειμένου" #: contrib/admin/models.py:20 msgid "object repr" -msgstr "" +msgstr "repr αντικειμένου" #: contrib/admin/models.py:21 msgid "action flag" -msgstr "" +msgstr "σημαία ενέργειας" #: contrib/admin/models.py:22 msgid "change message" -msgstr "αλλάξτε το μήνυμα" +msgstr "αλλαγή μηνύματος" #: contrib/admin/models.py:25 msgid "log entry" -msgstr "" +msgstr "εγγραφή καταγραφής" #: contrib/admin/models.py:26 msgid "log entries" -msgstr "" +msgstr "εγγραφές καταγραφής" -#: contrib/admin/templatetags/admin_list.py:228 +#: contrib/admin/templatetags/admin_list.py:247 msgid "All dates" msgstr "Όλες οι ημερομηνίες" -#: contrib/admin/views/decorators.py:9 contrib/auth/forms.py:36 -#: contrib/auth/forms.py:41 -msgid "" -"Please enter a correct username and password. Note that both fields are case-" -"sensitive." -msgstr "" -"Παρακαλώ εισάγετε ένα σωστό όνομα χρήστη και κωδικό. Να σημειωθεί ότι και τα " -"δύο πεδία είναι case-sensitive." +#: contrib/admin/templates/admin_doc/bookmarklets.html:3 +#: contrib/admin/templates/admin/500.html:4 +#: contrib/admin/templates/admin/invalid_setup.html:4 +#: contrib/admin/templates/admin/object_history.html:5 +#: contrib/admin/templates/admin/delete_confirmation.html:6 +#: contrib/admin/templates/admin/change_list.html:6 +#: contrib/admin/templates/admin/change_form.html:13 +#: contrib/admin/templates/admin/base.html:30 +#: contrib/admin/templates/admin/auth/user/change_password.html:12 +#: contrib/admin/templates/registration/logged_out.html:4 +#: contrib/admin/templates/registration/password_reset_done.html:4 +#: contrib/admin/templates/registration/password_change_form.html:4 +#: contrib/admin/templates/registration/password_change_done.html:4 +#: contrib/admin/templates/registration/password_reset_form.html:4 +msgid "Home" +msgstr "Αρχική" -#: contrib/admin/views/decorators.py:23 -#: contrib/admin/templates/admin/login.html:25 -msgid "Log in" -msgstr "Συνδεθείτε" +#: contrib/admin/templates/admin_doc/bookmarklets.html:3 +#: contrib/admin/templates/admin/object_history.html:3 +#: contrib/admin/templates/admin/delete_confirmation.html:3 +#: contrib/admin/templates/admin/change_list.html:5 +#: contrib/admin/templates/admin/change_form.html:10 +#: contrib/admin/templates/admin/base.html:25 +#: contrib/admin/templates/admin/auth/user/change_password.html:9 +#: contrib/admin/templates/registration/password_change_form.html:3 +#: contrib/admin/templates/registration/password_change_done.html:3 +msgid "Documentation" +msgstr "Τεκμηρίωση" -#: contrib/admin/views/decorators.py:61 -msgid "" -"Please log in again, because your session has expired. Don't worry: Your " -"submission has been saved." -msgstr "" -"Παρακαλώ ξανασυνδεθείτε, γιατί η session σας έληξε. Μην ανησυχείτε: Η " -"submission σας έχει αποθηκευτεί." +#: contrib/admin/templates/admin_doc/bookmarklets.html:3 +msgid "Bookmarklets" +msgstr "Σελιδοδείκτες" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:4 +#: contrib/admin/templates/admin_doc/missing_docutils.html:4 +#: contrib/admin/templates/admin_doc/view_detail.html:4 +#: contrib/admin/templates/admin_doc/template_filter_index.html:5 +#: contrib/admin/templates/admin_doc/view_index.html:5 +#: contrib/admin/templates/admin_doc/template_tag_index.html:5 +#: contrib/admin/templates/admin_doc/model_detail.html:3 +#: contrib/admin/templates/admin_doc/model_index.html:5 +#: contrib/admin/templates/admin_doc/index.html:4 +#: contrib/admin/templates/admin_doc/template_detail.html:4 +#: contrib/admin/templates/admin/object_history.html:3 +#: contrib/admin/templates/admin/delete_confirmation.html:3 +#: contrib/admin/templates/admin/change_list.html:5 +#: contrib/admin/templates/admin/change_form.html:10 +#: contrib/admin/templates/admin/base.html:25 +#: contrib/admin/templates/admin/auth/user/change_password.html:9 +#: contrib/admin/templates/admin/auth/user/change_password.html:15 +#: contrib/admin/templates/admin/auth/user/change_password.html:46 +#: contrib/admin/templates/registration/password_change_form.html:3 +#: contrib/admin/templates/registration/password_change_done.html:3 +msgid "Change password" +msgstr "Αλλαγή συνθηματικού" -#: contrib/admin/views/decorators.py:68 +#: contrib/admin/templates/admin_doc/bookmarklets.html:5 +msgid "Documentation bookmarklets" +msgstr "Σελιδοδείκτες τεκμηρίωσης" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:9 +#, fuzzy msgid "" -"Looks like your browser isn't configured to accept cookies. Please enable " -"cookies, reload this page, and try again." +"\n" +"<p class=\"help\">To install bookmarklets, drag the link to your bookmarks\n" +"toolbar, or right-click the link and add it to your bookmarks. Now you can\n" +"select the bookmarklet from any page in the site. Note that some of these\n" +"bookmarklets require you to be viewing the site from a computer designated\n" +"as \"internal\" (talk to your system administrator if you aren't sure if\n" +"your computer is \"internal\").</p>\n" msgstr "" -"Απ'οτι φαίνεται, ο φυλλομετρητής σας δεν έχει ρυθμιστεί να δέχεται cookies. " -"Παρακαλώ ενεργοποιείστε τα cookies, ξαναφορτώστε αυτή την σελίδα, και " -"δοκιμάστε ξανά." +"\n" +"<p class=\"help\"> δεσμός ή δεξιά δεσμός και αύξηση Τώρα υποφαινόμενο από " +"κάθε σελίδα μέσα site Σημείωση από υποφαινόμενο site από a σύστημα " +"υποφαινόμενο t είναι</p> n" -#: contrib/admin/views/decorators.py:82 -msgid "Usernames cannot contain the '@' character." -msgstr "Τα ονόματα των χρηστών δεν μπορόυν να περιέχουν τον χαρακτήρα '@'." +#: contrib/admin/templates/admin_doc/bookmarklets.html:19 +msgid "Documentation for this page" +msgstr "Τεκμηρίωση για αυτήν τη σελίδα" -#: contrib/admin/views/decorators.py:84 -#, python-format -msgid "Your e-mail address is not your username. Try '%s' instead." -msgstr "" -"Η ηλεκτρονική σας διεύθυνση δεν είναι το ονόμα χρήστη σας. Δοκιμάστε '%s' " -"έναντι αυτού." +#: contrib/admin/templates/admin_doc/bookmarklets.html:20 +#, fuzzy +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "Άλματα υποφαινόμενο από κάθε σελίδα τεκμηρίωση για σελίδα." -#: contrib/admin/views/main.py:226 -msgid "Site administration" -msgstr "Διαχείριση του Διαδικτυακού χώρου" +#: contrib/admin/templates/admin_doc/bookmarklets.html:22 +msgid "Show object ID" +msgstr "Εμφάνιση ID αντικειμένου" -#: contrib/admin/views/main.py:260 -#, python-format -msgid "The %(name)s \"%(obj)s\" was added successfully." -msgstr "Το %(name)s \"%(obj)s\" αποθηκεύτηκε επιτυχώς." +#: contrib/admin/templates/admin_doc/bookmarklets.html:23 +#, fuzzy +msgid "" +"Shows the content-type and unique ID for pages that represent a single " +"object." +msgstr "Περιεχόμενο τύπος και μοναδικό ID για σελίδες a single αντικείμενο." -#: contrib/admin/views/main.py:264 contrib/admin/views/main.py:348 -msgid "You may edit it again below." -msgstr "Μπορείτε να το επεξεργαστείτε ξανα παρακάτω." +#: contrib/admin/templates/admin_doc/bookmarklets.html:25 +msgid "Edit this object (current window)" +msgstr "Επεξεργασία αυτού του αντικειμένου (τρέχον παράθυρο)" -#: contrib/admin/views/main.py:272 contrib/admin/views/main.py:357 -#, python-format -msgid "You may add another %s below." -msgstr "Μπορείτε να προσθέσετε ακόμα ένα %s απο κάτω." +#: contrib/admin/templates/admin_doc/bookmarklets.html:26 +#, fuzzy +msgid "Jumps to the admin page for pages that represent a single object." +msgstr "Άλματα σελίδα για σελίδες a single αντικείμενο." -#: contrib/admin/views/main.py:290 -#, python-format -msgid "Add %s" -msgstr "Προσθήκη %s" +#: contrib/admin/templates/admin_doc/bookmarklets.html:28 +msgid "Edit this object (new window)" +msgstr "Επεξεργασία αυτού του αντικειμένου (νέο παράθυρο)" -#: contrib/admin/views/main.py:336 -#, python-format -msgid "Added %s." -msgstr "Προστέθηκε %s." +#: contrib/admin/templates/admin_doc/bookmarklets.html:29 +#, fuzzy +msgid "As above, but opens the admin page in a new window." +msgstr "σελίδα μέσα a νέο παράθυρο." -#: contrib/admin/views/main.py:336 contrib/admin/views/main.py:338 -#: contrib/admin/views/main.py:340 -msgid "and" -msgstr "και" +#: contrib/admin/templates/admin/submit_line.html:3 +#: contrib/admin/templates/admin/delete_confirmation.html:9 +msgid "Delete" +msgstr "Διαγραφή" -#: contrib/admin/views/main.py:338 -#, python-format -msgid "Changed %s." -msgstr "Επεξεργάσθηκε %s." +#: contrib/admin/templates/admin/submit_line.html:4 +msgid "Save as new" +msgstr "Αποθήκευση ως νέο" -#: contrib/admin/views/main.py:340 -#, python-format -msgid "Deleted %s." -msgstr "Διεγράφη %s." +#: contrib/admin/templates/admin/submit_line.html:5 +msgid "Save and add another" +msgstr "Αποθήκευση και προσθήκη καινούριου" -#: contrib/admin/views/main.py:343 -msgid "No fields changed." -msgstr "Κανένα πεδίο δεν άλλαξε." +#: contrib/admin/templates/admin/submit_line.html:6 +msgid "Save and continue editing" +msgstr "Αποθήκευση και συνέχεια επεξεργασίας" -#: contrib/admin/views/main.py:346 -#, python-format -msgid "The %(name)s \"%(obj)s\" was changed successfully." -msgstr "Το %(name)s \"%(obj)s\" επεξεργάσθηκε επιτυχώς." +#: contrib/admin/templates/admin/submit_line.html:7 +msgid "Save" +msgstr "Αποθήκευση" -#: contrib/admin/views/main.py:354 -#, python-format -msgid "" -"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below." -msgstr "" -"Το %(name)s \"%(obj)s\" αποθηκεύθηκε επιτυχώς. Μπορείτε να το επεξεργαστείτε πάλι παρακάτω." +#: contrib/admin/templates/admin/500.html:4 +msgid "Server error" +msgstr "Σφάλμα εξυπηρετητή" -#: contrib/admin/views/main.py:392 -#, python-format -msgid "Change %s" -msgstr "Αλλαγή %s" +#: contrib/admin/templates/admin/500.html:6 +msgid "Server error (500)" +msgstr "Σφάλμα εξυπηρετητή (500)" -#: contrib/admin/views/main.py:470 -#, python-format -msgid "One or more %(fieldname)s in %(name)s: %(obj)s" -msgstr "" +#: contrib/admin/templates/admin/500.html:9 +msgid "Server Error <em>(500)</em>" +msgstr "Σφάλμα εξυπηρετητή <em>(500)</em>" -#: contrib/admin/views/main.py:475 -#, python-format -msgid "One or more %(fieldname)s in %(name)s:" +#: contrib/admin/templates/admin/500.html:10 +msgid "" +"There's been an error. It's been reported to the site administrators via e-" +"mail and should be fixed shortly. Thanks for your patience." msgstr "" +"Υπήρξε ένα σφάλμα. Έχει αναφερθεί στους διαχειριστές του ιστότοπου μέσω ηλ. " +"ταχυδρομείου και θα πρέπει να επιδιορθωθεί σύντομα. Ευχαριστούμε για την " +"υπομονή σας." -#: contrib/admin/views/main.py:508 +#: contrib/admin/templates/admin/filter.html:2 #, python-format -msgid "The %(name)s \"%(obj)s\" was deleted successfully." -msgstr "" +msgid " By %(filter_title)s " +msgstr " Ανά %(filter_title)s " -#: contrib/admin/views/main.py:511 -msgid "Are you sure?" -msgstr "Είστε σίγουρος;" +#: contrib/admin/templates/admin/filters.html:4 +msgid "Filter" +msgstr "Φίλτρο" -#: contrib/admin/views/main.py:533 -#, python-format -msgid "Change history: %s" -msgstr "Ιστορικό Αλλαγών: %s" +#: contrib/admin/templates/admin/invalid_setup.html:8 +#, fuzzy +msgid "" +"Something's wrong with your database installation. Make sure the appropriate " +"database tables have been created, and make sure the database is readable by " +"the appropriate user." +msgstr "χρήστης." -#: contrib/admin/views/main.py:565 -#, python-format -msgid "Select %s" -msgstr "Επιλογή %s" +#: contrib/admin/templates/admin/search_form.html:8 +msgid "Go" +msgstr "Μετάβαση" -#: contrib/admin/views/main.py:565 +#: contrib/admin/templates/admin/search_form.html:10 #, python-format -msgid "Select %s to change" -msgstr "Επιλέξτε %s προς αλλαγή" - -#: contrib/admin/views/doc.py:277 contrib/admin/views/doc.py:286 -#: contrib/admin/views/doc.py:288 contrib/admin/views/doc.py:294 -#: contrib/admin/views/doc.py:295 contrib/admin/views/doc.py:297 -msgid "Integer" -msgstr "Ακέραιος" +msgid "1 result" +msgid_plural "%(counter)s results" +msgstr[0] "1 αποτέλεσμα" +msgstr[1] "%(counter)s αποτελέσματα" -#: contrib/admin/views/doc.py:278 -msgid "Boolean (Either True or False)" -msgstr "Boolean (Είτε Αληθές ή Ψέυδές)" - -#: contrib/admin/views/doc.py:279 contrib/admin/views/doc.py:296 +#: contrib/admin/templates/admin/search_form.html:10 #, python-format -msgid "String (up to %(maxlength)s)" -msgstr "" - -#: contrib/admin/views/doc.py:280 -msgid "Comma-separated integers" -msgstr "" - -#: contrib/admin/views/doc.py:281 -msgid "Date (without time)" -msgstr "Ημερομηνία (χωρίς την ώρα)" - -#: contrib/admin/views/doc.py:282 -msgid "Date (with time)" -msgstr "Ημερομηνία (με την ώρα)" - -#: contrib/admin/views/doc.py:283 -msgid "E-mail address" -msgstr "Ηλεκτρονική διεύθυνση" - -#: contrib/admin/views/doc.py:284 contrib/admin/views/doc.py:287 -msgid "File path" -msgstr "Τοποθεσία Αρχείου" - -#: contrib/admin/views/doc.py:285 -msgid "Decimal number" -msgstr "Δεκαδικός αριθμός" - -#: contrib/admin/views/doc.py:291 -msgid "Boolean (Either True, False or None)" -msgstr "" - -#: contrib/admin/views/doc.py:292 -msgid "Relation to parent model" -msgstr "Σχέση με το γονεϊκό μοντέλο" - -#: contrib/admin/views/doc.py:293 -msgid "Phone number" -msgstr "Αριθμός τηλεφώνου" - -#: contrib/admin/views/doc.py:298 -msgid "Text" -msgstr "Κείμενο" - -#: contrib/admin/views/doc.py:299 -msgid "Time" -msgstr "Ώρα" - -#: contrib/admin/views/doc.py:300 contrib/flatpages/models.py:7 -msgid "URL" -msgstr "" - -#: contrib/admin/views/doc.py:301 -msgid "U.S. state (two uppercase letters)" -msgstr "" - -#: contrib/admin/views/doc.py:302 -msgid "XML text" -msgstr "" - -#: contrib/admin/templates/admin/object_history.html:3 -#: contrib/admin/templates/admin/change_list.html:5 -#: contrib/admin/templates/admin/base.html:23 -#: contrib/admin/templates/admin/delete_confirmation.html:3 -#: contrib/admin/templates/admin/change_form.html:10 -#: contrib/admin/templates/registration/password_change_done.html:3 -#: contrib/admin/templates/registration/password_change_form.html:3 -#: contrib/admin/templates/admin_doc/bookmarklets.html:3 -msgid "Documentation" -msgstr "Τεκμηρίωση" - -#: contrib/admin/templates/admin/object_history.html:3 -#: contrib/admin/templates/admin/change_list.html:5 -#: contrib/admin/templates/admin/base.html:23 -#: contrib/admin/templates/admin/delete_confirmation.html:3 -#: contrib/admin/templates/admin/change_form.html:10 -#: contrib/admin/templates/registration/password_change_done.html:3 -#: contrib/admin/templates/registration/password_change_form.html:3 -#: contrib/admin/templates/admin_doc/bookmarklets.html:4 -#: contrib/admin/templates/admin_doc/view_detail.html:4 -#: contrib/admin/templates/admin_doc/template_tag_index.html:5 -#: contrib/admin/templates/admin_doc/template_detail.html:4 -#: contrib/admin/templates/admin_doc/template_filter_index.html:5 -#: contrib/admin/templates/admin_doc/missing_docutils.html:4 -#: contrib/admin/templates/admin_doc/view_index.html:5 -#: contrib/admin/templates/admin_doc/model_detail.html:3 -#: contrib/admin/templates/admin_doc/index.html:4 -#: contrib/admin/templates/admin_doc/model_index.html:5 -msgid "Change password" -msgstr "Αλλαγή κωδικού" +msgid "%(full_result_count)s total" +msgstr "%(full_result_count)s συνολικά" #: contrib/admin/templates/admin/object_history.html:5 -#: contrib/admin/templates/admin/500.html:4 -#: contrib/admin/templates/admin/change_list.html:6 -#: contrib/admin/templates/admin/base.html:28 -#: contrib/admin/templates/admin/delete_confirmation.html:6 -#: contrib/admin/templates/admin/change_form.html:13 -#: contrib/admin/templates/registration/password_change_done.html:4 -#: contrib/admin/templates/registration/password_reset_form.html:4 -#: contrib/admin/templates/registration/logged_out.html:4 -#: contrib/admin/templates/registration/password_reset_done.html:4 -#: contrib/admin/templates/registration/password_change_form.html:4 -#: contrib/admin/templates/admin_doc/bookmarklets.html:3 -msgid "Home" -msgstr "Home" - -#: contrib/admin/templates/admin/object_history.html:5 -#: contrib/admin/templates/admin/change_form.html:20 +#: contrib/admin/templates/admin/change_form.html:21 msgid "History" msgstr "Ιστορικό" #: contrib/admin/templates/admin/object_history.html:18 msgid "Date/time" -msgstr "Ημερομηνία/Ώρα" +msgstr "Ημερομηνία/ώρα" #: contrib/admin/templates/admin/object_history.html:19 msgid "User" @@ -687,62 +1836,98 @@ msgstr "Χρήστης" #: contrib/admin/templates/admin/object_history.html:20 msgid "Action" -msgstr "Δράση" +msgstr "Ενέργεια" #: contrib/admin/templates/admin/object_history.html:26 msgid "DATE_WITH_TIME_FULL" msgstr "N j, Y, P" #: contrib/admin/templates/admin/object_history.html:36 +#, fuzzy msgid "" "This object doesn't have a change history. It probably wasn't added via this " "admin site." -msgstr "" +msgstr "αντικείμενο t a t site." -#: contrib/admin/templates/admin/base_site.html:4 -msgid "Django site admin" -msgstr "Διαχειριστής ιστοσελίδας Django" +#: contrib/admin/templates/admin/delete_confirmation.html:14 +#, fuzzy, python-format +msgid "" +"Deleting the %(object_name)s '%(escaped_object)s' would result in deleting " +"related objects, but your account doesn't have permission to delete the " +"following types of objects:" +msgstr "Διαγραφή αντικείμενο μέσα λογαριασμός t δικαίωμα διαγραφή από:" -#: contrib/admin/templates/admin/base_site.html:7 -msgid "Django administration" -msgstr "Διαχείριση Django" +#: contrib/admin/templates/admin/delete_confirmation.html:21 +#, fuzzy, python-format +msgid "" +"Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? " +"All of the following related items will be deleted:" +msgstr "υποφαινόμενο υποφαινόμενο διαγραφή αντικείμενο Όλα από διαγράφηκε:" -#: contrib/admin/templates/admin/500.html:4 -msgid "Server error" -msgstr "Σφάλμα Διακομιστή" +#: contrib/admin/templates/admin/delete_confirmation.html:26 +msgid "Yes, I'm sure" +msgstr "Ναι, είμαι βέβαιος" -#: contrib/admin/templates/admin/500.html:6 -msgid "Server error (500)" -msgstr "Σφάλμα Διακομιστή (500)" +#: contrib/admin/templates/admin/pagination.html:10 +msgid "Show all" +msgstr "Εμφάνιση όλων" -#: contrib/admin/templates/admin/500.html:9 -msgid "Server Error <em>(500)</em>" -msgstr "Σφάλμα Διακομιστή <em>(500)</em>" +#: contrib/admin/templates/admin/change_list.html:12 +#, python-format +msgid "Add %(name)s" +msgstr "Προσθήκη %(name)s" -#: contrib/admin/templates/admin/500.html:10 -msgid "" -"There's been an error. It's been reported to the site administrators via e-" -"mail and should be fixed shortly. Thanks for your patience." -msgstr "" +#: contrib/admin/templates/admin/change_form.html:15 +#: contrib/admin/templates/admin/index.html:28 +msgid "Add" +msgstr "Προσθήκη" + +#: contrib/admin/templates/admin/change_form.html:22 +msgid "View on site" +msgstr "Προβολή στην ιστοσελίδα" + +#: contrib/admin/templates/admin/change_form.html:32 +#: contrib/admin/templates/admin/auth/user/change_password.html:24 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "Παρακαλούμε διορθώστε το παρακάτω λάθος." +msgstr[1] "Παρακαλούμε διορθώστε τα παρακάτω λάθη." + +#: contrib/admin/templates/admin/change_form.html:50 +msgid "Ordering" +msgstr "Ταξινόμηση" + +#: contrib/admin/templates/admin/change_form.html:53 +msgid "Order:" +msgstr "Ταξινόμηση:" + +#: contrib/admin/templates/admin/base.html:25 +msgid "Welcome," +msgstr "Καλωσήρθατε," #: contrib/admin/templates/admin/404.html:4 #: contrib/admin/templates/admin/404.html:8 msgid "Page not found" -msgstr "Η σελίδα δε βρέθηκε." +msgstr "Η σελίδα δε βρέθηκε" #: contrib/admin/templates/admin/404.html:10 msgid "We're sorry, but the requested page could not be found." -msgstr "" +msgstr "Λυπόμαστε, αλλά η σελίδα που ζητήθηκε δε μπόρεσε να βρεθεί." + +#: contrib/admin/templates/admin/login.html:25 +#: contrib/admin/views/decorators.py:24 +msgid "Log in" +msgstr "Σύνδεση" #: contrib/admin/templates/admin/index.html:17 #, python-format msgid "Models available in the %(name)s application." msgstr "Διαθέσιμα μοντέλα στην εφαρμογή %(name)s." -#: contrib/admin/templates/admin/index.html:28 -#: contrib/admin/templates/admin/change_form.html:15 -msgid "Add" -msgstr "Προσθήκη" +#: contrib/admin/templates/admin/index.html:18 +#, python-format +msgid "%(name)s" +msgstr "%(name)s" #: contrib/admin/templates/admin/index.html:34 msgid "Change" @@ -750,1172 +1935,834 @@ msgstr "Επεξεργασία" #: contrib/admin/templates/admin/index.html:44 msgid "You don't have permission to edit anything." -msgstr "Δεν έχετε άδεια να επεξεργαστείτε τίποτα." +msgstr "Δεν έχετε δικαίωμα να επεξεργαστείτε τίποτα." #: contrib/admin/templates/admin/index.html:52 msgid "Recent Actions" -msgstr "Πρόσφατες Πράξεις" +msgstr "Πρόσφατες ενέργειες" #: contrib/admin/templates/admin/index.html:53 msgid "My Actions" -msgstr "Οι πράξεις μου" +msgstr "Οι ενέργειες μου" #: contrib/admin/templates/admin/index.html:57 msgid "None available" msgstr "Κανένα διαθέσιμο" -#: contrib/admin/templates/admin/change_list.html:11 -#, python-format -msgid "Add %(name)s" -msgstr "Προσθήκη %(name)s" +#: contrib/admin/templates/admin/base_site.html:4 +msgid "Django site admin" +msgstr "Διαχειριστής ιστότοπου Django" -#: contrib/admin/templates/admin/login.html:22 -msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?" -msgstr "<a href=\"/password_reset/\">Ξεχάσατε τον κωδικό σας;</a> " +#: contrib/admin/templates/admin/base_site.html:7 +msgid "Django administration" +msgstr "Διαχείριση Django" -#: contrib/admin/templates/admin/base.html:23 -msgid "Welcome," -msgstr "Καλωσήρθατε," +#: contrib/admin/templates/admin/auth/user/add_form.html:6 +#, fuzzy +msgid "" +"First, enter a username and password. Then, you'll be able to edit more user " +"options." +msgstr "όνομα χρήστη συνθηματικό χρήστης." -#: contrib/admin/templates/admin/delete_confirmation.html:9 -#: contrib/admin/templates/admin/submit_line.html:3 -msgid "Delete" -msgstr "Διαγραφή" +#: contrib/admin/templates/admin/auth/user/add_form.html:12 +msgid "Username" +msgstr "Όνομα χρήστη" -#: contrib/admin/templates/admin/delete_confirmation.html:14 -#, python-format -msgid "" -"Deleting the %(object_name)s '%(object)s' would result in deleting related " -"objects, but your account doesn't have permission to delete the following " -"types of objects:" -msgstr "" +#: contrib/admin/templates/admin/auth/user/add_form.html:18 +#: contrib/admin/templates/admin/auth/user/change_password.html:34 +msgid "Password" +msgstr "Συνθηματικό" -#: contrib/admin/templates/admin/delete_confirmation.html:21 -#, python-format -msgid "" -"Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of " -"the following related items will be deleted:" -msgstr "" +#: contrib/admin/templates/admin/auth/user/add_form.html:23 +#: contrib/admin/templates/admin/auth/user/change_password.html:39 +msgid "Password (again)" +msgstr "Συνθηματικό (ξανά)" -#: contrib/admin/templates/admin/delete_confirmation.html:26 -msgid "Yes, I'm sure" -msgstr "Ναι, είμαι σίγουρος" +#: contrib/admin/templates/admin/auth/user/add_form.html:24 +#: contrib/admin/templates/admin/auth/user/change_password.html:40 +msgid "Enter the same password as above, for verification." +msgstr "Εισάγετε το ίδιο συνθηματικό όπως παραπάνω, για λόγους επιβεβαίωσης." -#: contrib/admin/templates/admin/filter.html:2 +#: contrib/admin/templates/admin/auth/user/change_password.html:28 #, python-format -msgid " By %(title)s " -msgstr "" +#, fuzzy +msgid "Enter a new password for the user <strong>%(username)s</strong>." +msgstr "συνθηματικό χρήστης<strong> όνομα χρήστη</strong>." -#: contrib/admin/templates/admin/search_form.html:8 -msgid "Go" -msgstr "Πήγαινε" +#: contrib/admin/templates/widget/file.html:2 +msgid "Currently:" +msgstr "Τρέχουσα:" -#: contrib/admin/templates/admin/change_form.html:21 -msgid "View on site" -msgstr "Προβολή στην ιστοσελίδα" +#: contrib/admin/templates/widget/file.html:3 +msgid "Change:" +msgstr "Αλλαγή:" -#: contrib/admin/templates/admin/change_form.html:30 -msgid "Please correct the error below." -msgid_plural "Please correct the errors below." -msgstr[0] "Παρακαλώ διορθώστε το παρακάτω λάθος." -msgstr[1] "Παρακαλώ διορθώστε τα παρακάτω λάθη." +#: contrib/admin/templates/widget/date_time.html:3 +msgid "Date:" +msgstr "Ημ/νία:" -#: contrib/admin/templates/admin/change_form.html:48 -msgid "Ordering" -msgstr "Σειρά" +#: contrib/admin/templates/widget/date_time.html:4 +msgid "Time:" +msgstr "Ώρα:" -#: contrib/admin/templates/admin/change_form.html:51 -msgid "Order:" -msgstr "Σειρά:" +#: contrib/admin/templates/registration/logged_out.html:8 +msgid "Thanks for spending some quality time with the Web site today." +msgstr "Ευχαριστούμε που διαθέσατε κάποιο ποιοτικό χρόνο στον ιστότοπο σήμερα." -#: contrib/admin/templates/admin/submit_line.html:4 -msgid "Save as new" -msgstr "Αποθήκευση καινούριου" +#: contrib/admin/templates/registration/logged_out.html:10 +msgid "Log in again" +msgstr "Σύνδεση ξανά" -#: contrib/admin/templates/admin/submit_line.html:5 -msgid "Save and add another" -msgstr "Αποθήκευση και προσθήκη καινούριου." +#: contrib/admin/templates/registration/password_reset_email.html:2 +#, fuzzy +msgid "You're receiving this e-mail because you requested a password reset" +msgstr "συνθηματικό" -#: contrib/admin/templates/admin/submit_line.html:6 -msgid "Save and continue editing" -msgstr "Αποθήκευση και συνέχεια επεξεργασίας" +#: contrib/admin/templates/registration/password_reset_email.html:3 +#, fuzzy, python-format +msgid "for your user account at %(site_name)s" +msgstr "για χρήστης λογαριασμός σε" -#: contrib/admin/templates/admin/submit_line.html:7 -msgid "Save" -msgstr "Αποθήκευση" +#: contrib/admin/templates/registration/password_reset_email.html:5 +#, fuzzy, python-format +msgid "Your new password is: %(new_password)s" +msgstr "νέο συνθηματικό είναι" -#: contrib/admin/templates/registration/password_change_done.html:4 -#: contrib/admin/templates/registration/password_change_form.html:4 -#: contrib/admin/templates/registration/password_change_form.html:6 -#: contrib/admin/templates/registration/password_change_form.html:10 -msgid "Password change" -msgstr "Αλλαγή Κωδικού" +#: contrib/admin/templates/registration/password_reset_email.html:7 +#, fuzzy +msgid "Feel free to change this password by going to this page:" +msgstr "συνθηματικό από σελίδα:" -#: contrib/admin/templates/registration/password_change_done.html:6 -#: contrib/admin/templates/registration/password_change_done.html:10 -msgid "Password change successful" -msgstr "Αλλαγή κωδικού επιτυχής" +#: contrib/admin/templates/registration/password_reset_email.html:11 +#, fuzzy +msgid "Your username, in case you've forgotten:" +msgstr "όνομα χρήστη μέσα υποφαινόμενο:" -#: contrib/admin/templates/registration/password_change_done.html:12 -msgid "Your password was changed." -msgstr "Ο κωδίκός σας άλλαξε." +#: contrib/admin/templates/registration/password_reset_email.html:13 +#, fuzzy +msgid "Thanks for using our site!" +msgstr "Ευχαριστώ για site!" + +#: contrib/admin/templates/registration/password_reset_email.html:15 +#, python-format +#, fuzzy +msgid "The %(site_name)s team" +msgstr "ιστότοπος όνομα" +#: contrib/admin/templates/registration/password_reset_done.html:4 #: contrib/admin/templates/registration/password_reset_form.html:4 #: contrib/admin/templates/registration/password_reset_form.html:6 #: contrib/admin/templates/registration/password_reset_form.html:10 -#: contrib/admin/templates/registration/password_reset_done.html:4 msgid "Password reset" -msgstr "Επαναφορά κωδικού" - -#: contrib/admin/templates/registration/password_reset_form.html:12 -msgid "" -"Forgotten your password? Enter your e-mail address below, and we'll reset " -"your password and e-mail the new one to you." -msgstr "" - -#: contrib/admin/templates/registration/password_reset_form.html:16 -msgid "E-mail address:" -msgstr "E-mail διεύθυνση:" - -#: contrib/admin/templates/registration/password_reset_form.html:16 -msgid "Reset my password" -msgstr "Επαναφορά του κωδικού μου" - -#: contrib/admin/templates/registration/logged_out.html:8 -msgid "Thanks for spending some quality time with the Web site today." -msgstr "" -"Ευχαριστούμε που διαθέσατε χρόνο στο να βελτίωσετε την ιστοσελίδα σήμερα." - -#: contrib/admin/templates/registration/logged_out.html:10 -msgid "Log in again" -msgstr "Εισαγωγή ξανά" +msgstr "Επαναφορά συνθηματικού" #: contrib/admin/templates/registration/password_reset_done.html:6 #: contrib/admin/templates/registration/password_reset_done.html:10 msgid "Password reset successful" -msgstr "" +msgstr "Επιτυχής επαναφορά συνθηματικού" #: contrib/admin/templates/registration/password_reset_done.html:12 msgid "" "We've e-mailed a new password to the e-mail address you submitted. You " "should be receiving it shortly." msgstr "" +"Ένα νέο συνθηματικό έχει αποσταλεί στην ηλεκτρονική διεύθυνση που έχετε " +"επιλέξει. Θα πρέπει να το παραλάβετε πολύ σύντομα." + +#: contrib/admin/templates/registration/password_change_form.html:4 +#: contrib/admin/templates/registration/password_change_form.html:6 +#: contrib/admin/templates/registration/password_change_form.html:10 +#: contrib/admin/templates/registration/password_change_done.html:4 +msgid "Password change" +msgstr "Αλλαγή συνθηματικού" #: contrib/admin/templates/registration/password_change_form.html:12 msgid "" "Please enter your old password, for security's sake, and then enter your new " "password twice so we can verify you typed it in correctly." msgstr "" +"Παρακαλούμε εισάγετε το παλιό σας συνθηματικό, για λόγους ασφάλειας, και " +"κατόπιν εισάγετε το νέο σας συνθηματικό δύο φορές ούτως ώστε να " +"πιστοποιήσουμε ότι το πληκτρολογήσατε σωστά." #: contrib/admin/templates/registration/password_change_form.html:17 msgid "Old password:" -msgstr "Παλιός κωδικός:" +msgstr "Παλιό συνθηματικό:" #: contrib/admin/templates/registration/password_change_form.html:19 msgid "New password:" -msgstr "Νέος κωδικός:" +msgstr "Νέο συνθηματικό:" #: contrib/admin/templates/registration/password_change_form.html:21 msgid "Confirm password:" -msgstr "Επιβεβαίωση κωδικού" +msgstr "Επιβεβαίωση συνθηματικού:" #: contrib/admin/templates/registration/password_change_form.html:23 msgid "Change my password" -msgstr "Αλλαγή του κωδικού μου" +msgstr "Αλλαγή του συνθηματικού μου" -#: contrib/admin/templates/registration/password_reset_email.html:2 -msgid "You're receiving this e-mail because you requested a password reset" -msgstr "" +#: contrib/admin/templates/registration/password_change_done.html:6 +#: contrib/admin/templates/registration/password_change_done.html:10 +msgid "Password change successful" +msgstr "Επιτυχής αλλαγή συνθηματικού" -#: contrib/admin/templates/registration/password_reset_email.html:3 -#, python-format -msgid "for your user account at %(site_name)s" -msgstr "" +#: contrib/admin/templates/registration/password_change_done.html:12 +msgid "Your password was changed." +msgstr "Το συνθηματικό σας έχει αλλαχτεί." -#: contrib/admin/templates/registration/password_reset_email.html:5 -#, python-format -msgid "Your new password is: %(new_password)s" +#: contrib/admin/templates/registration/password_reset_form.html:12 +msgid "" +"Forgotten your password? Enter your e-mail address below, and we'll reset " +"your password and e-mail the new one to you." msgstr "" +"Έχετε ξεχάσει το συνθηματικό σας; Εισάγετε παρακάτω την ηλεκτρονική σας " +"διεύθυνση, και θα επαναφέρουμε το συνθηματικό σας, αποστέλλοντας το " +"καινούριο στην ηλ. σας διεύθυνση." -#: contrib/admin/templates/registration/password_reset_email.html:7 -msgid "Feel free to change this password by going to this page:" -msgstr "" +#: contrib/admin/templates/registration/password_reset_form.html:16 +msgid "E-mail address:" +msgstr "Ηλεκτρονική διεύθυνση:" -#: contrib/admin/templates/registration/password_reset_email.html:11 -msgid "Your username, in case you've forgotten:" -msgstr "" +#: contrib/admin/templates/registration/password_reset_form.html:16 +msgid "Reset my password" +msgstr "Επαναφορά του συνθηματικού μου" -#: contrib/admin/templates/registration/password_reset_email.html:13 -msgid "Thanks for using our site!" -msgstr "" +#: contrib/admin/views/main.py:223 +msgid "Site administration" +msgstr "Διαχείριση του ιστότοπου" -#: contrib/admin/templates/registration/password_reset_email.html:15 +#: contrib/admin/views/main.py:257 contrib/admin/views/auth.py:19 #, python-format -msgid "The %(site_name)s team" -msgstr "" - -#: contrib/admin/templates/admin_doc/bookmarklets.html:3 -msgid "Bookmarklets" -msgstr "" - -#: contrib/admin/templates/admin_doc/bookmarklets.html:5 -msgid "Documentation bookmarklets" -msgstr "" +msgid "The %(name)s \"%(obj)s\" was added successfully." +msgstr "Το %(name)s \"%(obj)s\" αποθηκεύτηκε με επιτυχία." -#: contrib/admin/templates/admin_doc/bookmarklets.html:9 -msgid "" -"\n" -"<p class=\"help\">To install bookmarklets, drag the link to your bookmarks\n" -"toolbar, or right-click the link and add it to your bookmarks. Now you can\n" -"select the bookmarklet from any page in the site. Note that some of these\n" -"bookmarklets require you to be viewing the site from a computer designated\n" -"as \"internal\" (talk to your system administrator if you aren't sure if\n" -"your computer is \"internal\").</p>\n" -msgstr "" +#: contrib/admin/views/main.py:261 contrib/admin/views/main.py:347 +#: contrib/admin/views/auth.py:24 +msgid "You may edit it again below." +msgstr "Μπορείτε να το επεξεργαστείτε ξανά παρακάτω." -#: contrib/admin/templates/admin_doc/bookmarklets.html:19 -msgid "Documentation for this page" -msgstr "" +#: contrib/admin/views/main.py:271 contrib/admin/views/main.py:356 +#, python-format +msgid "You may add another %s below." +msgstr "Μπορείτε να προσθέσετε ακόμα ένα %s παρακάτω." -#: contrib/admin/templates/admin_doc/bookmarklets.html:20 -msgid "" -"Jumps you from any page to the documentation for the view that generates " -"that page." -msgstr "" +#: contrib/admin/views/main.py:289 +#, python-format +msgid "Add %s" +msgstr "Προσθήκη %s" -#: contrib/admin/templates/admin_doc/bookmarklets.html:22 -msgid "Show object ID" -msgstr "" +#: contrib/admin/views/main.py:335 +#, python-format +msgid "Added %s." +msgstr "Το %s προστέθηκε." -#: contrib/admin/templates/admin_doc/bookmarklets.html:23 -msgid "" -"Shows the content-type and unique ID for pages that represent a single " -"object." -msgstr "" +#: contrib/admin/views/main.py:337 +#, python-format +msgid "Changed %s." +msgstr "Έγινε επεξεργασία του %s." -#: contrib/admin/templates/admin_doc/bookmarklets.html:25 -msgid "Edit this object (current window)" -msgstr "" +#: contrib/admin/views/main.py:339 +#, python-format +msgid "Deleted %s." +msgstr "Το %s διεγράφη." -#: contrib/admin/templates/admin_doc/bookmarklets.html:26 -msgid "Jumps to the admin page for pages that represent a single object." -msgstr "" +#: contrib/admin/views/main.py:342 +msgid "No fields changed." +msgstr "Κανένα πεδίο δεν άλλαξε." -#: contrib/admin/templates/admin_doc/bookmarklets.html:28 -msgid "Edit this object (new window)" -msgstr "" +#: contrib/admin/views/main.py:345 +#, python-format +msgid "The %(name)s \"%(obj)s\" was changed successfully." +msgstr "Το %(name)s \"%(obj)s\" αλλάχτηκε με επιτυχία." -#: contrib/admin/templates/admin_doc/bookmarklets.html:29 -msgid "As above, but opens the admin page in a new window." +#: contrib/admin/views/main.py:353 +#, python-format +msgid "The %(name)s \"%(obj)s\" was added successfully. You may edit it again below." msgstr "" +"Το %(name)s \"%(obj)s\" αποθηκεύτηκε με επιτυχία. Μπορείτε να το " +"επεξεργαστείτε πάλι παρακάτω." -#: contrib/admin/templates/widget/date_time.html:3 -msgid "Date:" -msgstr "Ημ/νία:" - -#: contrib/admin/templates/widget/date_time.html:4 -msgid "Time:" -msgstr " Ώρα:" +#: contrib/admin/views/main.py:391 +#, python-format +msgid "Change %s" +msgstr "Αλλαγή του %s" -#: contrib/admin/templates/widget/file.html:2 -msgid "Currently:" -msgstr "Τρέχον:" +#: contrib/admin/views/main.py:476 +#, python-format +msgid "One or more %(fieldname)s in %(name)s: %(obj)s" +msgstr "Ένα ή περισσότερα %(fieldname)s στο %(name)s: %(obj)s" -#: contrib/admin/templates/widget/file.html:3 -msgid "Change:" -msgstr "Αλλαγή:" +#: contrib/admin/views/main.py:481 +#, python-format +msgid "One or more %(fieldname)s in %(name)s:" +msgstr "Ένα ή περισσότερα %(fieldname)s στο %(name)s:" -#: contrib/redirects/models.py:7 -msgid "redirect from" -msgstr "" +#: contrib/admin/views/main.py:514 +#, python-format +msgid "The %(name)s \"%(obj)s\" was deleted successfully." +msgstr "Το %(name)s \"%(obj)s\" διαγράφηκε με επιτυχία." -#: contrib/redirects/models.py:8 -msgid "" -"This should be an absolute path, excluding the domain name. Example: '/" -"events/search/'." -msgstr "" +#: contrib/admin/views/main.py:517 +msgid "Are you sure?" +msgstr "Είστε σίγουροι;" -#: contrib/redirects/models.py:9 -msgid "redirect to" -msgstr "" +#: contrib/admin/views/main.py:539 +#, python-format +msgid "Change history: %s" +msgstr "Ιστορικό αλλαγών: %s" -#: contrib/redirects/models.py:10 -msgid "" -"This can be either an absolute path (as above) or a full URL starting with " -"'http://'." -msgstr "" +#: contrib/admin/views/main.py:573 +#, python-format +msgid "Select %s" +msgstr "Επιλέξτε %s" -#: contrib/redirects/models.py:12 -msgid "redirect" -msgstr "" +#: contrib/admin/views/main.py:573 +#, python-format +msgid "Select %s to change" +msgstr "Επιλέξτε %s προς αλλαγή" -#: contrib/redirects/models.py:13 -msgid "redirects" -msgstr "" +#: contrib/admin/views/main.py:768 +msgid "Database error" +msgstr "Σφάλμα βάσης δεδομένων" -#: contrib/flatpages/models.py:8 +#: contrib/admin/views/decorators.py:62 msgid "" -"Example: '/about/contact/'. Make sure to have leading and trailing slashes." -msgstr "" - -#: contrib/flatpages/models.py:9 -msgid "title" -msgstr "" - -#: contrib/flatpages/models.py:10 -msgid "content" -msgstr "" - -#: contrib/flatpages/models.py:11 -msgid "enable comments" -msgstr "" - -#: contrib/flatpages/models.py:12 -msgid "template name" +"Please log in again, because your session has expired. Don't worry: Your " +"submission has been saved." msgstr "" +"Παρακαλούμε συνδεθείτε εκ νέου, γιατί η συνεδρία σας έχει λήξει. Μην " +"ανησυχείτε: Η υποβολή σας έχει αποθηκευτεί." -#: contrib/flatpages/models.py:13 +#: contrib/admin/views/decorators.py:69 msgid "" -"Example: 'flatpages/contact_page'. If this isn't provided, the system will " -"use 'flatpages/default'." -msgstr "" - -#: contrib/flatpages/models.py:14 -msgid "registration required" -msgstr "" - -#: contrib/flatpages/models.py:14 -msgid "If this is checked, only logged-in users will be able to view the page." -msgstr "" - -#: contrib/flatpages/models.py:18 -msgid "flat page" -msgstr "" - -#: contrib/flatpages/models.py:19 -msgid "flat pages" -msgstr "" - -#: contrib/auth/models.py:13 contrib/auth/models.py:26 -msgid "name" -msgstr "" - -#: contrib/auth/models.py:15 -msgid "codename" -msgstr "" - -#: contrib/auth/models.py:17 -msgid "permission" -msgstr "" - -#: contrib/auth/models.py:18 contrib/auth/models.py:27 -msgid "permissions" -msgstr "" - -#: contrib/auth/models.py:29 -msgid "group" -msgstr "" - -#: contrib/auth/models.py:30 contrib/auth/models.py:65 -msgid "groups" -msgstr "" - -#: contrib/auth/models.py:55 -msgid "username" -msgstr "" - -#: contrib/auth/models.py:56 -msgid "first name" -msgstr "" - -#: contrib/auth/models.py:57 -msgid "last name" -msgstr "" - -#: contrib/auth/models.py:58 -msgid "e-mail address" -msgstr "" - -#: contrib/auth/models.py:59 -msgid "password" -msgstr "" - -#: contrib/auth/models.py:59 -msgid "Use '[algo]$[salt]$[hexdigest]'" -msgstr "" - -#: contrib/auth/models.py:60 -msgid "staff status" -msgstr "" - -#: contrib/auth/models.py:60 -msgid "Designates whether the user can log into this admin site." -msgstr "" - -#: contrib/auth/models.py:61 -msgid "active" +"Looks like your browser isn't configured to accept cookies. Please enable " +"cookies, reload this page, and try again." msgstr "" +"Από ότι φαίνεται, ο πλοηγητής σας δεν έχει ρυθμιστεί να δέχεται cookies. " +"Παρακαλούμε ενεργοποιείστε τα cookies, φορτώστε ξανά αυτήν τη σελίδα και " +"δοκιμάστε ξανά." -#: contrib/auth/models.py:62 -msgid "superuser status" -msgstr "" +#: contrib/admin/views/decorators.py:83 +msgid "Usernames cannot contain the '@' character." +msgstr "Τα ονόματα χρηστών δεν επιτρέπεται να περιέχουν το χαρακτήρα '@'." -#: contrib/auth/models.py:63 -msgid "last login" +#: contrib/admin/views/decorators.py:85 +#, python-format +msgid "Your e-mail address is not your username. Try '%s' instead." msgstr "" +"Η ηλεκτρονική σας διεύθυνση δεν είναι το όνομα χρήστη σας. Δοκιμάστε '%s' " +"στη θέση αυτού." -#: contrib/auth/models.py:64 -msgid "date joined" -msgstr "" +#: contrib/admin/views/doc.py:46 contrib/admin/views/doc.py:48 +#: contrib/admin/views/doc.py:50 +msgid "tag:" +msgstr "ετικέτα:" -#: contrib/auth/models.py:66 -msgid "" -"In addition to the permissions manually assigned, this user will also get " -"all permissions granted to each group he/she is in." -msgstr "" +#: contrib/admin/views/doc.py:77 contrib/admin/views/doc.py:79 +#: contrib/admin/views/doc.py:81 +msgid "filter:" +msgstr "φίλτρο:" -#: contrib/auth/models.py:67 -msgid "user permissions" -msgstr "" +#: contrib/admin/views/doc.py:135 contrib/admin/views/doc.py:137 +#: contrib/admin/views/doc.py:139 +msgid "view:" +msgstr "προβολή:" -#: contrib/auth/models.py:70 -#, fuzzy -msgid "user" -msgstr "Χρήστης" +#: contrib/admin/views/doc.py:164 +#, fuzzy, python-format +msgid "App %r not found" +msgstr "Η σελίδα δε βρέθηκε" -#: contrib/auth/models.py:71 +#: contrib/admin/views/doc.py:171 +#, python-format #, fuzzy -msgid "users" -msgstr "Χρήστης" - -#: contrib/auth/models.py:76 -msgid "Personal info" -msgstr "" +msgid "Model %(name)r not found in app %(label)r" +msgstr "όνομα" -#: contrib/auth/models.py:77 -msgid "Permissions" +#: contrib/admin/views/doc.py:183 +#, python-format +msgid "the related `%(label)s.%(type)s` object" msgstr "" -#: contrib/auth/models.py:78 -msgid "Important dates" -msgstr "" +#: contrib/admin/views/doc.py:183 contrib/admin/views/doc.py:205 +#: contrib/admin/views/doc.py:219 contrib/admin/views/doc.py:224 +msgid "model:" +msgstr "μοντέλο:" -#: contrib/auth/models.py:79 -msgid "Groups" -msgstr "" - -#: contrib/auth/models.py:219 +#: contrib/admin/views/doc.py:214 +#, python-format #, fuzzy -msgid "message" -msgstr "αλλάξτε το μήνυμα" - -#: contrib/auth/forms.py:30 -msgid "" -"Your Web browser doesn't appear to have cookies enabled. Cookies are " -"required for logging in." -msgstr "" -"Ο φυλλομετρητής σας δεν φαίνεται να έχει ενεργοποιημένα τα cookies. Τα " -"cookies απαιτούνται για να συνδεθείτε" - -#: contrib/contenttypes/models.py:25 -msgid "python model class name" -msgstr "" +msgid "related `%(label)s.%(name)s` objects" +msgstr "όνομα" -#: contrib/contenttypes/models.py:28 -msgid "content type" -msgstr "" - -#: contrib/contenttypes/models.py:29 -msgid "content types" -msgstr "" - -#: contrib/sessions/models.py:35 -msgid "session key" -msgstr "" - -#: contrib/sessions/models.py:36 -msgid "session data" -msgstr "" - -#: contrib/sessions/models.py:37 -msgid "expire date" -msgstr "" - -#: contrib/sessions/models.py:41 -msgid "session" -msgstr "" - -#: contrib/sessions/models.py:42 -msgid "sessions" -msgstr "" - -#: contrib/sites/models.py:10 -msgid "domain name" -msgstr "" - -#: contrib/sites/models.py:11 -msgid "display name" -msgstr "" +#: contrib/admin/views/doc.py:219 +#, python-format +msgid "all %s" +msgstr "όλα %s" -#: contrib/sites/models.py:15 -msgid "site" +#: contrib/admin/views/doc.py:224 +#, python-format +msgid "number of %s" msgstr "" -#: contrib/sites/models.py:16 -msgid "sites" +#: contrib/admin/views/doc.py:229 +#, python-format +msgid "Fields on %s objects" msgstr "" -#: utils/translation.py:360 -msgid "DATE_FORMAT" -msgstr "N j, Y" - -#: utils/translation.py:361 -msgid "DATETIME_FORMAT" -msgstr "N j, Y, P" - -#: utils/translation.py:362 -msgid "TIME_FORMAT" -msgstr "P" - -#: utils/dates.py:6 -msgid "Monday" -msgstr "Δευτέρα" - -#: utils/dates.py:6 -msgid "Tuesday" -msgstr "Τρίτη" - -#: utils/dates.py:6 -msgid "Wednesday" -msgstr "Τετάρτη" - -#: utils/dates.py:6 -msgid "Thursday" -msgstr "Πέμπτη" - -#: utils/dates.py:6 -msgid "Friday" -msgstr "Παρασκευή" - -#: utils/dates.py:7 -msgid "Saturday" -msgstr "Σάββατο" - -#: utils/dates.py:7 -msgid "Sunday" -msgstr "Κυριακή" - -#: utils/dates.py:14 -msgid "January" -msgstr "Ιανουάριος" - -#: utils/dates.py:14 -msgid "February" -msgstr "Φεβρουάριος" - -#: utils/dates.py:14 utils/dates.py:27 -msgid "March" -msgstr "Μάρτιος" - -#: utils/dates.py:14 utils/dates.py:27 -msgid "April" -msgstr "Απρίλιος" - -#: utils/dates.py:14 utils/dates.py:27 -msgid "May" -msgstr "Μάιος" - -#: utils/dates.py:14 utils/dates.py:27 -msgid "June" -msgstr "Ιούνιος" - -#: utils/dates.py:15 utils/dates.py:27 -msgid "July" -msgstr "Ιούλιος" - -#: utils/dates.py:15 -msgid "August" -msgstr "Αύγουστος" - -#: utils/dates.py:15 -msgid "September" -msgstr "Σεπτέμβριος" - -#: utils/dates.py:15 -msgid "October" -msgstr "Οκτώβριος" - -#: utils/dates.py:15 -msgid "November" -msgstr "Νοέμβριος" - -#: utils/dates.py:16 -msgid "December" -msgstr "Δεκέμβριος" - -#: utils/dates.py:19 -#, fuzzy -msgid "jan" -msgstr "Ιαν" - -#: utils/dates.py:19 -msgid "feb" -msgstr "Φεβ" - -#: utils/dates.py:19 -msgid "mar" -msgstr "Μάρ" - -#: utils/dates.py:19 -msgid "apr" -msgstr "Απρ" - -#: utils/dates.py:19 -msgid "may" -msgstr "Μάι" - -#: utils/dates.py:19 -msgid "jun" -msgstr "Ιούν" - -#: utils/dates.py:20 -msgid "jul" -msgstr "Ιούλ" - -#: utils/dates.py:20 -msgid "aug" -msgstr "Αύγ" - -#: utils/dates.py:20 -msgid "sep" -msgstr "Σεπ" - -#: utils/dates.py:20 -msgid "oct" -msgstr "Οκτ" - -#: utils/dates.py:20 -msgid "nov" -msgstr "Νοέ" - -#: utils/dates.py:20 -msgid "dec" -msgstr "Δεκ" - -#: utils/dates.py:27 -msgid "Jan." -msgstr "Ιάν." - -#: utils/dates.py:27 -msgid "Feb." -msgstr "Φεβ." +#: contrib/admin/views/doc.py:291 contrib/admin/views/doc.py:301 +#: contrib/admin/views/doc.py:303 contrib/admin/views/doc.py:309 +#: contrib/admin/views/doc.py:310 contrib/admin/views/doc.py:312 +msgid "Integer" +msgstr "Ακέραιος" -#: utils/dates.py:28 -msgid "Aug." -msgstr "Αύγ." +#: contrib/admin/views/doc.py:292 +msgid "Boolean (Either True or False)" +msgstr "Boolean (Είτε Αληθές ή Ψευδές)" -#: utils/dates.py:28 -msgid "Sept." -msgstr "Σεπτ." +#: contrib/admin/views/doc.py:293 contrib/admin/views/doc.py:311 +#, python-format +msgid "String (up to %(maxlength)s)" +msgstr "Συμβολοσειρά (μέχρι %(maxlength)s χαρακτήρες)" -#: utils/dates.py:28 -msgid "Oct." -msgstr "Οκτ." +#: contrib/admin/views/doc.py:294 +msgid "Comma-separated integers" +msgstr "Ακέραιοι χωρισμένοι με κόμματα" -#: utils/dates.py:28 -msgid "Nov." -msgstr "Νοέ." +#: contrib/admin/views/doc.py:295 +msgid "Date (without time)" +msgstr "Ημερομηνία (χωρίς την ώρα)" -#: utils/dates.py:28 -msgid "Dec." -msgstr "Δεκ." +#: contrib/admin/views/doc.py:296 +msgid "Date (with time)" +msgstr "Ημερομηνία (με την ώρα)" -#: utils/timesince.py:12 -msgid "year" -msgid_plural "years" -msgstr[0] "χρόνος" -msgstr[1] "χρόνια" +#: contrib/admin/views/doc.py:297 +msgid "E-mail address" +msgstr "Ηλεκτρονική διεύθυνση" -#: utils/timesince.py:13 -msgid "month" -msgid_plural "months" -msgstr[0] "μήνας" -msgstr[1] "μήνες" +#: contrib/admin/views/doc.py:298 contrib/admin/views/doc.py:299 +#: contrib/admin/views/doc.py:302 +msgid "File path" +msgstr "Τοποθεσία αρχείου" -#: utils/timesince.py:14 -msgid "week" -msgid_plural "weeks" -msgstr[0] "εβδομάδα" -msgstr[1] "εβδομάδες" +#: contrib/admin/views/doc.py:300 +msgid "Decimal number" +msgstr "Δεκαδικός αριθμός" -#: utils/timesince.py:15 -msgid "day" -msgid_plural "days" -msgstr[0] "ημέρα" -msgstr[1] "ημέρες" +#: contrib/admin/views/doc.py:306 +msgid "Boolean (Either True, False or None)" +msgstr "Boolean (Αληθές, Ψευδές, ή τίποτα)" -#: utils/timesince.py:16 -msgid "hour" -msgid_plural "hours" -msgstr[0] "ώρα" -msgstr[1] "ώρες" +#: contrib/admin/views/doc.py:307 +msgid "Relation to parent model" +msgstr "Σχέση με το γονικό μοντέλο" -#: utils/timesince.py:17 -msgid "minute" -msgid_plural "minutes" -msgstr[0] "λεπτό" -msgstr[1] "λεπτά" +#: contrib/admin/views/doc.py:308 +msgid "Phone number" +msgstr "Αριθμός τηλεφώνου" -#: conf/global_settings.py:37 -msgid "Bengali" -msgstr "" +#: contrib/admin/views/doc.py:313 +msgid "Text" +msgstr "Κείμενο" -#: conf/global_settings.py:38 -msgid "Czech" -msgstr "" +#: contrib/admin/views/doc.py:314 +msgid "Time" +msgstr "Ώρα" -#: conf/global_settings.py:39 -msgid "Welsh" -msgstr "" +#: contrib/admin/views/doc.py:316 +msgid "U.S. state (two uppercase letters)" +msgstr "Πολιτεία ΗΠΑ. (δύο κεφαλαία γράμματα)" -#: conf/global_settings.py:40 -msgid "Danish" -msgstr "" +#: contrib/admin/views/doc.py:317 +msgid "XML text" +msgstr "Κείμενο XML" -#: conf/global_settings.py:41 -msgid "German" -msgstr "" +#: contrib/admin/views/doc.py:343 +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "Το %s δε φαίνεται να είναι ένα αντικείμενο urlpattern" -#: conf/global_settings.py:42 -msgid "Greek" -msgstr "" +#: contrib/admin/views/auth.py:30 +msgid "Add user" +msgstr "Προσθήκη χρήστη" -#: conf/global_settings.py:43 -msgid "English" -msgstr "" +#: contrib/admin/views/auth.py:57 +msgid "Password changed successfully." +msgstr "Το συνθηματικό αλλάχτηκε με επιτυχία." -#: conf/global_settings.py:44 -msgid "Spanish" -msgstr "" +#: contrib/admin/views/auth.py:64 +#, python-format +msgid "Change password: %s" +msgstr "Αλλαγή συνθηματικού: %s" -#: conf/global_settings.py:45 -msgid "French" -msgstr "" +#: newforms/fields.py:103 newforms/fields.py:256 +#, python-format +msgid "Ensure this value has at most %d characters." +msgstr "Βεβαιωθείτε ότι το κείμενο σας έχει μέγεθος το πολύ %d χαρακτήρες." -#: conf/global_settings.py:46 -msgid "Galician" -msgstr "" +#: newforms/fields.py:105 newforms/fields.py:258 +#, python-format +msgid "Ensure this value has at least %d characters." +msgstr "Βεβαιωθείτε ότι το κείμενο σας έχει μέγεθος τουλάχιστον %d χαρακτήρες." -#: conf/global_settings.py:47 -msgid "Hungarian" -msgstr "" +#: newforms/fields.py:128 core/validators.py:120 +msgid "Enter a whole number." +msgstr "Εισάγετε έναν ακέραιο αριθμό." -#: conf/global_settings.py:48 -msgid "Hebrew" -msgstr "" +#: newforms/fields.py:130 +#, fuzzy, python-format +msgid "Ensure this value is less than or equal to %s." +msgstr "τιμή a από." -#: conf/global_settings.py:49 -msgid "Icelandic" +#: newforms/fields.py:132 +#, python-format +msgid "Ensure this value is greater than or equal to %s." msgstr "" -#: conf/global_settings.py:50 -msgid "Italian" -msgstr "" +#: newforms/fields.py:165 +msgid "Enter a valid date." +msgstr "Εισάγετε μια έγκυρη ημερομηνία." -#: conf/global_settings.py:51 -msgid "Japanese" -msgstr "" +#: newforms/fields.py:192 +msgid "Enter a valid time." +msgstr "Εισάγετε μια έγκυρη ώρα." -#: conf/global_settings.py:52 -msgid "Dutch" -msgstr "" +#: newforms/fields.py:228 +msgid "Enter a valid date/time." +msgstr "Εισάγετε μια έγκυρη ημερομηνία/ώρα." -#: conf/global_settings.py:53 -msgid "Norwegian" -msgstr "" +#: newforms/fields.py:242 +msgid "Enter a valid value." +msgstr "Εισάγετε μια έγκυρη τιμή." -#: conf/global_settings.py:54 -msgid "Brazilian" -msgstr "" +#: newforms/fields.py:271 core/validators.py:162 +msgid "Enter a valid e-mail address." +msgstr "Εισάγετε μια έγκυρη διεύθυνση ηλ. ταχυδρομείου." -#: conf/global_settings.py:55 -msgid "Romanian" -msgstr "" +#: newforms/fields.py:289 newforms/fields.py:311 +msgid "Enter a valid URL." +msgstr "Εισάγετε ένα έγκυρο URL." -#: conf/global_settings.py:56 -msgid "Russian" -msgstr "" +#: newforms/fields.py:313 +#, fuzzy +msgid "This URL appears to be a broken link." +msgstr "Το URL %s είναι χαλασμένος σύνδεσμος." -#: conf/global_settings.py:57 -msgid "Slovak" -msgstr "" +#: newforms/fields.py:362 newforms/models.py:165 +#, fuzzy +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Επιλέξτε μια έγκυρη επιλογή; Το '%(data)s' δεν είναι στα %(choices)s." -#: conf/global_settings.py:58 -msgid "Slovenian" -msgstr "" +#: newforms/fields.py:380 newforms/fields.py:456 newforms/models.py:182 +#, fuzzy +msgid "Enter a list of values." +msgstr "Εισάγετε ένα έγκυρο όνομα αρχείου." -#: conf/global_settings.py:59 -msgid "Serbian" -msgstr "" +#: newforms/fields.py:389 newforms/models.py:188 +#, fuzzy, python-format +msgid "Select a valid choice. %s is not one of the available choices." +msgstr "Επιλέξτε μια έγκυρη επιλογή; Το '%(data)s' δεν είναι στα %(choices)s." -#: conf/global_settings.py:60 -msgid "Swedish" -msgstr "" +#: template/defaultfilters.py:491 +msgid "yes,no,maybe" +msgstr "ναι,όχι,ίσως" -#: conf/global_settings.py:61 -msgid "Ukrainian" -msgstr "" +#: views/generic/create_update.py:43 +#, fuzzy, python-format +msgid "The %(verbose_name)s was created successfully." +msgstr "Το %(name)s \"%(obj)s\" αλλάχτηκε με επιτυχία." -#: conf/global_settings.py:62 -msgid "Simplified Chinese" -msgstr "" +#: views/generic/create_update.py:117 +#, fuzzy, python-format +msgid "The %(verbose_name)s was updated successfully." +msgstr "Το %(name)s \"%(obj)s\" διαγράφηκε με επιτυχία." -#: conf/global_settings.py:63 -msgid "Traditional Chinese" -msgstr "" +#: views/generic/create_update.py:184 +#, fuzzy, python-format +msgid "The %(verbose_name)s was deleted." +msgstr "Το %(name)s \"%(obj)s\" διαγράφηκε με επιτυχία." -#: core/validators.py:60 +#: core/validators.py:64 msgid "This value must contain only letters, numbers and underscores." -msgstr "" +msgstr "Αυτή η τιμή πρέπει να περιέχει μόνο γράμματα, αριθμούς και υπογεγραμμένες." -#: core/validators.py:64 +#: core/validators.py:68 msgid "" "This value must contain only letters, numbers, underscores, dashes or " "slashes." msgstr "" +"Αυτή η τιμή πρέπει να περιέχει μόνο γράμματα, αριθμούς, υπογεγραμμένες, " +"παύλες ή καθέτους." #: core/validators.py:72 -msgid "Uppercase letters are not allowed here." +#, fuzzy +msgid "This value must contain only letters, numbers, underscores or hyphens." msgstr "" +"Αυτή η τιμή πρέπει να περιέχει μόνο γράμματα, αριθμούς, υπογεγραμμένες, " +"παύλες ή καθέτους." #: core/validators.py:76 +msgid "Uppercase letters are not allowed here." +msgstr "Τα κεφαλαία γράμματα δεν επιτρέπονται εδώ." + +#: core/validators.py:80 msgid "Lowercase letters are not allowed here." -msgstr "" +msgstr "Τα πεζά γράμματα δεν επιτρέπονται εδώ." -#: core/validators.py:83 +#: core/validators.py:87 msgid "Enter only digits separated by commas." -msgstr "" +msgstr "Εισάγετε μόνο ψηφία χωρισμένα με κόμματα." -#: core/validators.py:95 +#: core/validators.py:99 msgid "Enter valid e-mail addresses separated by commas." -msgstr "" +msgstr "Εισάγετε έγκυρες ηλ. διευθύνσεις χωρισμένες με κόμματα." -#: core/validators.py:99 +#: core/validators.py:103 msgid "Please enter a valid IP address." -msgstr "" +msgstr "Παρακαλούμε εισάγετε μια έγκυρη διεύθυνση IP." -#: core/validators.py:103 +#: core/validators.py:107 msgid "Empty values are not allowed here." -msgstr "" +msgstr "Δεν επιτρέπονται κενές τιμές εδώ." -#: core/validators.py:107 +#: core/validators.py:111 msgid "Non-numeric characters aren't allowed here." -msgstr "" +msgstr "Δεν επιτρέπονται μη-αριθμητικοί χαρακτήρες εδώ." -#: core/validators.py:111 +#: core/validators.py:115 msgid "This value can't be comprised solely of digits." -msgstr "" - -#: core/validators.py:116 -msgid "Enter a whole number." -msgstr "" - -#: core/validators.py:120 -msgid "Only alphabetical characters are allowed here." -msgstr "" +msgstr "Αυτή η τιμή δεν μπορεί να αποτελείται μόνο από ψηφία." #: core/validators.py:124 -msgid "Enter a valid date in YYYY-MM-DD format." -msgstr "" +msgid "Only alphabetical characters are allowed here." +msgstr "Μόνο αλφαβητικοί χαρακτήρες επιτρέπονται εδώ." -#: core/validators.py:128 -msgid "Enter a valid time in HH:MM format." +#: core/validators.py:139 +msgid "Year must be 1900 or later." msgstr "" -#: core/validators.py:132 db/models/fields/__init__.py:468 -msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format." -msgstr "" +#: core/validators.py:143 +#, fuzzy, python-format +msgid "Invalid date: %s" +msgstr "Μη έγκυρο URL: %s" -#: core/validators.py:136 -msgid "Enter a valid e-mail address." -msgstr "Εισάγετε ένα σωστό e-mail." +#: core/validators.py:153 +msgid "Enter a valid time in HH:MM format." +msgstr "Εισάγετε μία έγκυρη ώρα στη μορφή ΩΩ-ΛΛ." -#: core/validators.py:148 +#: core/validators.py:178 +#, fuzzy msgid "" "Upload a valid image. The file you uploaded was either not an image or a " "corrupted image." -msgstr "" +msgstr "a εικόνα αρχείο υποφαινόμενο όχι εικόνα ή a εικόνα." -#: core/validators.py:155 -#, python-format +#: core/validators.py:185 +#, fuzzy, python-format msgid "The URL %s does not point to a valid image." -msgstr "" +msgstr "URL όχι σημείο a εικόνα." -#: core/validators.py:159 -#, python-format +#: core/validators.py:189 +#, fuzzy, python-format msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid." -msgstr "" +msgstr "Τηλέφωνο μέσα είναι." -#: core/validators.py:167 -#, python-format +#: core/validators.py:197 +#, fuzzy, python-format msgid "The URL %s does not point to a valid QuickTime video." -msgstr "" +msgstr "URL όχι σημείο a." -#: core/validators.py:171 +#: core/validators.py:201 msgid "A valid URL is required." -msgstr "" +msgstr "Απαιτείται ένα έγκυρο URL." -#: core/validators.py:185 +#: core/validators.py:215 #, python-format msgid "" "Valid HTML is required. Specific errors are:\n" "%s" msgstr "" +"Απαιτείται έγκυρη HTML. Συγκεκριμένα σφάλματα είναι τα εξής:\n" +"%s" -#: core/validators.py:192 +#: core/validators.py:222 #, python-format msgid "Badly formed XML: %s" -msgstr "" +msgstr "Κακώς δομημένη XML: %s" -#: core/validators.py:202 +#: core/validators.py:239 #, python-format msgid "Invalid URL: %s" -msgstr "" +msgstr "Μη έγκυρο URL: %s" -#: core/validators.py:206 core/validators.py:208 +#: core/validators.py:244 core/validators.py:246 #, python-format msgid "The URL %s is a broken link." -msgstr "Η διεύθυνση (URL) %s είναι χαλασμένη σύνδεση." +msgstr "Το URL %s είναι χαλασμένος σύνδεσμος." -#: core/validators.py:214 +#: core/validators.py:252 +#, fuzzy msgid "Enter a valid U.S. state abbreviation." -msgstr "" +msgstr "a U συντομογραφία." -#: core/validators.py:229 -#, python-format +#: core/validators.py:266 +#, fuzzy, python-format msgid "Watch your mouth! The word %s is not allowed here." msgid_plural "Watch your mouth! The words %s are not allowed here." -msgstr[0] "" -msgstr[1] "" +msgstr[0] "Παρακολούθηση είναι όχι." +msgstr[1] "Παρακολούθηση είναι όχι." -#: core/validators.py:236 +#: core/validators.py:273 #, python-format msgid "This field must match the '%s' field." -msgstr "" +msgstr "Αυτό το πεδίο πρέπει να ταιριάζει με το πεδίο '%s'." -#: core/validators.py:255 +#: core/validators.py:292 +#, fuzzy msgid "Please enter something for at least one field." -msgstr "" +msgstr "για σε ένα πεδίο." -#: core/validators.py:264 core/validators.py:275 +#: core/validators.py:301 core/validators.py:312 msgid "Please enter both fields or leave them both empty." -msgstr "Παρακαλώ συμπληρώστε και τα δύο πεδία ή αφήστε τα και τα δύο άδεια." +msgstr "Παρακαλούμε συμπληρώστε και τα δύο πεδία ή αφήστε τα και τα δύο άδεια." -#: core/validators.py:282 -#, python-format +#: core/validators.py:320 +#, fuzzy, python-format msgid "This field must be given if %(field)s is %(value)s" -msgstr "" +msgstr "πεδίο πεδίο είναι τιμή" -#: core/validators.py:294 -#, python-format +#: core/validators.py:333 +#, fuzzy, python-format msgid "This field must be given if %(field)s is not %(value)s" -msgstr "" +msgstr "πεδίο πεδίο είναι όχι τιμή" -#: core/validators.py:313 +#: core/validators.py:352 msgid "Duplicate values are not allowed." -msgstr "" +msgstr "Δεν επιτρέπονται διπλές τιμές." + +#: core/validators.py:367 +#, python-format +msgid "This value must be between %(lower)s and %(upper)s." +msgstr "Αυτή η τιμή πρέπει να είναι μεταξύ %(lower)s και %(upper)s." -#: core/validators.py:336 +#: core/validators.py:369 #, python-format +msgid "This value must be at least %s." +msgstr "Αυτή η τιμή πρέπει να είναι τουλάχιστον %s." + +#: core/validators.py:371 +#, python-format +msgid "This value must be no more than %s." +msgstr "Αυτή η τιμή πρέπει να είναι το πολύ %s." + +#: core/validators.py:407 +#, fuzzy, python-format msgid "This value must be a power of %s." -msgstr "" +msgstr "τιμή a από." -#: core/validators.py:347 +#: core/validators.py:418 msgid "Please enter a valid decimal number." -msgstr "Παρακαλώ είσάγετε έναν έγκυρο δεκαδίκο αριθμό." +msgstr "Παρακαλούμε εισάγετε έναν έγκυρο δεκαδικό αριθμό." -#: core/validators.py:349 +#: core/validators.py:422 #, python-format msgid "Please enter a valid decimal number with at most %s total digit." -msgid_plural "" -"Please enter a valid decimal number with at most %s total digits." +msgid_plural "Please enter a valid decimal number with at most %s total digits." msgstr[0] "" +"Παρακαλούμε εισάγετε έναν έγκυρο δεκαδικό αριθμό με το πολύ %s ψηφίο " +"συνολικά." msgstr[1] "" +"Παρακαλούμε εισάγετε έναν έγκυρο δεκαδικό αριθμό με το πολύ %s ψηφία " +"συνολικά." -#: core/validators.py:352 +#: core/validators.py:425 #, python-format -msgid "Please enter a valid decimal number with at most %s decimal place." -msgid_plural "" -"Please enter a valid decimal number with at most %s decimal places." +msgid "Please enter a valid decimal number with a whole part of at most %s digit." +msgid_plural "Please enter a valid decimal number with a whole part of at most %s digits." msgstr[0] "" +"Παρακαλούμε εισάγετε έναν έγκυρο δεκαδικό αριθμό με ακέραιο μέρος το πολύ %s ψηφίο " +"συνολικά." msgstr[1] "" +"Παρακαλούμε εισάγετε έναν έγκυρο δεκαδικό αριθμό με ακέραιο μέρος το πολύ %s ψηφία " +"συνολικά." -#: core/validators.py:362 +#: core/validators.py:428 +#, python-format +msgid "Please enter a valid decimal number with at most %s decimal place." +msgid_plural "Please enter a valid decimal number with at most %s decimal places." +msgstr[0] "Παρακαλούμε εισάγετε έναν έγκυρο δεκαδικό αριθμό με το πολύ %s δεκαδική θέση." +msgstr[1] "" +"Παρακαλούμε εισάγετε έναν έγκυρο δεκαδικό αριθμό με το πολύ %s δεκαδικές " +"θέσεις." + +#: core/validators.py:438 #, python-format msgid "Make sure your uploaded file is at least %s bytes big." -msgstr "Σιγουρευτείτε ότι το αρχείο που ανεβάζετε είναι %s bytes τουλάχιστον." +msgstr "Βεβαιωθείτε ότι το αρχείο που στέλνετε έχει μέγεθος τουλάχιστον %s ψηφία." -#: core/validators.py:363 +#: core/validators.py:439 #, python-format msgid "Make sure your uploaded file is at most %s bytes big." -msgstr "Σιγουρευτείτε ότι το αρχείο που ανεβάζετε έχει μέγεθος μέχρι %s bytes." +msgstr "Βεβαιωθείτε ότι το αρχείο που στέλνετε έχει μέγεθος το πολύ μέχρι %s ψηφία." -#: core/validators.py:376 +#: core/validators.py:456 msgid "The format for this field is wrong." -msgstr "Η διάταξη αυτού του πεδίου έιναι λάθος" +msgstr "Η μορφή αυτού του πεδίου είναι λανθασμένη." -#: core/validators.py:391 +#: core/validators.py:471 msgid "This field is invalid." -msgstr "Αυτό το πεδίο είναι άκυρο" +msgstr "Αυτό το πεδίο είναι μη έγκυρο." -#: core/validators.py:426 -#, python-format +#: core/validators.py:507 +#, fuzzy, python-format msgid "Could not retrieve anything from %s." -msgstr "" +msgstr "όχι Οτιδήποτε από." -#: core/validators.py:429 -#, python-format -msgid "" -"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'." -msgstr "" +#: core/validators.py:510 +#, fuzzy, python-format +msgid "The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'." +msgstr "URL url Περιεχόμενο Τύπος." -#: core/validators.py:462 -#, python-format +#: core/validators.py:543 +#, fuzzy, python-format msgid "" "Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with " "\"%(start)s\".)" -msgstr "" +msgstr "close από Γραμμή με έναρξη" -#: core/validators.py:466 -#, python-format +#: core/validators.py:547 +#, fuzzy, python-format msgid "" "Some text starting on line %(line)s is not allowed in that context. (Line " "starts with \"%(start)s\".)" -msgstr "" +msgstr "κείμενο ενεργό είναι όχι μέσα Γραμμή με έναρξη" -#: core/validators.py:471 -#, python-format +#: core/validators.py:552 +#, fuzzy, python-format msgid "" "\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%" "(start)s\".)" -msgstr "" +msgstr "ενεργό είναι χαρακτηριστικό Γραμμή με έναρξη" -#: core/validators.py:476 -#, python-format +#: core/validators.py:557 +#, fuzzy, python-format msgid "" "\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%" "(start)s\".)" -msgstr "" +msgstr "ενεργό είναι Γραμμή με έναρξη" -#: core/validators.py:480 -#, python-format +#: core/validators.py:561 +#, fuzzy, python-format msgid "" "A tag on line %(line)s is missing one or more required attributes. (Line " "starts with \"%(start)s\".)" -msgstr "" +msgstr "ενεργό είναι αγνοείται ένα ή περισσότερα Γραμμή με έναρξη" -#: core/validators.py:485 -#, python-format +#: core/validators.py:566 +#, fuzzy, python-format msgid "" "The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line " "starts with \"%(start)s\".)" -msgstr "" - -#: db/models/manipulators.py:302 -#, python-format -msgid "%(object)s with this %(type)s already exists for the given %(field)s." -msgstr "" - -#: db/models/fields/__init__.py:40 -#, python-format -msgid "%(optname)s with this %(fieldname)s already exists." -msgstr "" - -#: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265 -#: db/models/fields/__init__.py:542 db/models/fields/__init__.py:553 -#: forms/__init__.py:346 -msgid "This field is required." -msgstr "Αυτό το πεδίο είναι απαραίτητο" - -#: db/models/fields/__init__.py:337 -msgid "This value must be an integer." -msgstr "" - -#: db/models/fields/__init__.py:369 -#, fuzzy -msgid "This value must be either True or False." -msgstr "Boolean (Είτε Αληθές ή Ψευδές)" - -#: db/models/fields/__init__.py:385 -#, fuzzy -msgid "This field cannot be null." -msgstr "Αυτό το πεδίο δεν μπορεί να είναι κενό (null)" - -#: db/models/fields/__init__.py:562 -msgid "Enter a valid filename." -msgstr "Εισάγετε ένα έγκυρο όνομα αρχείου" - -#: db/models/fields/related.py:43 -#, python-format -msgid "Please enter a valid %s." -msgstr "Παρακαλώ εισάγετε ένα/μία έγκυρο/η %s" - -#: db/models/fields/related.py:579 -#, fuzzy -msgid "Separate multiple IDs with commas." -msgstr "Ξεχωρίστε πολλαπλές ΙDs με κόμματα" - -#: db/models/fields/related.py:581 -msgid "" -"Hold down \"Control\", or \"Command\" on a Mac, to select more than one." -msgstr "" - -#: db/models/fields/related.py:625 -#, python-format -msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid." -msgid_plural "" -"Please enter valid %(self)s IDs. The values %(value)r are invalid." -msgstr[0] "" -msgstr[1] "" - -#: forms/__init__.py:380 -#, python-format -msgid "Ensure your text is less than %s character." -msgid_plural "Ensure your text is less than %s characters." -msgstr[0] "" -msgstr[1] "" - -#: forms/__init__.py:385 -msgid "Line breaks are not allowed here." -msgstr "" - -#: forms/__init__.py:480 forms/__init__.py:551 forms/__init__.py:589 -#, python-format -msgid "Select a valid choice; '%(data)s' is not in %(choices)s." -msgstr "" - -#: forms/__init__.py:645 -msgid "The submitted file is empty." -msgstr "" - -#: forms/__init__.py:699 -msgid "Enter a whole number between -32,768 and 32,767." -msgstr "" - -#: forms/__init__.py:708 -msgid "Enter a positive number." -msgstr "" - -#: forms/__init__.py:717 -msgid "Enter a whole number between 0 and 32,767." -msgstr "" - -#: template/defaultfilters.py:379 -msgid "yes,no,maybe" -msgstr "ναί,όχι,ίσως" - -#~ msgid "Comment" -#~ msgstr "Σχόλιο" +msgstr "χαρακτηριστικό ενεργό τιμή Γραμμή με έναρξη" -#~ msgid "Comments" -#~ msgstr "Σχόλια" diff --git a/django/conf/locale/es/LC_MESSAGES/django.mo b/django/conf/locale/es/LC_MESSAGES/django.mo Binary files differindex be8be19162..28d389b404 100644 --- a/django/conf/locale/es/LC_MESSAGES/django.mo +++ b/django/conf/locale/es/LC_MESSAGES/django.mo diff --git a/django/conf/locale/es/LC_MESSAGES/django.po b/django/conf/locale/es/LC_MESSAGES/django.po index 5f11644cfa..bf6d4ed6ae 100644 --- a/django/conf/locale/es/LC_MESSAGES/django.po +++ b/django/conf/locale/es/LC_MESSAGES/django.po @@ -6,775 +6,585 @@ msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-08-17 15:35-0400\n" -"PO-Revision-Date: 2007-07-14 13:00-0500\n" -"Last-Translator: Mario Gonzalez <gonzalemario @t gmail.com>\n" +"POT-Creation-Date: 2007-09-14 12:41+0200\n" +"PO-Revision-Date: 2007-09-14 14:32+0100\n" +"Last-Translator: Marc Garcia <marc.garcia@accopensys.com>\n" "Language-Team: Castellano <Django-I18N@googlegroups.com>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" #: db/models/manipulators.py:309 #, python-format msgid "%(object)s with this %(type)s already exists for the given %(field)s." msgstr "%(object)s de este %(type)s ya existen en este %(field)s." -#: db/models/manipulators.py:310 contrib/admin/views/main.py:342 -#: contrib/admin/views/main.py:344 contrib/admin/views/main.py:346 -#: core/validators.py:275 +#: db/models/manipulators.py:310 +#: core/validators.py:283 +#: contrib/admin/views/main.py:342 +#: contrib/admin/views/main.py:344 +#: contrib/admin/views/main.py:346 msgid "and" msgstr "y" -#: db/models/fields/__init__.py:49 +#: db/models/fields/related.py:55 +#, python-format +msgid "Please enter a valid %s." +msgstr "Por favor, introduzca un %s válido." + +#: db/models/fields/related.py:658 +msgid "Separate multiple IDs with commas." +msgstr "Separe múltiples IDs con comas." + +#: db/models/fields/related.py:660 +msgid "Hold down \"Control\", or \"Command\" on a Mac, to select more than one." +msgstr "Mantenga presionado \"Control\", o \"Command\" en un Mac, para seleccionar más de uno." + +#: db/models/fields/related.py:707 +#, python-format +msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid." +msgid_plural "Please enter valid %(self)s IDs. The values %(value)r are invalid." +msgstr[0] "Por favor, introduzca IDs de %(self)s válidos. El valor %(value)r no es válido." +msgstr[1] "Por favor, introduzca IDs de %(self)s válidos. Los valores %(value)r no son válidos." + +#: db/models/fields/__init__.py:52 #, python-format msgid "%(optname)s with this %(fieldname)s already exists." msgstr "Ya existe %(optname)s con este %(fieldname)s." -#: db/models/fields/__init__.py:156 db/models/fields/__init__.py:313 -#: db/models/fields/__init__.py:721 db/models/fields/__init__.py:732 -#: newforms/fields.py:92 newforms/fields.py:490 newforms/fields.py:566 -#: newforms/fields.py:577 newforms/models.py:193 oldforms/__init__.py:373 +#: db/models/fields/__init__.py:159 +#: db/models/fields/__init__.py:316 +#: db/models/fields/__init__.py:724 +#: db/models/fields/__init__.py:735 +#: oldforms/__init__.py:373 +#: newforms/fields.py:93 +#: newforms/fields.py:509 +#: newforms/fields.py:585 +#: newforms/fields.py:596 +#: newforms/models.py:193 msgid "This field is required." msgstr "Este campo es obligatorio." -#: db/models/fields/__init__.py:411 +#: db/models/fields/__init__.py:414 msgid "This value must be an integer." msgstr "Este valor debe ser un entero." -#: db/models/fields/__init__.py:446 +#: db/models/fields/__init__.py:449 msgid "This value must be either True or False." msgstr "Este valor debe ser Verdadero o Falso." -#: db/models/fields/__init__.py:467 +#: db/models/fields/__init__.py:470 msgid "This field cannot be null." msgstr "Este campo no puede estar vacío." -#: db/models/fields/__init__.py:501 core/validators.py:155 +#: db/models/fields/__init__.py:504 +#: core/validators.py:156 msgid "Enter a valid date in YYYY-MM-DD format." msgstr "Introduzca una fecha válida en formato AAAA-MM-DD." -#: db/models/fields/__init__.py:570 core/validators.py:164 +#: db/models/fields/__init__.py:573 +#: core/validators.py:165 msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format." msgstr "Introduzca una fecha/hora válida en formato AAAA-MM-DD HH:MM." -#: db/models/fields/__init__.py:631 +#: db/models/fields/__init__.py:634 msgid "This value must be a decimal number." msgstr "Este valor debe ser un entero." -#: db/models/fields/__init__.py:741 +#: db/models/fields/__init__.py:744 msgid "Enter a valid filename." msgstr "Introduzca un nombre de fichero válido" -#: db/models/fields/__init__.py:883 +#: db/models/fields/__init__.py:887 msgid "This value must be either None, True or False." msgstr "Este valor debe ser Verdadero o Falso." -#: db/models/fields/related.py:55 -#, python-format -msgid "Please enter a valid %s." -msgstr "Por favor, introduzca un %s válido." - -#: db/models/fields/related.py:661 -msgid "Separate multiple IDs with commas." -msgstr "Separe múltiples IDs con comas." - -#: db/models/fields/related.py:663 -msgid "" -"Hold down \"Control\", or \"Command\" on a Mac, to select more than one." -msgstr "" -"Mantenga presionado \"Control\", o \"Command\" en un Mac, para seleccionar " -"más de uno." - -#: db/models/fields/related.py:710 -#, python-format -msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid." -msgid_plural "" -"Please enter valid %(self)s IDs. The values %(value)r are invalid." -msgstr[0] "" -"Por favor, introduzca IDs de %(self)s válidos. El valor %(value)r no es " -"válido." -msgstr[1] "" -"Por favor, introduzca IDs de %(self)s válidos. Los valores %(value)r no son " -"válidos." - -#: conf/global_settings.py:38 +#: conf/global_settings.py:39 msgid "Arabic" msgstr "Árabe" -#: conf/global_settings.py:39 +#: conf/global_settings.py:40 msgid "Bengali" msgstr "Bengalí" -#: conf/global_settings.py:40 +#: conf/global_settings.py:41 msgid "Bulgarian" msgstr "Búlgaro" -#: conf/global_settings.py:41 +#: conf/global_settings.py:42 msgid "Catalan" msgstr "Catalán" -#: conf/global_settings.py:42 +#: conf/global_settings.py:43 msgid "Czech" msgstr "Checo" -#: conf/global_settings.py:43 +#: conf/global_settings.py:44 msgid "Welsh" msgstr "Galés" -#: conf/global_settings.py:44 +#: conf/global_settings.py:45 msgid "Danish" msgstr "Danés" -#: conf/global_settings.py:45 +#: conf/global_settings.py:46 msgid "German" msgstr "Alemán" -#: conf/global_settings.py:46 +#: conf/global_settings.py:47 msgid "Greek" msgstr "Griego" -#: conf/global_settings.py:47 +#: conf/global_settings.py:48 msgid "English" msgstr "Inglés" -#: conf/global_settings.py:48 +#: conf/global_settings.py:49 msgid "Spanish" msgstr "Español" -#: conf/global_settings.py:49 +#: conf/global_settings.py:50 msgid "Argentinean Spanish" msgstr "Español Argentino" -#: conf/global_settings.py:50 +#: conf/global_settings.py:51 msgid "Persian" msgstr "Persa" -#: conf/global_settings.py:51 +#: conf/global_settings.py:52 msgid "Finnish" msgstr "Finés" -#: conf/global_settings.py:52 +#: conf/global_settings.py:53 msgid "French" msgstr "Francés" -#: conf/global_settings.py:53 +#: conf/global_settings.py:54 msgid "Galician" msgstr "Gallego" -#: conf/global_settings.py:54 +#: conf/global_settings.py:55 msgid "Hungarian" msgstr "Húngaro" -#: conf/global_settings.py:55 +#: conf/global_settings.py:56 msgid "Hebrew" msgstr "Hebreo" -#: conf/global_settings.py:56 +#: conf/global_settings.py:57 msgid "Croatian" msgstr "Croata" -#: conf/global_settings.py:57 +#: conf/global_settings.py:58 msgid "Icelandic" msgstr "Islandés" -#: conf/global_settings.py:58 +#: conf/global_settings.py:59 msgid "Italian" msgstr "Italiano" -#: conf/global_settings.py:59 +#: conf/global_settings.py:60 msgid "Japanese" msgstr "Japonés" -#: conf/global_settings.py:60 +#: conf/global_settings.py:61 msgid "Korean" msgstr "Koreano" -#: conf/global_settings.py:61 +#: conf/global_settings.py:62 +msgid "Khmer" +msgstr "Khmer" + +#: conf/global_settings.py:63 msgid "Kannada" msgstr "Kannada" -#: conf/global_settings.py:62 +#: conf/global_settings.py:64 msgid "Latvian" msgstr "Latvio" -#: conf/global_settings.py:63 +#: conf/global_settings.py:65 msgid "Macedonian" msgstr "Macedonio" -#: conf/global_settings.py:64 +#: conf/global_settings.py:66 msgid "Dutch" msgstr "Alemán" -#: conf/global_settings.py:65 +#: conf/global_settings.py:67 msgid "Norwegian" msgstr "Noruego" -#: conf/global_settings.py:66 +#: conf/global_settings.py:68 msgid "Polish" msgstr "Polaco" -#: conf/global_settings.py:67 +#: conf/global_settings.py:69 msgid "Portugese" msgstr "Portugés" -#: conf/global_settings.py:68 +#: conf/global_settings.py:70 msgid "Brazilian" msgstr "Brasileño" -#: conf/global_settings.py:69 +#: conf/global_settings.py:71 msgid "Romanian" msgstr "Rumano" -#: conf/global_settings.py:70 +#: conf/global_settings.py:72 msgid "Russian" msgstr "Ruso" -#: conf/global_settings.py:71 +#: conf/global_settings.py:73 msgid "Slovak" msgstr "Eslovaco" -#: conf/global_settings.py:72 +#: conf/global_settings.py:74 msgid "Slovenian" msgstr "Esloveno" -#: conf/global_settings.py:73 +#: conf/global_settings.py:75 msgid "Serbian" msgstr "Serbio" -#: conf/global_settings.py:74 +#: conf/global_settings.py:76 msgid "Swedish" msgstr "Sueco" -#: conf/global_settings.py:75 +#: conf/global_settings.py:77 msgid "Tamil" msgstr "Tamil" -#: conf/global_settings.py:76 +#: conf/global_settings.py:78 msgid "Telugu" msgstr "Telugu" -#: conf/global_settings.py:77 +#: conf/global_settings.py:79 msgid "Turkish" msgstr "Turco" -#: conf/global_settings.py:78 +#: conf/global_settings.py:80 msgid "Ukrainian" msgstr "Ucraniano" -#: conf/global_settings.py:79 +#: conf/global_settings.py:81 msgid "Simplified Chinese" msgstr "Chino simplificado" -#: conf/global_settings.py:80 +#: conf/global_settings.py:82 msgid "Traditional Chinese" msgstr "Chino tradicional" -#: views/generic/create_update.py:43 -#, python-format -msgid "The %(verbose_name)s was created successfully." -msgstr "El %(verbose_name)s se ha creado correctamente." - -#: views/generic/create_update.py:117 -#, python-format -msgid "The %(verbose_name)s was updated successfully." -msgstr "Se actualizó con éxito el %(verbose_name)s." - -#: views/generic/create_update.py:184 -#, python-format -msgid "The %(verbose_name)s was deleted." -msgstr "El %(verbose_name)s ha sido eliminado." - -#: utils/dates.py:6 -msgid "Monday" -msgstr "Lunes" - -#: utils/dates.py:6 -msgid "Tuesday" -msgstr "Martes" - -#: utils/dates.py:6 -msgid "Wednesday" -msgstr "Miércoles" - -#: utils/dates.py:6 -msgid "Thursday" -msgstr "Jueves" - -#: utils/dates.py:6 -msgid "Friday" -msgstr "Viernes" - -#: utils/dates.py:7 -msgid "Saturday" -msgstr "Sábado" - -#: utils/dates.py:7 -msgid "Sunday" -msgstr "Domingo" - -#: utils/dates.py:10 -msgid "Mon" -msgstr "Lun" - -#: utils/dates.py:10 -msgid "Tue" -msgstr "Mar" - -#: utils/dates.py:10 -msgid "Wed" -msgstr "Mie" - -#: utils/dates.py:10 -msgid "Thu" -msgstr "Jue" - -#: utils/dates.py:10 -msgid "Fri" -msgstr "Vie" - -#: utils/dates.py:11 -msgid "Sat" -msgstr "Sab" - -#: utils/dates.py:11 -msgid "Sun" -msgstr "Dom" - -#: utils/dates.py:18 -msgid "January" -msgstr "Enero" - -#: utils/dates.py:18 -msgid "February" -msgstr "Febrero" - -#: utils/dates.py:18 utils/dates.py:31 -msgid "March" -msgstr "Marzo" - -#: utils/dates.py:18 utils/dates.py:31 -msgid "April" -msgstr "Abril" - -#: utils/dates.py:18 utils/dates.py:31 -msgid "May" -msgstr "Mayo" - -#: utils/dates.py:18 utils/dates.py:31 -msgid "June" -msgstr "Junio" - -#: utils/dates.py:19 utils/dates.py:31 -msgid "July" -msgstr "Julio" - -#: utils/dates.py:19 -msgid "August" -msgstr "Agosto" - -#: utils/dates.py:19 -msgid "September" -msgstr "Septiembre" - -#: utils/dates.py:19 -msgid "October" -msgstr "Octubre" - -#: utils/dates.py:19 -msgid "November" -msgstr "Noviembre" - -#: utils/dates.py:20 -msgid "December" -msgstr "Diciembre" - -#: utils/dates.py:23 -msgid "jan" -msgstr "ene" - -#: utils/dates.py:23 -msgid "feb" -msgstr "feb" - -#: utils/dates.py:23 -msgid "mar" -msgstr "mar" - -#: utils/dates.py:23 -msgid "apr" -msgstr "abr" - -#: utils/dates.py:23 -msgid "may" -msgstr "may" - -#: utils/dates.py:23 -msgid "jun" -msgstr "jun" - -#: utils/dates.py:24 -msgid "jul" -msgstr "jul" +#: core/validators.py:72 +msgid "This value must contain only letters, numbers and underscores." +msgstr "Este valor debe contener sólo letras, números y guiones bajos." -#: utils/dates.py:24 -msgid "aug" -msgstr "ago" +#: core/validators.py:76 +msgid "This value must contain only letters, numbers, underscores, dashes or slashes." +msgstr "Este valor debe contener letras, números, guiones bajos o barras solamente." -#: utils/dates.py:24 -msgid "sep" -msgstr "sep" +#: core/validators.py:80 +msgid "This value must contain only letters, numbers, underscores or hyphens." +msgstr "Este valor debe contener sólo letras, números, guiones bajos o medios." -#: utils/dates.py:24 -msgid "oct" -msgstr "oct" +#: core/validators.py:84 +msgid "Uppercase letters are not allowed here." +msgstr "No se admiten letras mayúsculas." -#: utils/dates.py:24 -msgid "nov" -msgstr "nov" +#: core/validators.py:88 +msgid "Lowercase letters are not allowed here." +msgstr "No se admiten letras minúsculas." -#: utils/dates.py:24 -msgid "dec" -msgstr "dic" +#: core/validators.py:95 +msgid "Enter only digits separated by commas." +msgstr "Introduzca sólo dígitos separados por comas." -#: utils/dates.py:31 -msgid "Jan." -msgstr "Ene." +#: core/validators.py:107 +msgid "Enter valid e-mail addresses separated by commas." +msgstr "Introduzca direcciones de correo válidas separadas por comas." -#: utils/dates.py:31 -msgid "Feb." -msgstr "Feb." +#: core/validators.py:111 +msgid "Please enter a valid IP address." +msgstr "Por favor introduzca una dirección IP válida." -#: utils/dates.py:32 -msgid "Aug." -msgstr "Ago." +#: core/validators.py:115 +msgid "Empty values are not allowed here." +msgstr "No se admiten valores vacíos." -#: utils/dates.py:32 -msgid "Sept." -msgstr "Sept." +#: core/validators.py:119 +msgid "Non-numeric characters aren't allowed here." +msgstr "No se admiten caracteres no numéricos." -#: utils/dates.py:32 -msgid "Oct." -msgstr "Oct." +#: core/validators.py:123 +msgid "This value can't be comprised solely of digits." +msgstr "Este valor no puede comprender sólo dígitos." -#: utils/dates.py:32 -msgid "Nov." -msgstr "Nov." +#: core/validators.py:128 +#: newforms/fields.py:149 +msgid "Enter a whole number." +msgstr "Introduzca un número entero." -#: utils/dates.py:32 -msgid "Dec." -msgstr "Dic." +#: core/validators.py:132 +msgid "Only alphabetical characters are allowed here." +msgstr "Sólo se admiten caracteres alfabéticos." -#: utils/timesince.py:12 -msgid "year" -msgid_plural "years" -msgstr[0] "año" -msgstr[1] "años" +#: core/validators.py:147 +msgid "Year must be 1900 or later." +msgstr "El año debe ser 1900 o posterior." -#: utils/timesince.py:13 -msgid "month" -msgid_plural "months" -msgstr[0] "mes" -msgstr[1] "meses" +#: core/validators.py:151 +#, python-format +msgid "Invalid date: %s" +msgstr "Fecha no válida: %s" -#: utils/timesince.py:14 -msgid "week" -msgid_plural "weeks" -msgstr[0] "semana" -msgstr[1] "semanas" +#: core/validators.py:161 +msgid "Enter a valid time in HH:MM format." +msgstr "Introduzca una hora válida en formato HH:MM." -#: utils/timesince.py:15 -msgid "day" -msgid_plural "days" -msgstr[0] "día" -msgstr[1] "días" +#: core/validators.py:170 +#: newforms/fields.py:343 +msgid "Enter a valid e-mail address." +msgstr "Introduzca una dirección de correo electrónico válida" -#: utils/timesince.py:16 -msgid "hour" -msgid_plural "hours" -msgstr[0] "hora" -msgstr[1] "horas" +#: core/validators.py:182 +#: core/validators.py:469 +#: oldforms/__init__.py:686 +#: newforms/fields.py:377 +msgid "No file was submitted. Check the encoding type on the form." +msgstr "No se ha enviado ningún fichero. Compruebe el tipo de codificación en el formulario." -#: utils/timesince.py:17 -msgid "minute" -msgid_plural "minutes" -msgstr[0] "minuto" -msgstr[1] "minutos" +#: core/validators.py:193 +#: newforms/fields.py:405 +msgid "Upload a valid image. The file you uploaded was either not an image or a corrupted image." +msgstr "Envíe una imagen válida. El fichero que ha enviado no era una imagen o se trataba de una imagen corrupta." -#: utils/timesince.py:39 +#: core/validators.py:200 #, python-format -msgid "%(number)d %(type)s" -msgstr "%(number)d %(type)s" +msgid "The URL %s does not point to a valid image." +msgstr "La URL %s no apunta a una imagen válida." -#: utils/timesince.py:45 +#: core/validators.py:204 #, python-format -msgid ", %(number)d %(type)s" -msgstr ", %(number)d %(type)s" - -#: utils/text.py:127 -msgid "or" -msgstr "o" - -#: utils/dateformat.py:41 -msgid "p.m." -msgstr "p.m" - -#: utils/dateformat.py:42 -msgid "a.m." -msgstr "a.m" - -#: utils/dateformat.py:47 -msgid "PM" -msgstr "PM" - -#: utils/dateformat.py:48 -msgid "AM" -msgstr "AM" - -#: utils/dateformat.py:97 -msgid "midnight" -msgstr "media noche" - -#: utils/dateformat.py:99 -msgid "noon" -msgstr "medio día" - -#: utils/translation/trans_real.py:391 -msgid "DATE_FORMAT" -msgstr "j N Y" - -#: utils/translation/trans_real.py:392 -msgid "DATETIME_FORMAT" -msgstr "j N Y P" - -#: utils/translation/trans_real.py:393 -msgid "TIME_FORMAT" -msgstr "P" +msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid." +msgstr "Los números de teléfono deben guardar el formato XXX-XXX-XXXX. \"%s\" no es válido." -#: utils/translation/trans_real.py:409 -msgid "YEAR_MONTH_FORMAT" -msgstr "F Y" +#: core/validators.py:212 +#, python-format +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." -#: utils/translation/trans_real.py:410 -msgid "MONTH_DAY_FORMAT" -msgstr "j \\de F" +#: core/validators.py:216 +msgid "A valid URL is required." +msgstr "Se precisa una URL válida." -#: newforms/fields.py:116 +#: core/validators.py:230 #, python-format -msgid "Ensure this value has at most %(max)d characters (it has %(length)d)." +msgid "" +"Valid HTML is required. Specific errors are:\n" +"%s" msgstr "" -"Asegúrese de que su texto tiene a lo más %(max)d caracteres (actualmente " -"tiene %(length)d)." +"Se precisa HTML válido. Los errores específicos son:\n" +"%s" -#: newforms/fields.py:118 +#: core/validators.py:237 #, python-format -msgid "Ensure this value has at least %(min)d characters (it has %(length)d)." -msgstr "" -"Asegúrese de que su texto tiene al menos %(min)d caracteres (actualmente " -"tiene %(length)d)." - -#: newforms/fields.py:142 core/validators.py:127 -msgid "Enter a whole number." -msgstr "Introduzca un número entero." +msgid "Badly formed XML: %s" +msgstr "XML mal formado: %s" -#: newforms/fields.py:144 newforms/fields.py:167 newforms/fields.py:197 +#: core/validators.py:254 #, python-format -msgid "Ensure this value is less than or equal to %s." -msgstr "Asegúrese de que este valor es menor o igual a %s." +msgid "Invalid URL: %s" +msgstr "URL no válida: %s" -#: newforms/fields.py:146 newforms/fields.py:169 newforms/fields.py:199 +#: core/validators.py:259 +#: core/validators.py:261 #, python-format -msgid "Ensure this value is greater than or equal to %s." -msgstr "Asegúrese de que este valor es mayor o igual a %s." - -#: newforms/fields.py:165 newforms/fields.py:192 -msgid "Enter a number." -msgstr "Introduzca un número." +msgid "The URL %s is a broken link." +msgstr "La URL %s es un enlace roto." -#: newforms/fields.py:201 -#, python-format -msgid "Ensure that there are no more than %s digits in total." -msgstr "Asegúrese de que no hay más de %s dígitos en total." +#: core/validators.py:267 +msgid "Enter a valid U.S. state abbreviation." +msgstr "Introduzca una abreviatura válida de estado de los EEUU." -#: newforms/fields.py:203 +#: core/validators.py:281 #, python-format -msgid "Ensure that there are no more than %s decimal places." -msgstr "Asegúrese de que no hay más de %s decimales." +msgid "Watch your mouth! The word %s is not allowed here." +msgid_plural "Watch your mouth! The words %s are not allowed here." +msgstr[0] "¡Cuida tu vocabulario! Aquí no admitimos la palabra %s." +msgstr[1] "¡Cuida tu vocabulario! Aquí no admitimos las palabras %s." -#: newforms/fields.py:205 +#: core/validators.py:288 #, python-format -msgid "Ensure that there are no more than %s digits before the decimal point." -msgstr "Asegúrese de que no hay más de %s dígitos antes del punto decimal." - -#: newforms/fields.py:238 newforms/fields.py:610 -msgid "Enter a valid date." -msgstr "Introduzca una fecha válida." - -#: newforms/fields.py:265 newforms/fields.py:612 -msgid "Enter a valid time." -msgstr "Introduzca una hora válida." - -#: newforms/fields.py:301 -msgid "Enter a valid date/time." -msgstr "Introduzca una fecha/hora válida." +msgid "This field must match the '%s' field." +msgstr "Este campo debe concordar con el campo '%s'." -#: newforms/fields.py:314 -msgid "Enter a valid value." -msgstr "Introduzca un valor correcto." +#: core/validators.py:307 +msgid "Please enter something for at least one field." +msgstr "Por favor, introduzca algo en al menos un campo." -#: newforms/fields.py:336 core/validators.py:169 -msgid "Enter a valid e-mail address." -msgstr "Introduzca una dirección de correo electrónico válida" +#: core/validators.py:316 +#: core/validators.py:327 +msgid "Please enter both fields or leave them both empty." +msgstr "Por favor, rellene ambos campos o deje ambos vacíos." -#: newforms/fields.py:376 oldforms/__init__.py:686 core/validators.py:181 -#: core/validators.py:461 -msgid "No file was submitted. Check the encoding type on the form." -msgstr "" -"No se ha enviado ningún fichero. Compruebe el tipo de codificación en el " -"formulario." +#: core/validators.py:335 +#, python-format +msgid "This field must be given if %(field)s is %(value)s" +msgstr "Se debe proporcionar este campo si %(field)s es %(value)s" -#: newforms/fields.py:378 -msgid "No file was submitted." -msgstr "No se ha enviado ningún fichero" +#: core/validators.py:348 +#, python-format +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" -#: newforms/fields.py:380 oldforms/__init__.py:688 -msgid "The submitted file is empty." -msgstr "El fichero enviado está vacío." +#: core/validators.py:367 +msgid "Duplicate values are not allowed." +msgstr "No se admiten valores duplicados." -#: newforms/fields.py:397 core/validators.py:185 -msgid "" -"Upload a valid image. The file you uploaded was either not an image or a " -"corrupted image." -msgstr "" -"Envíe una imagen válida. El fichero que ha enviado no era una imagen o se " -"trataba de una imagen corrupta." +#: core/validators.py:382 +#, python-format +msgid "This value must be between %(lower)s and %(upper)s." +msgstr "Este valor debe estar entre %(lower)s y %(upper)s." -#: newforms/fields.py:403 newforms/fields.py:425 -msgid "Enter a valid URL." -msgstr "Introduzca una URL válida." +#: core/validators.py:384 +#, python-format +msgid "This value must be at least %s." +msgstr "Este valor debe ser como mínimo %s." -#: newforms/fields.py:427 -msgid "This URL appears to be a broken link." -msgstr "La URL parece ser un enlace roto." +#: core/validators.py:386 +#, python-format +msgid "This value must be no more than %s." +msgstr "Este valor no debe ser mayor que %s." -#: newforms/fields.py:478 newforms/models.py:180 -msgid "Select a valid choice. That choice is not one of the available choices." -msgstr "Escoja una opción válida. Esa opción no está entre las aceptadas." +#: core/validators.py:422 +#, python-format +msgid "This value must be a power of %s." +msgstr "Este valor debe ser una potencia de %s." -#: newforms/fields.py:494 newforms/fields.py:570 newforms/models.py:197 -msgid "Enter a list of values." -msgstr "Introduzca una lista de valores." +#: core/validators.py:432 +msgid "Please enter a valid decimal number." +msgstr "Por favor, introduzca un número decimal válido." -#: newforms/fields.py:500 newforms/models.py:203 +#: core/validators.py:439 #, python-format -msgid "Select a valid choice. %s is not one of the available choices." -msgstr "Escoja una opción válida; '%s' no es una de las opciones disponibles." +msgid "Please enter a valid decimal number with at most %s total digit." +msgid_plural "Please enter a valid decimal number with at most %s total digits." +msgstr[0] "Por favor, introduzca un número decimal válido con a lo más %s dígito en total." +msgstr[1] "Por favor, introduzca un número decimal válido con a lo más %s dígitos en total." -#: newforms/widgets.py:188 contrib/admin/filterspecs.py:152 -#: oldforms/__init__.py:591 -msgid "Unknown" -msgstr "Desconocido" +#: core/validators.py:442 +#, python-format +msgid "Please enter a valid decimal number with a whole part of at most %s digit." +msgid_plural "Please enter a valid decimal number with a whole part of at most %s digits." +msgstr[0] "Por favor, introduzca un número decimal válido con a lo más %s dígito en su parte entera." +msgstr[1] "Por favor, introduzca un número decimal válido con a lo más %s dígitos en su parte entera." -#: newforms/widgets.py:188 contrib/admin/filterspecs.py:145 -#: oldforms/__init__.py:591 -msgid "Yes" -msgstr "Sí" +#: core/validators.py:445 +#, python-format +msgid "Please enter a valid decimal number with at most %s decimal place." +msgid_plural "Please enter a valid decimal number with at most %s decimal places." +msgstr[0] "Por favor, introduzca un número decimal válido con a lo más %s dígito decimal." +msgstr[1] "Por favor, introduzca un número decimal válido con a lo más %s dígitos decimales." -#: newforms/widgets.py:188 contrib/admin/filterspecs.py:145 -#: oldforms/__init__.py:591 -msgid "No" -msgstr "No" +#: core/validators.py:453 +msgid "Please enter a valid floating point number." +msgstr "Por favor, introduzca un número decimal válido." -#: contrib/contenttypes/models.py:37 -msgid "python model class name" -msgstr "nombre de módulo python" +#: core/validators.py:462 +#, python-format +msgid "Make sure your uploaded file is at least %s bytes big." +msgstr "Asegúrese de que el fichero que envía tiene al menos %s bytes." -#: contrib/contenttypes/models.py:40 -msgid "content type" -msgstr "tipo de contenido" +#: core/validators.py:463 +#, python-format +msgid "Make sure your uploaded file is at most %s bytes big." +msgstr "Asegúrese de que el fichero que envía tiene como máximo %s bytes." -#: contrib/contenttypes/models.py:41 -msgid "content types" -msgstr "tipos de contenido" +#: core/validators.py:480 +msgid "The format for this field is wrong." +msgstr "El formato de este campo es incorrecto." -#: contrib/humanize/templatetags/humanize.py:17 -msgid "th" -msgstr "th" +#: core/validators.py:495 +msgid "This field is invalid." +msgstr "Este campo no es válido." -#: contrib/humanize/templatetags/humanize.py:17 -msgid "st" -msgstr "st" +#: core/validators.py:531 +#, python-format +msgid "Could not retrieve anything from %s." +msgstr "No pude obtener nada de %s." -#: contrib/humanize/templatetags/humanize.py:17 -msgid "nd" -msgstr "nd" +#: core/validators.py:534 +#, python-format +msgid "The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'." +msgstr "La URL %(url)s devolvió la cabecera Content-Type '%(contenttype)s', que no es válida." -#: contrib/humanize/templatetags/humanize.py:17 -msgid "rd" -msgstr "rd" +#: core/validators.py:567 +#, python-format +msgid "Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with \"%(start)s\".)" +msgstr "Por favor, cierre la etiqueta %(tag)s de la línea %(line)s. (La línea empieza por \"%(start)s\".)" -#: contrib/humanize/templatetags/humanize.py:47 +#: core/validators.py:571 #, python-format -msgid "%(value).1f million" -msgid_plural "%(value).1f million" -msgstr[0] "%(value).1f millón" -msgstr[1] "%(value).1f millión" +msgid "Some text starting on line %(line)s is not allowed in that context. (Line starts with \"%(start)s\".)" +msgstr "Parte del texto que comienza en la línea %(line)s no está permitido en ese contexto. (La línea empieza por \"%(start)s\".)" -#: contrib/humanize/templatetags/humanize.py:50 +#: core/validators.py:576 #, python-format -msgid "%(value).1f billion" -msgid_plural "%(value).1f billion" -msgstr[0] "%(value).1f billión" -msgstr[1] "%(value).1f billión" +msgid "\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%(start)s\".)" +msgstr "El \"%(attr)s\" de la línea %(line)s no es un atributo válido. (La línea empieza por \"%(start)s\".)" -#: contrib/humanize/templatetags/humanize.py:53 +#: core/validators.py:581 #, python-format -msgid "%(value).1f trillion" -msgid_plural "%(value).1f trillion" -msgstr[0] "%(value).1f trillión" -msgstr[1] "%(value).1f trillión" +msgid "\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%(start)s\".)" +msgstr "La \"<%(tag)s>\" de la línea %(line)s no es una etiqueta válida. (La línea empieza por \"%(start)s\".)" -#: contrib/humanize/templatetags/humanize.py:68 -msgid "one" -msgstr "uno" +#: core/validators.py:585 +#, python-format +msgid "A tag on line %(line)s is missing one or more required attributes. (Line starts with \"%(start)s\".)" +msgstr "A una etiqueta de la línea %(line)s le faltan uno o más atributos requeridos. (La línea empieza por \"%(start)s\".)" -#: contrib/humanize/templatetags/humanize.py:68 -msgid "two" -msgstr "dos" +#: core/validators.py:590 +#, python-format +msgid "The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line starts with \"%(start)s\".)" +msgstr "El atributo \"%(attr)s\" de la línea %(line)s tiene un valor que no es válido. (La línea empieza por \"%(start)s\".)" -#: contrib/humanize/templatetags/humanize.py:68 -msgid "three" -msgstr "tres" +#: contrib/auth/forms.py:17 +#: contrib/auth/forms.py:138 +msgid "The two password fields didn't match." +msgstr "Las dos contraseñas no coinciden." -#: contrib/humanize/templatetags/humanize.py:68 -msgid "four" -msgstr "cuatro" +#: contrib/auth/forms.py:25 +msgid "A user with that username already exists." +msgstr "Ya existe un usuario con este nombre." -#: contrib/humanize/templatetags/humanize.py:68 -msgid "five" -msgstr "cinco" +#: contrib/auth/forms.py:53 +msgid "Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in." +msgstr "Tu navegador de internet parece no tener las cookies habilitadas. Las cookies se necesitan para poder ingresar." -#: contrib/humanize/templatetags/humanize.py:68 -msgid "six" -msgstr "seis" +#: contrib/auth/forms.py:60 +#: contrib/admin/views/decorators.py:10 +msgid "Please enter a correct username and password. Note that both fields are case-sensitive." +msgstr "Por favor, introduzca un correcto nombre de usuario y contraseña. Note que ambos campos son sensibles a mayúsculas/minúsculas." -#: contrib/humanize/templatetags/humanize.py:68 -msgid "seven" -msgstr "siete" +#: contrib/auth/forms.py:62 +msgid "This account is inactive." +msgstr "Esta cuenta está inactiva." -#: contrib/humanize/templatetags/humanize.py:68 -msgid "eight" -msgstr "ocho" +#: contrib/auth/forms.py:84 +msgid "That e-mail address doesn't have an associated user account. Are you sure you've registered?" +msgstr "Esta dirección de correo electrónico no tiene una cuenta de usuario asociada. ¿Está seguro de que se ha registrado?" -#: contrib/humanize/templatetags/humanize.py:68 -msgid "nine" -msgstr "nueve" +#: contrib/auth/forms.py:117 +msgid "The two 'new password' fields didn't match." +msgstr "Las contraseñas introducidas en los campos 'nueva contraseña' no coinciden." -#: contrib/auth/views.py:47 -msgid "Logged out" -msgstr "Sesión terminada" +#: contrib/auth/forms.py:124 +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Tu contraseña antigua es incorrecta. Por favor, vuelve a introducirla correctamente." -#: contrib/auth/models.py:53 contrib/auth/models.py:73 +#: contrib/auth/models.py:53 +#: contrib/auth/models.py:73 msgid "name" msgstr "nombre" @@ -786,7 +596,8 @@ msgstr "nombre en código" msgid "permission" msgstr "permiso" -#: contrib/auth/models.py:59 contrib/auth/models.py:74 +#: contrib/auth/models.py:59 +#: contrib/auth/models.py:74 msgid "permissions" msgstr "permisos" @@ -794,7 +605,8 @@ msgstr "permisos" msgid "group" msgstr "grupo" -#: contrib/auth/models.py:78 contrib/auth/models.py:121 +#: contrib/auth/models.py:78 +#: contrib/auth/models.py:121 msgid "groups" msgstr "grupos" @@ -803,12 +615,8 @@ msgid "username" msgstr "nombre de usuario" #: contrib/auth/models.py:111 -msgid "" -"Required. 30 characters or fewer. Alphanumeric characters only (letters, " -"digits and underscores)." -msgstr "" -"Requerido. 30 caracteres o menos. Sólo caracteres alfanuméricos (letras, " -"dígitos y guiones bajos)." +msgid "Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores)." +msgstr "Requerido. 30 caracteres o menos. Sólo caracteres alfanuméricos (letras, dígitos y guiones bajos)." #: contrib/auth/models.py:112 msgid "first name" @@ -827,12 +635,8 @@ msgid "password" msgstr "clave" #: contrib/auth/models.py:115 -msgid "" -"Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change " -"password form</a>." -msgstr "" -"Use'[algo]$[sal]$[hash hexadecimal]' o use <a href=\"password/\">el " -"formulario para cambiar la contraseña</a>." +msgid "Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change password form</a>." +msgstr "Use'[algo]$[sal]$[hash hexadecimal]' o use <a href=\"password/\">el formulario para cambiar la contraseña</a>." #: contrib/auth/models.py:116 msgid "staff status" @@ -847,24 +651,16 @@ msgid "active" msgstr "activo" #: contrib/auth/models.py:117 -msgid "" -"Designates whether this user can log into the Django admin. Unselect this " -"instead of deleting accounts." -msgstr "" -"Indica si el usuario puede entrar en este sitio de administración. Desmarque " -"esto en lugar de borrar la cuenta." +msgid "Designates whether this user can log into the Django admin. Unselect this instead of deleting accounts." +msgstr "Indica si el usuario puede entrar en este sitio de administración. Desmarque esto en lugar de borrar la cuenta." #: contrib/auth/models.py:118 msgid "superuser status" msgstr "es superusuario" #: contrib/auth/models.py:118 -msgid "" -"Designates that this user has all permissions without explicitly assigning " -"them." -msgstr "" -"Indica que este usuario tiene todos los permisos sin asignárselos " -"explícitamente." +msgid "Designates that this user has all permissions without explicitly assigning them." +msgstr "Indica que este usuario tiene todos los permisos sin asignárselos explícitamente." #: contrib/auth/models.py:119 msgid "last login" @@ -875,12 +671,8 @@ msgid "date joined" msgstr "fecha de creación" #: contrib/auth/models.py:122 -msgid "" -"In addition to the permissions manually assigned, this user will also get " -"all permissions granted to each group he/she is in." -msgstr "" -"Además de los permisos asignados manualmente, este usuario también tendrá " -"todos los permisos de los grupos en los que esté." +msgid "In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in." +msgstr "Además de los permisos asignados manualmente, este usuario también tendrá todos los permisos de los grupos en los que esté." #: contrib/auth/models.py:123 msgid "user permissions" @@ -910,508 +702,41 @@ msgstr "Fechas importantes" msgid "Groups" msgstr "Grupos" -#: contrib/auth/models.py:287 +#: contrib/auth/models.py:288 msgid "message" msgstr "mensaje" -#: contrib/auth/forms.py:17 contrib/auth/forms.py:138 -msgid "The two password fields didn't match." -msgstr "Las dos contraseñas no coinciden." - -#: contrib/auth/forms.py:25 -msgid "A user with that username already exists." -msgstr "Ya existe un usuario con este nombre." - -#: contrib/auth/forms.py:53 -msgid "" -"Your Web browser doesn't appear to have cookies enabled. Cookies are " -"required for logging in." -msgstr "" -"Tu navegador de internet parece no tener las cookies habilitadas. Las " -"cookies se necesitan para poder ingresar." - -#: contrib/auth/forms.py:60 contrib/admin/views/decorators.py:10 -msgid "" -"Please enter a correct username and password. Note that both fields are case-" -"sensitive." -msgstr "" -"Por favor, introduzca un correcto nombre de usuario y contraseña. Note que " -"ambos campos son sensibles a mayúsculas/minúsculas." - -#: contrib/auth/forms.py:62 -msgid "This account is inactive." -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 "" -"Esta dirección de correo electrónico no tiene una cuenta de usuario " -"asociada. ¿Está seguro de que se ha registrado?" - -#: contrib/auth/forms.py:117 -msgid "The two 'new password' fields didn't match." -msgstr "" -"Las contraseñas introducidas en los campos 'nueva contraseña' no coinciden." - -#: contrib/auth/forms.py:124 -msgid "Your old password was entered incorrectly. Please enter it again." -msgstr "" -"Tu contraseña antigua es incorrecta. Por favor, vuelve a introducirla " -"correctamente." - -#: contrib/redirects/models.py:7 -msgid "redirect from" -msgstr "redirigir desde" - -#: contrib/redirects/models.py:8 -msgid "" -"This should be an absolute path, excluding the domain name. Example: '/" -"events/search/'." -msgstr "" -"Esta ruta debería ser absoluta, excluyendo el nombre de dominio. Ejeplo: '/" -"events/search/'." - -#: contrib/redirects/models.py:9 -msgid "redirect to" -msgstr "redirigir a" - -#: contrib/redirects/models.py:10 -msgid "" -"This can be either an absolute path (as above) or a full URL starting with " -"'http://'." -msgstr "" -"Esto puede ser bien una ruta absoluta (como antes) o una URL completa que " -"empiece con 'http://'." - -#: contrib/redirects/models.py:13 -msgid "redirect" -msgstr "redirección" - -#: contrib/redirects/models.py:14 -msgid "redirects" -msgstr "redirecciones" - -#: contrib/comments/models.py:67 contrib/comments/models.py:169 -msgid "object ID" -msgstr "ID de objeto" - -#: contrib/comments/models.py:68 -msgid "headline" -msgstr "encabezado" - -#: contrib/comments/models.py:69 contrib/comments/models.py:90 -#: contrib/comments/models.py:170 -msgid "comment" -msgstr "comentario" - -#: contrib/comments/models.py:70 -msgid "rating #1" -msgstr "calificación 1" - -#: contrib/comments/models.py:71 -msgid "rating #2" -msgstr "calificación 2" - -#: contrib/comments/models.py:72 -msgid "rating #3" -msgstr "calificación 3" - -#: contrib/comments/models.py:73 -msgid "rating #4" -msgstr "calificación 4" - -#: contrib/comments/models.py:74 -msgid "rating #5" -msgstr "calificación 5" - -#: contrib/comments/models.py:75 -msgid "rating #6" -msgstr "calificación 6" - -#: contrib/comments/models.py:76 -msgid "rating #7" -msgstr "calificación 7" - -#: contrib/comments/models.py:77 -msgid "rating #8" -msgstr "calificación 8" - -#: contrib/comments/models.py:82 -msgid "is valid rating" -msgstr "es calificación válida" - -#: contrib/comments/models.py:83 contrib/comments/models.py:172 -msgid "date/time submitted" -msgstr "fecha/hora de envío" - -#: contrib/comments/models.py:84 contrib/comments/models.py:173 -msgid "is public" -msgstr "es público" - -#: contrib/comments/models.py:85 contrib/admin/views/doc.py:306 -msgid "IP address" -msgstr "Dirección IP" - -#: contrib/comments/models.py:86 -msgid "is removed" -msgstr "está eliminado" - -#: contrib/comments/models.py:86 -msgid "" -"Check this box if the comment is inappropriate. A \"This comment has been " -"removed\" message will be displayed instead." -msgstr "" -"Marque esta caja si el comentario es inapropiado. En su lugar se mostrará " -"\"Este comentario ha sido eliminado\"." - -#: contrib/comments/models.py:91 -msgid "comments" -msgstr "comentarios" - -#: contrib/comments/models.py:134 contrib/comments/models.py:213 -msgid "Content object" -msgstr "Objeto contenido" - -#: contrib/comments/models.py:162 -#, python-format -msgid "" -"Posted by %(user)s at %(date)s\n" -"\n" -"%(comment)s\n" -"\n" -"http://%(domain)s%(url)s" -msgstr "" -"Enviado por %(user)s en %(date)s\n" -"\n" -"%(comment)s\n" -"\n" -"http://%(domain)s%(url)s" - -#: contrib/comments/models.py:171 -msgid "person's name" -msgstr "nombre de la persona" - -#: contrib/comments/models.py:174 -msgid "ip address" -msgstr "dirección ip" - -#: contrib/comments/models.py:176 -msgid "approved by staff" -msgstr "aprobado por el staff" - -#: contrib/comments/models.py:179 -msgid "free comment" -msgstr "comentario libre" - -#: contrib/comments/models.py:180 -msgid "free comments" -msgstr "comentarios libres" - -#: contrib/comments/models.py:239 -msgid "score" -msgstr "puntuación" - -#: contrib/comments/models.py:240 -msgid "score date" -msgstr "fecha de la puntuación" - -#: contrib/comments/models.py:243 -msgid "karma score" -msgstr "punto karma" - -#: contrib/comments/models.py:244 -msgid "karma scores" -msgstr "puntos karma" - -#: contrib/comments/models.py:248 -#, python-format -msgid "%(score)d rating by %(user)s" -msgstr "puntuado %(score)d por %(user)s" - -#: contrib/comments/models.py:264 -#, python-format -msgid "" -"This comment was flagged by %(user)s:\n" -"\n" -"%(text)s" -msgstr "" -"Este comentario fue marcado por %(user)s:\n" -"\n" -"%(text)s" - -#: contrib/comments/models.py:271 -msgid "flag date" -msgstr "fecha de la marca" - -#: contrib/comments/models.py:274 -msgid "user flag" -msgstr "marca de usuario" - -#: contrib/comments/models.py:275 -msgid "user flags" -msgstr "marcas de usuario" - -#: contrib/comments/models.py:279 -#, python-format -msgid "Flag by %r" -msgstr "Marca de %r" - -#: contrib/comments/models.py:284 -msgid "deletion date" -msgstr "fecha de eliminación" - -#: contrib/comments/models.py:286 -msgid "moderator deletion" -msgstr "eliminación de moderador" - -#: contrib/comments/models.py:287 -msgid "moderator deletions" -msgstr "eliminaciones de moderador" - -#: contrib/comments/models.py:291 -#, python-format -msgid "Moderator deletion by %r" -msgstr "Eliminación del moderador %r" - -#: contrib/comments/views/karma.py:20 -msgid "Anonymous users cannot vote" -msgstr "Los usuarios anónimos no pueden votar" - -#: contrib/comments/views/karma.py:24 -msgid "Invalid comment ID" -msgstr "ID de comentario no válido" - -#: contrib/comments/views/karma.py:26 -msgid "No voting for yourself" -msgstr "No puedes votarte tú mismo" - -#: contrib/comments/views/comments.py:28 -msgid "" -"This rating is required because you've entered at least one other rating." -msgstr "Se precisa esta puntuación porque ha introducido al menos otra más." - -#: contrib/comments/views/comments.py:112 -#, python-format -msgid "" -"This comment was posted by a user who has posted fewer than %(count)s " -"comment:\n" -"\n" -"%(text)s" -msgid_plural "" -"This comment was posted by a user who has posted fewer than %(count)s " -"comments:\n" -"\n" -"%(text)s" -msgstr[0] "" -"Este comentario lo envió un usuario que ha enviado menos de %(count)s " -"comentario:\n" -"\n" -"%(text)s" -msgstr[1] "" -"Este comentario lo envió un usuario que ha enviado menos de %(count)s " -"comentarios:\n" -"\n" -"%(text)s" - -#: contrib/comments/views/comments.py:117 -#, python-format -msgid "" -"This comment was posted by a sketchy user:\n" -"\n" -"%(text)s" -msgstr "" -"Este comentario ha sido colocado por un usuario poco preciso: \n" -"\n" -"%(text)s" - -#: contrib/comments/views/comments.py:189 -#: contrib/comments/views/comments.py:281 -msgid "Only POSTs are allowed" -msgstr "Sólo se admite POST" - -#: contrib/comments/views/comments.py:193 -#: contrib/comments/views/comments.py:285 -msgid "One or more of the required fields wasn't submitted" -msgstr "No se proporcionó uno o más de los siguientes campos requeridos" - -#: contrib/comments/views/comments.py:197 -#: contrib/comments/views/comments.py:287 -msgid "Somebody tampered with the comment form (security violation)" -msgstr "" -"Alguien está jugando con el formulario de comentarios (violación de " -"seguridad)" - -#: contrib/comments/views/comments.py:207 -#: contrib/comments/views/comments.py:293 -msgid "" -"The comment form had an invalid 'target' parameter -- the object ID was " -"invalid" -msgstr "" -"El formulario de comentarios tiene un parámetro 'target' no válido (el ID de " -"objeto era inválido)" - -#: contrib/comments/views/comments.py:258 -#: contrib/comments/views/comments.py:322 -msgid "The comment form didn't provide either 'preview' or 'post'" -msgstr "El formulario de comentario no proporcionó 'previsualizar' ni 'enviar'" - -#: contrib/comments/templates/comments/form.html:6 -#: contrib/comments/templates/comments/form.html:8 -#: contrib/admin/templates/admin/login.html:17 -msgid "Username:" -msgstr "Usuario:" - -#: contrib/comments/templates/comments/form.html:6 -#: contrib/admin/templates/admin/change_list.html:5 -#: contrib/admin/templates/admin/object_history.html:3 -#: contrib/admin/templates/admin/change_form.html:10 -#: contrib/admin/templates/admin/delete_confirmation.html:3 -#: contrib/admin/templates/admin/base.html:25 -#: contrib/admin/templates/admin/auth/user/change_password.html:9 -#: contrib/admin/templates/registration/password_change_done.html:3 -#: contrib/admin/templates/registration/password_change_form.html:3 -#: contrib/admin/templates/admin_doc/view_detail.html:4 -#: contrib/admin/templates/admin_doc/bookmarklets.html:4 -#: contrib/admin/templates/admin_doc/template_detail.html:4 -#: contrib/admin/templates/admin_doc/template_tag_index.html:5 -#: contrib/admin/templates/admin_doc/missing_docutils.html:4 -#: contrib/admin/templates/admin_doc/view_index.html:5 -#: contrib/admin/templates/admin_doc/model_detail.html:3 -#: contrib/admin/templates/admin_doc/index.html:4 -#: contrib/admin/templates/admin_doc/model_index.html:5 -#: contrib/admin/templates/admin_doc/template_filter_index.html:5 -msgid "Log out" -msgstr "Terminar sesión" - -#: contrib/comments/templates/comments/form.html:8 -#: contrib/admin/templates/admin/login.html:20 -msgid "Password:" -msgstr "Clave:" - -#: contrib/comments/templates/comments/form.html:8 -msgid "Forgotten your password?" -msgstr "¿Has olvidado tu contraseña?" - -#: contrib/comments/templates/comments/form.html:12 -msgid "Ratings" -msgstr "Calificaciones" - -#: contrib/comments/templates/comments/form.html:12 -#: contrib/comments/templates/comments/form.html:23 -msgid "Required" -msgstr "Requerido" - -#: contrib/comments/templates/comments/form.html:12 -#: contrib/comments/templates/comments/form.html:23 -msgid "Optional" -msgstr "Opcional" - -#: contrib/comments/templates/comments/form.html:23 -msgid "Post a photo" -msgstr "Postea una fotografía" - -#: contrib/comments/templates/comments/form.html:28 -#: contrib/comments/templates/comments/freeform.html:5 -msgid "Comment:" -msgstr "Comentario:" - -#: contrib/comments/templates/comments/form.html:35 -#: contrib/comments/templates/comments/freeform.html:10 -msgid "Preview comment" -msgstr "Previsualizar comentario" - -#: contrib/comments/templates/comments/freeform.html:4 -msgid "Your name:" -msgstr "Tu nombre:" - -#: contrib/flatpages/models.py:7 contrib/admin/views/doc.py:317 -msgid "URL" -msgstr "URL" - -#: contrib/flatpages/models.py:8 -msgid "" -"Example: '/about/contact/'. Make sure to have leading and trailing slashes." -msgstr "" -"Ejemplo: '/about/contact/'. Asegúrese de que pone barras al principio y al " -"final." - -#: contrib/flatpages/models.py:9 -msgid "title" -msgstr "título" - -#: contrib/flatpages/models.py:10 -msgid "content" -msgstr "contenido" - -#: contrib/flatpages/models.py:11 -msgid "enable comments" -msgstr "admitir comentarios" - -#: contrib/flatpages/models.py:12 -msgid "template name" -msgstr "nombre de plantilla" - -#: contrib/flatpages/models.py:13 -msgid "" -"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " -"will use 'flatpages/default.html'." -msgstr "" -"Ejemplo: 'flatpages/contact_page.html'. Si no es proporcionado, el sistema " -"usará 'flatpages/default.html'." - -#: contrib/flatpages/models.py:14 -msgid "registration required" -msgstr "debe estar registrado" - -#: contrib/flatpages/models.py:14 -msgid "If this is checked, only logged-in users will be able to view the page." -msgstr "Si está marcado, sólo los usuarios registrados podrán ver la página." - -#: contrib/flatpages/models.py:18 -msgid "flat page" -msgstr "página estática" - -#: contrib/flatpages/models.py:19 -msgid "flat pages" -msgstr "páginas estáticas" - -#: contrib/sessions/models.py:68 -msgid "session key" -msgstr "clave de sesión" - -#: contrib/sessions/models.py:69 -msgid "session data" -msgstr "datos de sesión" +#: contrib/auth/views.py:47 +msgid "Logged out" +msgstr "Sesión terminada" -#: contrib/sessions/models.py:70 -msgid "expire date" -msgstr "fecha de caducidad" +#: contrib/admin/models.py:17 +msgid "action time" +msgstr "hora de acción" -#: contrib/sessions/models.py:74 -msgid "session" -msgstr "sesión" +#: contrib/admin/models.py:20 +msgid "object id" +msgstr "id de objeto" -#: contrib/sessions/models.py:75 -msgid "sessions" -msgstr "sesiones" +#: contrib/admin/models.py:21 +msgid "object repr" +msgstr "repr de objeto" -#: contrib/sites/models.py:15 -msgid "domain name" -msgstr "nombre de dominio" +#: contrib/admin/models.py:22 +msgid "action flag" +msgstr "marca de acción" -#: contrib/sites/models.py:16 -msgid "display name" -msgstr "nombre para mostrar" +#: contrib/admin/models.py:23 +msgid "change message" +msgstr "mensaje de cambio" -#: contrib/sites/models.py:20 -msgid "site" -msgstr "sitio" +#: contrib/admin/models.py:26 +msgid "log entry" +msgstr "entrada de registro" -#: contrib/sites/models.py:21 -msgid "sites" -msgstr "sitios" +#: contrib/admin/models.py:27 +msgid "log entries" +msgstr "entradas de registro" #: contrib/admin/filterspecs.py:42 #, python-format @@ -1422,8 +747,10 @@ msgstr "" "<h3>Por %s:</h3>\n" "<ul>\n" -#: contrib/admin/filterspecs.py:72 contrib/admin/filterspecs.py:90 -#: contrib/admin/filterspecs.py:145 contrib/admin/filterspecs.py:171 +#: contrib/admin/filterspecs.py:72 +#: contrib/admin/filterspecs.py:90 +#: contrib/admin/filterspecs.py:145 +#: contrib/admin/filterspecs.py:171 msgid "All" msgstr "Todo" @@ -1447,66 +774,64 @@ msgstr "Este mes" msgid "This year" msgstr "Este año" -#: contrib/admin/models.py:17 -msgid "action time" -msgstr "hora de acción" +#: contrib/admin/filterspecs.py:145 +#: oldforms/__init__.py:591 +#: newforms/widgets.py:188 +msgid "Yes" +msgstr "Sí" -#: contrib/admin/models.py:20 -msgid "object id" -msgstr "id de objeto" +#: contrib/admin/filterspecs.py:145 +#: oldforms/__init__.py:591 +#: newforms/widgets.py:188 +msgid "No" +msgstr "No" -#: contrib/admin/models.py:21 -msgid "object repr" -msgstr "repr de objeto" +#: contrib/admin/filterspecs.py:152 +#: oldforms/__init__.py:591 +#: newforms/widgets.py:188 +msgid "Unknown" +msgstr "Desconocido" -#: contrib/admin/models.py:22 -msgid "action flag" -msgstr "marca de acción" +#: contrib/admin/views/decorators.py:24 +#: contrib/admin/templates/admin/login.html:25 +msgid "Log in" +msgstr "Identificarse" -#: contrib/admin/models.py:23 -msgid "change message" -msgstr "mensaje de cambio" +#: contrib/admin/views/decorators.py:62 +msgid "Please log in again, because your session has expired. Don't worry: Your submission has been saved." +msgstr "Por favor, identifíquese de nuevo, porque su sesión ha caducado. No se preocupe: se ha guardado su envío." -#: contrib/admin/models.py:26 -msgid "log entry" -msgstr "entrada de registro" +#: contrib/admin/views/decorators.py:69 +msgid "Looks like your browser isn't configured to accept cookies. Please enable cookies, reload this page, and try again." +msgstr "Parece que su navegador no está configurado para aceptar cookies. Actívelas por favor, recargue esta página, e inténtelo de nuevo." -#: contrib/admin/models.py:27 -msgid "log entries" -msgstr "entradas de registro" +#: contrib/admin/views/decorators.py:83 +msgid "Usernames cannot contain the '@' character." +msgstr "Los nombres de usuario no pueden contener el carácter '@'." -#: contrib/admin/templatetags/admin_list.py:254 -msgid "All dates" -msgstr "Todas las fechas" +#: contrib/admin/views/decorators.py:85 +#, python-format +msgid "Your e-mail address is not your username. Try '%s' instead." +msgstr "Su dirección de correo no es su nombre de usuario. Pruebe con '%s' en su lugar." + +#: contrib/admin/views/main.py:230 +msgid "Site administration" +msgstr "Sitio administrativo" -#: contrib/admin/views/auth.py:20 contrib/admin/views/main.py:264 +#: contrib/admin/views/main.py:264 +#: contrib/admin/views/auth.py:20 #, python-format msgid "The %(name)s \"%(obj)s\" was added successfully." msgstr "Se añadió con éxito el %(name)s \"%(obj)s\"." -#: contrib/admin/views/auth.py:25 contrib/admin/views/main.py:268 +#: contrib/admin/views/main.py:268 #: contrib/admin/views/main.py:354 +#: contrib/admin/views/auth.py:25 msgid "You may edit it again below." msgstr "Puede editarlo de nuevo abajo." -#: contrib/admin/views/auth.py:31 -msgid "Add user" -msgstr "Añadir usuario" - -#: contrib/admin/views/auth.py:58 -msgid "Password changed successfully." -msgstr "La clave se ha cambiado exitosamente." - -#: contrib/admin/views/auth.py:65 -#, python-format -msgid "Change password: %s" -msgstr "Cambiar clave: %s" - -#: contrib/admin/views/main.py:230 -msgid "Site administration" -msgstr "Sitio administrativo" - -#: contrib/admin/views/main.py:278 contrib/admin/views/main.py:363 +#: contrib/admin/views/main.py:278 +#: contrib/admin/views/main.py:363 #, python-format msgid "You may add another %s below." msgstr "Puede agregar otro %s abajo." @@ -1542,10 +867,8 @@ msgstr "Se modificó con éxito el %(name)s \"%(obj)s." #: contrib/admin/views/main.py:360 #, python-format -msgid "" -"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below." -msgstr "" -"Se agregó con éxito el %(name)s \"%(obj)s. Puede editarlo de nuevo abajo." +msgid "The %(name)s \"%(obj)s\" was added successfully. You may edit it again below." +msgstr "Se agregó con éxito el %(name)s \"%(obj)s. Puede editarlo de nuevo abajo." #: contrib/admin/views/main.py:398 #, python-format @@ -1590,49 +913,20 @@ msgstr "Escoja %s para modificar" msgid "Database error" msgstr "Erorr en la base de datos" -#: contrib/admin/views/decorators.py:24 -#: contrib/admin/templates/admin/login.html:25 -msgid "Log in" -msgstr "Identificarse" - -#: contrib/admin/views/decorators.py:62 -msgid "" -"Please log in again, because your session has expired. Don't worry: Your " -"submission has been saved." -msgstr "" -"Por favor, identifíquese de nuevo, porque su sesión ha caducado. No se " -"preocupe: se ha guardado su envío." - -#: contrib/admin/views/decorators.py:69 -msgid "" -"Looks like your browser isn't configured to accept cookies. Please enable " -"cookies, reload this page, and try again." -msgstr "" -"Parece que su navegador no está configurado para aceptar cookies. Actívelas " -"por favor, recargue esta página, e inténtelo de nuevo." - -#: contrib/admin/views/decorators.py:83 -msgid "Usernames cannot contain the '@' character." -msgstr "Los nombres de usuario no pueden contener el carácter '@'." - -#: contrib/admin/views/decorators.py:85 -#, python-format -msgid "Your e-mail address is not your username. Try '%s' instead." -msgstr "" -"Su dirección de correo no es su nombre de usuario. Pruebe con '%s' en su " -"lugar." - -#: contrib/admin/views/doc.py:47 contrib/admin/views/doc.py:49 +#: contrib/admin/views/doc.py:47 +#: contrib/admin/views/doc.py:49 #: contrib/admin/views/doc.py:51 msgid "tag:" msgstr "etiqueta:" -#: contrib/admin/views/doc.py:78 contrib/admin/views/doc.py:80 +#: contrib/admin/views/doc.py:78 +#: contrib/admin/views/doc.py:80 #: contrib/admin/views/doc.py:82 msgid "filter:" msgstr "filtro:" -#: contrib/admin/views/doc.py:136 contrib/admin/views/doc.py:138 +#: contrib/admin/views/doc.py:136 +#: contrib/admin/views/doc.py:138 #: contrib/admin/views/doc.py:140 msgid "view:" msgstr "vista:" @@ -1652,8 +946,10 @@ msgstr "El modelo %(name)s no se ha encontrado en la aplicación %(label)r" msgid "the related `%(label)s.%(type)s` object" msgstr "el objeto relacionado`%(label)s.%(type)s` " -#: contrib/admin/views/doc.py:184 contrib/admin/views/doc.py:206 -#: contrib/admin/views/doc.py:220 contrib/admin/views/doc.py:225 +#: contrib/admin/views/doc.py:184 +#: contrib/admin/views/doc.py:206 +#: contrib/admin/views/doc.py:220 +#: contrib/admin/views/doc.py:225 msgid "model:" msgstr "modelo:" @@ -1677,9 +973,12 @@ msgstr "número de %s" msgid "Fields on %s objects" msgstr "Campos en %s objetos" -#: contrib/admin/views/doc.py:292 contrib/admin/views/doc.py:303 -#: contrib/admin/views/doc.py:305 contrib/admin/views/doc.py:311 -#: contrib/admin/views/doc.py:312 contrib/admin/views/doc.py:314 +#: contrib/admin/views/doc.py:292 +#: contrib/admin/views/doc.py:303 +#: contrib/admin/views/doc.py:305 +#: contrib/admin/views/doc.py:311 +#: contrib/admin/views/doc.py:312 +#: contrib/admin/views/doc.py:314 msgid "Integer" msgstr "Entero" @@ -1687,7 +986,8 @@ msgstr "Entero" msgid "Boolean (Either True or False)" msgstr "Booleano (Verdadero o Falso)" -#: contrib/admin/views/doc.py:294 contrib/admin/views/doc.py:313 +#: contrib/admin/views/doc.py:294 +#: contrib/admin/views/doc.py:313 #, python-format msgid "String (up to %(max_length)s)" msgstr "Cadena (máximo %(max_length)s)" @@ -1712,7 +1012,8 @@ msgstr "Número decimal" msgid "E-mail address" msgstr "Dirección de correo electrónico" -#: contrib/admin/views/doc.py:300 contrib/admin/views/doc.py:301 +#: contrib/admin/views/doc.py:300 +#: contrib/admin/views/doc.py:301 #: contrib/admin/views/doc.py:304 msgid "File path" msgstr "Ruta de fichero" @@ -1721,6 +1022,11 @@ msgstr "Ruta de fichero" msgid "Floating point number" msgstr "Número decimal" +#: contrib/admin/views/doc.py:306 +#: contrib/comments/models.py:85 +msgid "IP address" +msgstr "Dirección IP" + #: contrib/admin/views/doc.py:308 msgid "Boolean (Either True, False or None)" msgstr "Booleano (Verdadero, Falso o Nulo)" @@ -1741,6 +1047,11 @@ msgstr "Texto" msgid "Time" msgstr "Hora" +#: contrib/admin/views/doc.py:317 +#: contrib/flatpages/models.py:7 +msgid "URL" +msgstr "URL" + #: contrib/admin/views/doc.py:318 msgid "U.S. state (two uppercase letters)" msgstr "Estado de los EEUU (dos letras mayúsculas)" @@ -1754,171 +1065,183 @@ msgstr "Texto XML" msgid "%s does not appear to be a urlpattern object" msgstr "%s no parece ser un objeto urlpattern" -#: contrib/admin/templates/widget/file.html:2 -msgid "Currently:" -msgstr "Actualmente:" +#: contrib/admin/views/auth.py:31 +msgid "Add user" +msgstr "Añadir usuario" -#: contrib/admin/templates/widget/file.html:3 -msgid "Change:" -msgstr "Modificar:" +#: contrib/admin/views/auth.py:58 +msgid "Password changed successfully." +msgstr "La clave se ha cambiado exitosamente." -#: contrib/admin/templates/widget/date_time.html:3 -msgid "Date:" -msgstr "Fecha:" +#: contrib/admin/views/auth.py:65 +#, python-format +msgid "Change password: %s" +msgstr "Cambiar clave: %s" -#: contrib/admin/templates/widget/date_time.html:4 -msgid "Time:" -msgstr "Hora:" +#: contrib/admin/templatetags/admin_list.py:254 +msgid "All dates" +msgstr "Todas las fechas" + +#: contrib/admin/templates/admin/pagination.html:10 +msgid "Show all" +msgstr "Mostrarlo todo" +#: contrib/admin/templates/admin/delete_confirmation.html:3 +#: contrib/admin/templates/admin/change_form.html:10 #: contrib/admin/templates/admin/change_list.html:5 #: contrib/admin/templates/admin/object_history.html:3 -#: contrib/admin/templates/admin/change_form.html:10 -#: contrib/admin/templates/admin/delete_confirmation.html:3 #: contrib/admin/templates/admin/base.html:25 #: contrib/admin/templates/admin/auth/user/change_password.html:9 -#: contrib/admin/templates/registration/password_change_done.html:3 -#: contrib/admin/templates/registration/password_change_form.html:3 #: contrib/admin/templates/admin_doc/bookmarklets.html:3 +#: contrib/admin/templates/registration/password_change_form.html:3 +#: contrib/admin/templates/registration/password_change_done.html:3 msgid "Documentation" msgstr "Documentación" +#: contrib/admin/templates/admin/delete_confirmation.html:3 +#: contrib/admin/templates/admin/change_form.html:10 #: contrib/admin/templates/admin/change_list.html:5 #: contrib/admin/templates/admin/object_history.html:3 -#: contrib/admin/templates/admin/change_form.html:10 -#: contrib/admin/templates/admin/delete_confirmation.html:3 #: contrib/admin/templates/admin/base.html:25 #: contrib/admin/templates/admin/auth/user/change_password.html:9 #: contrib/admin/templates/admin/auth/user/change_password.html:15 #: contrib/admin/templates/admin/auth/user/change_password.html:46 -#: contrib/admin/templates/registration/password_change_done.html:3 -#: contrib/admin/templates/registration/password_change_form.html:3 -#: contrib/admin/templates/admin_doc/view_detail.html:4 +#: contrib/admin/templates/admin_doc/template_filter_index.html:5 #: contrib/admin/templates/admin_doc/bookmarklets.html:4 -#: contrib/admin/templates/admin_doc/template_detail.html:4 #: contrib/admin/templates/admin_doc/template_tag_index.html:5 +#: contrib/admin/templates/admin_doc/index.html:4 +#: contrib/admin/templates/admin_doc/model_detail.html:3 #: contrib/admin/templates/admin_doc/missing_docutils.html:4 +#: contrib/admin/templates/admin_doc/template_detail.html:4 #: contrib/admin/templates/admin_doc/view_index.html:5 -#: contrib/admin/templates/admin_doc/model_detail.html:3 -#: contrib/admin/templates/admin_doc/index.html:4 #: contrib/admin/templates/admin_doc/model_index.html:5 -#: contrib/admin/templates/admin_doc/template_filter_index.html:5 +#: contrib/admin/templates/admin_doc/view_detail.html:4 +#: contrib/admin/templates/registration/password_change_form.html:3 +#: contrib/admin/templates/registration/password_change_done.html:3 msgid "Change password" msgstr "Cambiar clave" +#: contrib/admin/templates/admin/delete_confirmation.html:3 +#: contrib/admin/templates/admin/change_form.html:10 +#: contrib/admin/templates/admin/change_list.html:5 +#: contrib/admin/templates/admin/object_history.html:3 +#: contrib/admin/templates/admin/base.html:25 +#: contrib/admin/templates/admin/auth/user/change_password.html:9 +#: contrib/admin/templates/admin_doc/template_filter_index.html:5 +#: contrib/admin/templates/admin_doc/bookmarklets.html:4 +#: contrib/admin/templates/admin_doc/template_tag_index.html:5 +#: contrib/admin/templates/admin_doc/index.html:4 +#: contrib/admin/templates/admin_doc/model_detail.html:3 +#: contrib/admin/templates/admin_doc/missing_docutils.html:4 +#: contrib/admin/templates/admin_doc/template_detail.html:4 +#: contrib/admin/templates/admin_doc/view_index.html:5 +#: contrib/admin/templates/admin_doc/model_index.html:5 +#: contrib/admin/templates/admin_doc/view_detail.html:4 +#: contrib/admin/templates/registration/password_change_form.html:3 +#: contrib/admin/templates/registration/password_change_done.html:3 +#: contrib/comments/templates/comments/form.html:6 +msgid "Log out" +msgstr "Terminar sesión" + +#: contrib/admin/templates/admin/delete_confirmation.html:6 +#: contrib/admin/templates/admin/change_form.html:13 #: contrib/admin/templates/admin/change_list.html:6 #: contrib/admin/templates/admin/object_history.html:5 #: contrib/admin/templates/admin/500.html:4 #: contrib/admin/templates/admin/invalid_setup.html:4 -#: contrib/admin/templates/admin/change_form.html:13 -#: contrib/admin/templates/admin/delete_confirmation.html:6 #: contrib/admin/templates/admin/base.html:30 #: contrib/admin/templates/admin/auth/user/change_password.html:12 -#: contrib/admin/templates/registration/password_change_done.html:4 +#: contrib/admin/templates/admin_doc/bookmarklets.html:3 #: contrib/admin/templates/registration/password_reset_form.html:4 #: contrib/admin/templates/registration/logged_out.html:4 #: contrib/admin/templates/registration/password_reset_done.html:4 #: contrib/admin/templates/registration/password_change_form.html:4 -#: contrib/admin/templates/admin_doc/bookmarklets.html:3 +#: contrib/admin/templates/registration/password_change_done.html:4 msgid "Home" msgstr "Inicio" -#: contrib/admin/templates/admin/change_list.html:12 -#, python-format -msgid "Add %(name)s" -msgstr "Agregar %(name)s" +#: contrib/admin/templates/admin/delete_confirmation.html:9 +#: contrib/admin/templates/admin/submit_line.html:3 +msgid "Delete" +msgstr "Eliminar" -#: contrib/admin/templates/admin/filter.html:2 +#: contrib/admin/templates/admin/delete_confirmation.html:14 #, python-format -msgid " By %(filter_title)s " -msgstr " Por %(filter_title)s " - -#: contrib/admin/templates/admin/object_history.html:5 -#: contrib/admin/templates/admin/change_form.html:21 -msgid "History" -msgstr "Histórico" +msgid "Deleting the %(object_name)s '%(escaped_object)s' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" +msgstr "Eliminar el %(object_name)s '%(escaped_object)s' provocaría la eliminación de objetos relacionados, pero su cuenta no tiene permiso para borrar los siguientes tipos de objetos:" -#: contrib/admin/templates/admin/object_history.html:18 -msgid "Date/time" -msgstr "Fecha/hora" +#: contrib/admin/templates/admin/delete_confirmation.html:21 +#, python-format +msgid "Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? All of the following related items will be deleted:" +msgstr "¿Está seguro de que quiere borrar los %(object_name)s \"%(escaped_object)s\"? Se borrarán los siguientes objetos relacionados:" -#: contrib/admin/templates/admin/object_history.html:19 -msgid "User" -msgstr "Usuario" +#: contrib/admin/templates/admin/delete_confirmation.html:26 +msgid "Yes, I'm sure" +msgstr "Sí, estoy seguro" -#: contrib/admin/templates/admin/object_history.html:20 -msgid "Action" -msgstr "Acción" +#: contrib/admin/templates/admin/404.html:4 +#: contrib/admin/templates/admin/404.html:8 +msgid "Page not found" +msgstr "Página no encontrada" -#: contrib/admin/templates/admin/object_history.html:26 -msgid "DATE_WITH_TIME_FULL" -msgstr "j M Y P" +#: contrib/admin/templates/admin/404.html:10 +msgid "We're sorry, but the requested page could not be found." +msgstr "Lo sentimos, pero no se encuentra la página solicitada." -#: contrib/admin/templates/admin/object_history.html:36 -msgid "" -"This object doesn't have a change history. It probably wasn't added via this " -"admin site." -msgstr "" -"Este objeto no tiene histórico de cambios. Probablemente no fue añadido " -"usando este sitio de administración." +#: contrib/admin/templates/admin/change_form.html:15 +#: contrib/admin/templates/admin/index.html:28 +msgid "Add" +msgstr "Agregar" -#: contrib/admin/templates/admin/search_form.html:8 -msgid "Go" -msgstr "Buscar" +#: contrib/admin/templates/admin/change_form.html:21 +#: contrib/admin/templates/admin/object_history.html:5 +msgid "History" +msgstr "Histórico" -#: contrib/admin/templates/admin/search_form.html:10 -#, python-format -msgid "1 result" -msgid_plural "%(counter)s results" -msgstr[0] "1 resultado" -msgstr[1] "%(counter)s resultados" +#: contrib/admin/templates/admin/change_form.html:22 +msgid "View on site" +msgstr "Ver en el sitio" -#: contrib/admin/templates/admin/search_form.html:10 -#, python-format -msgid "%(full_result_count)s total" -msgstr "%(full_result_count)s total" +#: contrib/admin/templates/admin/change_form.html:32 +#: contrib/admin/templates/admin/auth/user/change_password.html:24 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "Por favor, corrija el siguiente error." +msgstr[1] "Por favor, corrija los siguientes errores." -#: contrib/admin/templates/admin/pagination.html:10 -msgid "Show all" -msgstr "Mostrarlo todo" +#: contrib/admin/templates/admin/change_form.html:50 +msgid "Ordering" +msgstr "Ordenación" -#: contrib/admin/templates/admin/base_site.html:4 -msgid "Django site admin" -msgstr "Sitio de administración de Django" +#: contrib/admin/templates/admin/change_form.html:53 +msgid "Order:" +msgstr "Orden:" -#: contrib/admin/templates/admin/base_site.html:7 -msgid "Django administration" -msgstr "Administración de Django" +#: contrib/admin/templates/admin/filter.html:2 +#, python-format +msgid " By %(filter_title)s " +msgstr " Por %(filter_title)s " -#: contrib/admin/templates/admin/500.html:4 -msgid "Server error" -msgstr "Error del servidor" +#: contrib/admin/templates/admin/submit_line.html:4 +msgid "Save as new" +msgstr "Grabar como nuevo" -#: contrib/admin/templates/admin/500.html:6 -msgid "Server error (500)" -msgstr "Error del servidor (500)" +#: contrib/admin/templates/admin/submit_line.html:5 +msgid "Save and add another" +msgstr "Grabar y añadir otro" -#: contrib/admin/templates/admin/500.html:9 -msgid "Server Error <em>(500)</em>" -msgstr "Error de servidor <em>(500)</em>" +#: contrib/admin/templates/admin/submit_line.html:6 +msgid "Save and continue editing" +msgstr "Grabar y continuar editando" -#: contrib/admin/templates/admin/500.html:10 -msgid "" -"There's been an error. It's been reported to the site administrators via e-" -"mail and should be fixed shortly. Thanks for your patience." -msgstr "" -"Ha ocurrido un error. Se ha informado a los administradores del sitio " -"mediante correo electrónico y debería arreglarse en breve. Gracias por su " -"paciencia." +#: contrib/admin/templates/admin/submit_line.html:7 +msgid "Save" +msgstr "Grabar" -#: contrib/admin/templates/admin/invalid_setup.html:8 -msgid "" -"Something's wrong with your database installation. Make sure the appropriate " -"database tables have been created, and make sure the database is readable by " -"the appropriate user." -msgstr "" -"Algo va mal con la instalación de la base de datos. Asegúrate que las tablas " -"necesarias han sido creadas, y que la base de datos puede ser leída por el " -"usuario apropiado." +#: contrib/admin/templates/admin/change_list.html:12 +#, python-format +msgid "Add %(name)s" +msgstr "Agregar %(name)s" #: contrib/admin/templates/admin/index.html:17 #, python-format @@ -1930,11 +1253,6 @@ msgstr "Modelos disponibles en la aplicación %(name)s." msgid "%(name)s" msgstr "%(name)s" -#: contrib/admin/templates/admin/index.html:28 -#: contrib/admin/templates/admin/change_form.html:15 -msgid "Add" -msgstr "Agregar" - #: contrib/admin/templates/admin/index.html:34 msgid "Change" msgstr "Modificar" @@ -1955,94 +1273,92 @@ msgstr "Mis acciones" msgid "None available" msgstr "Ninguno disponible" -#: contrib/admin/templates/admin/404.html:4 -#: contrib/admin/templates/admin/404.html:8 -msgid "Page not found" -msgstr "Página no encontrada" +#: contrib/admin/templates/admin/base_site.html:4 +msgid "Django site admin" +msgstr "Sitio de administración de Django" -#: contrib/admin/templates/admin/404.html:10 -msgid "We're sorry, but the requested page could not be found." -msgstr "Lo sentimos, pero no se encuentra la página solicitada." +#: contrib/admin/templates/admin/base_site.html:7 +msgid "Django administration" +msgstr "Administración de Django" -#: contrib/admin/templates/admin/filters.html:4 -msgid "Filter" -msgstr "Filtro" +#: contrib/admin/templates/admin/object_history.html:18 +msgid "Date/time" +msgstr "Fecha/hora" -#: contrib/admin/templates/admin/change_form.html:22 -msgid "View on site" -msgstr "Ver en el sitio" +#: contrib/admin/templates/admin/object_history.html:19 +msgid "User" +msgstr "Usuario" -#: contrib/admin/templates/admin/change_form.html:32 -#: contrib/admin/templates/admin/auth/user/change_password.html:24 -msgid "Please correct the error below." -msgid_plural "Please correct the errors below." -msgstr[0] "Por favor, corrija el siguiente error." -msgstr[1] "Por favor, corrija los siguientes errores." +#: contrib/admin/templates/admin/object_history.html:20 +msgid "Action" +msgstr "Acción" -#: contrib/admin/templates/admin/change_form.html:50 -msgid "Ordering" -msgstr "Ordenación" +#: contrib/admin/templates/admin/object_history.html:26 +msgid "DATE_WITH_TIME_FULL" +msgstr "j M Y P" -#: contrib/admin/templates/admin/change_form.html:53 -msgid "Order:" -msgstr "Orden:" +#: contrib/admin/templates/admin/object_history.html:36 +msgid "This object doesn't have a change history. It probably wasn't added via this admin site." +msgstr "Este objeto no tiene histórico de cambios. Probablemente no fue añadido usando este sitio de administración." -#: contrib/admin/templates/admin/delete_confirmation.html:9 -#: contrib/admin/templates/admin/submit_line.html:3 -msgid "Delete" -msgstr "Eliminar" +#: contrib/admin/templates/admin/500.html:4 +msgid "Server error" +msgstr "Error del servidor" -#: contrib/admin/templates/admin/delete_confirmation.html:14 +#: contrib/admin/templates/admin/500.html:6 +msgid "Server error (500)" +msgstr "Error del servidor (500)" + +#: contrib/admin/templates/admin/500.html:9 +msgid "Server Error <em>(500)</em>" +msgstr "Error de servidor <em>(500)</em>" + +#: contrib/admin/templates/admin/500.html:10 +msgid "There's been an error. It's been reported to the site administrators via e-mail and should be fixed shortly. Thanks for your patience." +msgstr "Ha ocurrido un error. Se ha informado a los administradores del sitio mediante correo electrónico y debería arreglarse en breve. Gracias por su paciencia." + +#: contrib/admin/templates/admin/invalid_setup.html:8 +msgid "Something's wrong with your database installation. Make sure the appropriate database tables have been created, and make sure the database is readable by the appropriate user." +msgstr "Algo va mal con la instalación de la base de datos. Asegúrate que las tablas necesarias han sido creadas, y que la base de datos puede ser leída por el usuario apropiado." + +#: contrib/admin/templates/admin/search_form.html:8 +msgid "Go" +msgstr "Buscar" + +#: contrib/admin/templates/admin/search_form.html:10 #, python-format -msgid "" -"Deleting the %(object_name)s '%(escaped_object)s' would result in deleting " -"related objects, but your account doesn't have permission to delete the " -"following types of objects:" -msgstr "" -"Eliminar el %(object_name)s '%(escaped_object)s' provocaría la eliminación " -"de objetos relacionados, pero su cuenta no tiene permiso para borrar los " -"siguientes tipos de objetos:" +msgid "1 result" +msgid_plural "%(counter)s results" +msgstr[0] "1 resultado" +msgstr[1] "%(counter)s resultados" -#: contrib/admin/templates/admin/delete_confirmation.html:21 +#: contrib/admin/templates/admin/search_form.html:10 #, python-format -msgid "" -"Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? " -"All of the following related items will be deleted:" -msgstr "" -"¿Está seguro de que quiere borrar los %(object_name)s \"%(escaped_object)s" -"\"? Se borrarán los siguientes objetos relacionados:" +msgid "%(full_result_count)s total" +msgstr "%(full_result_count)s total" -#: contrib/admin/templates/admin/delete_confirmation.html:26 -msgid "Yes, I'm sure" -msgstr "Sí, estoy seguro" +#: contrib/admin/templates/admin/filters.html:4 +msgid "Filter" +msgstr "Filtro" + +#: contrib/admin/templates/admin/login.html:17 +#: contrib/comments/templates/comments/form.html:6 +#: contrib/comments/templates/comments/form.html:8 +msgid "Username:" +msgstr "Usuario:" + +#: contrib/admin/templates/admin/login.html:20 +#: contrib/comments/templates/comments/form.html:8 +msgid "Password:" +msgstr "Clave:" #: contrib/admin/templates/admin/base.html:25 msgid "Welcome," msgstr "Bienvenido," -#: contrib/admin/templates/admin/submit_line.html:4 -msgid "Save as new" -msgstr "Grabar como nuevo" - -#: contrib/admin/templates/admin/submit_line.html:5 -msgid "Save and add another" -msgstr "Grabar y añadir otro" - -#: contrib/admin/templates/admin/submit_line.html:6 -msgid "Save and continue editing" -msgstr "Grabar y continuar editando" - -#: contrib/admin/templates/admin/submit_line.html:7 -msgid "Save" -msgstr "Grabar" - #: contrib/admin/templates/admin/auth/user/add_form.html:6 -msgid "" -"First, enter a username and password. Then, you'll be able to edit more user " -"options." -msgstr "" -"Primero introduzca un nombre de usuario y una contraseña. Luego podrá editar " -"el resto de opciones del usuario." +msgid "First, enter a username and password. Then, you'll be able to edit more user options." +msgstr "Primero introduzca un nombre de usuario y una contraseña. Luego podrá editar el resto de opciones del usuario." #: contrib/admin/templates/admin/auth/user/add_form.html:12 msgid "Username" @@ -2066,25 +1382,81 @@ msgstr "Introduzca la misma contraseña que arriba, para verificación" #: contrib/admin/templates/admin/auth/user/change_password.html:28 #, python-format msgid "Enter a new password for the user <strong>%(username)s</strong>." +msgstr "Introduzca una nueva contraseña para el usuario <strong>%(username)s</strong>." + +#: contrib/admin/templates/admin_doc/bookmarklets.html:3 +msgid "Bookmarklets" +msgstr "Bookmarklets" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:5 +msgid "Documentation bookmarklets" +msgstr "Bookmarklets de documentación" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:9 +msgid "" +"\n" +"<p class=\"help\">To install bookmarklets, drag the link to your bookmarks\n" +"toolbar, or right-click the link and add it to your bookmarks. Now you can\n" +"select the bookmarklet from any page in the site. Note that some of these\n" +"bookmarklets require you to be viewing the site from a computer designated\n" +"as \"internal\" (talk to your system administrator if you aren't sure if\n" +"your computer is \"internal\").</p>\n" msgstr "" -"Introduzca una nueva contraseña para el usuario <strong>%(username)s</" -"strong>." +"\n" +"<p class=\"help\">Para instalar bookmarklets, arrastre el enlace a su barra\n" +"de favoritos, o pulse con el botón derecho el enlace y añádalo a sus favoritos.\n" +"Ahora puede escoger el bookmarklet desde cualquier página en el sitio.\n" +"Observer que algunos de estos bookmarklets precisan que esté viendo\n" +"el sitio desde un computador señalado como \"interno\" (hable\n" +"con su administrador de sistemas si no está seguro de si el suyo lo es).</p>\n" -#: contrib/admin/templates/registration/password_change_done.html:4 -#: contrib/admin/templates/registration/password_change_form.html:4 -#: contrib/admin/templates/registration/password_change_form.html:6 -#: contrib/admin/templates/registration/password_change_form.html:10 -msgid "Password change" -msgstr "Cambio de clave" +#: contrib/admin/templates/admin_doc/bookmarklets.html:19 +msgid "Documentation for this page" +msgstr "Documentación de esta página" -#: contrib/admin/templates/registration/password_change_done.html:6 -#: contrib/admin/templates/registration/password_change_done.html:10 -msgid "Password change successful" -msgstr "Cambio de clave exitoso" +#: contrib/admin/templates/admin_doc/bookmarklets.html:20 +msgid "Jumps you from any page to the documentation for the view that generates that page." +msgstr "Le lleva desde cualquier página a la documentación de la vista que la genera." -#: contrib/admin/templates/registration/password_change_done.html:12 -msgid "Your password was changed." -msgstr "Su clave ha sido cambiada." +#: contrib/admin/templates/admin_doc/bookmarklets.html:22 +msgid "Show object ID" +msgstr "Mostrar ID de objeto" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:23 +msgid "Shows the content-type and unique ID for pages that represent a single object." +msgstr "Muestra el tipo de contenido e ID unívoco de las páginas que representan un único objeto." + +#: contrib/admin/templates/admin_doc/bookmarklets.html:25 +msgid "Edit this object (current window)" +msgstr "Editar este objeto (ventana actual)" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:26 +msgid "Jumps to the admin page for pages that represent a single object." +msgstr "Le lleva a la página de administración de páginas que representan un único objeto." + +#: contrib/admin/templates/admin_doc/bookmarklets.html:28 +msgid "Edit this object (new window)" +msgstr "Editar este objeto (nueva ventana)" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:29 +msgid "As above, but opens the admin page in a new window." +msgstr "Como antes, pero abre la página de administración en una nueva ventana." + +#: contrib/admin/templates/widget/date_time.html:3 +msgid "Date:" +msgstr "Fecha:" + +#: contrib/admin/templates/widget/date_time.html:4 +msgid "Time:" +msgstr "Hora:" + +#: contrib/admin/templates/widget/file.html:2 +msgid "Currently:" +msgstr "Actualmente:" + +#: contrib/admin/templates/widget/file.html:3 +msgid "Change:" +msgstr "Modificar:" #: contrib/admin/templates/registration/password_reset_form.html:4 #: contrib/admin/templates/registration/password_reset_form.html:6 @@ -2094,12 +1466,8 @@ msgid "Password reset" msgstr "Recuperar clave" #: contrib/admin/templates/registration/password_reset_form.html:12 -msgid "" -"Forgotten your password? Enter your e-mail address below, and we'll reset " -"your password and e-mail the new one to you." -msgstr "" -"¿Ha olvidado su clave? Introduzca su dirección de correo electrónico, y " -"crearemos una nueva que le enviaremos por correo." +msgid "Forgotten your password? Enter your e-mail address below, and we'll reset your password and e-mail the new one to you." +msgstr "¿Ha olvidado su clave? Introduzca su dirección de correo electrónico, y crearemos una nueva que le enviaremos por correo." #: contrib/admin/templates/registration/password_reset_form.html:16 msgid "E-mail address:" @@ -2109,6 +1477,37 @@ msgstr "Dirección de correo electrónico:" msgid "Reset my password" msgstr "Recuperar mi clave" +#: contrib/admin/templates/registration/password_reset_email.html:2 +msgid "You're receiving this e-mail because you requested a password reset" +msgstr "Está recibiendo este mensaje debido a que solicitó recuperar la clave" + +#: contrib/admin/templates/registration/password_reset_email.html:3 +#, python-format +msgid "for your user account at %(site_name)s" +msgstr "de su cuenta de usuario en %(site_name)s." + +#: contrib/admin/templates/registration/password_reset_email.html:5 +#, python-format +msgid "Your new password is: %(new_password)s" +msgstr "Su nueva clave es: %(new_password)s" + +#: contrib/admin/templates/registration/password_reset_email.html:7 +msgid "Feel free to change this password by going to this page:" +msgstr "Puede cambiarla accediendo a esta página:" + +#: contrib/admin/templates/registration/password_reset_email.html:11 +msgid "Your username, in case you've forgotten:" +msgstr "Su nombre de usuario, en caso de haberlo olvidado:" + +#: contrib/admin/templates/registration/password_reset_email.html:13 +msgid "Thanks for using our site!" +msgstr "¡Gracias por usar nuestro sitio!" + +#: contrib/admin/templates/registration/password_reset_email.html:15 +#, python-format +msgid "The %(site_name)s team" +msgstr "El equipo de %(site_name)s" + #: contrib/admin/templates/registration/logged_out.html:8 msgid "Thanks for spending some quality time with the Web site today." msgstr "Gracias por el tiempo que ha dedicado al sitio web hoy." @@ -2123,20 +1522,19 @@ msgid "Password reset successful" msgstr "Recuperación de clave exitosa" #: contrib/admin/templates/registration/password_reset_done.html:12 -msgid "" -"We've e-mailed a new password to the e-mail address you submitted. You " -"should be receiving it shortly." -msgstr "" -"Le hemos enviado una clave nueva a la dirección que ha suministrado. Debería " -"recibirla en breve." +msgid "We've e-mailed a new password to the e-mail address you submitted. You should be receiving it shortly." +msgstr "Le hemos enviado una clave nueva a la dirección que ha suministrado. Debería recibirla en breve." + +#: contrib/admin/templates/registration/password_change_form.html:4 +#: contrib/admin/templates/registration/password_change_form.html:6 +#: contrib/admin/templates/registration/password_change_form.html:10 +#: contrib/admin/templates/registration/password_change_done.html:4 +msgid "Password change" +msgstr "Cambio de clave" #: contrib/admin/templates/registration/password_change_form.html:12 -msgid "" -"Please enter your old password, for security's sake, and then enter your new " -"password twice so we can verify you typed it in correctly." -msgstr "" -"Por favor, introduzca su clave antigua, por seguridad, y después introduzca " -"la nueva clave dos veces para verificar que la ha escrito correctamente." +msgid "Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly." +msgstr "Por favor, introduzca su clave antigua, por seguridad, y después introduzca la nueva clave dos veces para verificar que la ha escrito correctamente." #: contrib/admin/templates/registration/password_change_form.html:17 msgid "Old password:" @@ -2154,118 +1552,736 @@ msgstr "Confirme clave:" msgid "Change my password" msgstr "Cambiar mi clave" -#: contrib/admin/templates/registration/password_reset_email.html:2 -msgid "You're receiving this e-mail because you requested a password reset" -msgstr "Está recibiendo este mensaje debido a que solicitó recuperar la clave" +#: contrib/admin/templates/registration/password_change_done.html:6 +#: contrib/admin/templates/registration/password_change_done.html:10 +msgid "Password change successful" +msgstr "Cambio de clave exitoso" -#: contrib/admin/templates/registration/password_reset_email.html:3 +#: contrib/admin/templates/registration/password_change_done.html:12 +msgid "Your password was changed." +msgstr "Su clave ha sido cambiada." + +#: contrib/sites/models.py:33 +msgid "domain name" +msgstr "nombre de dominio" + +#: contrib/sites/models.py:34 +msgid "display name" +msgstr "nombre para mostrar" + +#: contrib/sites/models.py:38 +msgid "site" +msgstr "sitio" + +#: contrib/sites/models.py:39 +msgid "sites" +msgstr "sitios" + +#: contrib/humanize/templatetags/humanize.py:20 +msgid "th" +msgstr "th" + +#: contrib/humanize/templatetags/humanize.py:20 +msgid "st" +msgstr "st" + +#: contrib/humanize/templatetags/humanize.py:20 +msgid "nd" +msgstr "nd" + +#: contrib/humanize/templatetags/humanize.py:20 +msgid "rd" +msgstr "rd" + +#: contrib/humanize/templatetags/humanize.py:50 #, python-format -msgid "for your user account at %(site_name)s" -msgstr "de su cuenta de usuario en %(site_name)s." +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f millón" +msgstr[1] "%(value).1f millión" -#: contrib/admin/templates/registration/password_reset_email.html:5 +#: contrib/humanize/templatetags/humanize.py:53 #, python-format -msgid "Your new password is: %(new_password)s" -msgstr "Su nueva clave es: %(new_password)s" +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f billión" +msgstr[1] "%(value).1f billión" -#: contrib/admin/templates/registration/password_reset_email.html:7 -msgid "Feel free to change this password by going to this page:" -msgstr "Puede cambiarla accediendo a esta página:" +#: contrib/humanize/templatetags/humanize.py:56 +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f trillión" +msgstr[1] "%(value).1f trillión" -#: contrib/admin/templates/registration/password_reset_email.html:11 -msgid "Your username, in case you've forgotten:" -msgstr "Su nombre de usuario, en caso de haberlo olvidado:" +#: contrib/humanize/templatetags/humanize.py:71 +msgid "one" +msgstr "uno" -#: contrib/admin/templates/registration/password_reset_email.html:13 -msgid "Thanks for using our site!" -msgstr "¡Gracias por usar nuestro sitio!" +#: contrib/humanize/templatetags/humanize.py:71 +msgid "two" +msgstr "dos" -#: contrib/admin/templates/registration/password_reset_email.html:15 -#, python-format -msgid "The %(site_name)s team" -msgstr "El equipo de %(site_name)s" +#: contrib/humanize/templatetags/humanize.py:71 +msgid "three" +msgstr "tres" -#: contrib/admin/templates/admin_doc/bookmarklets.html:3 -msgid "Bookmarklets" -msgstr "Bookmarklets" +#: contrib/humanize/templatetags/humanize.py:71 +msgid "four" +msgstr "cuatro" -#: contrib/admin/templates/admin_doc/bookmarklets.html:5 -msgid "Documentation bookmarklets" -msgstr "Bookmarklets de documentación" +#: contrib/humanize/templatetags/humanize.py:71 +msgid "five" +msgstr "cinco" -#: contrib/admin/templates/admin_doc/bookmarklets.html:9 +#: contrib/humanize/templatetags/humanize.py:71 +msgid "six" +msgstr "seis" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "seven" +msgstr "siete" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "eight" +msgstr "ocho" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "nine" +msgstr "nueve" + +#: contrib/humanize/templatetags/humanize.py:90 +msgid "today" +msgstr "hoy" + +#: contrib/humanize/templatetags/humanize.py:92 +msgid "tomorrow" +msgstr "mañana" + +#: contrib/humanize/templatetags/humanize.py:94 +msgid "yesterday" +msgstr "ayer" + +#: contrib/flatpages/models.py:8 +msgid "Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "Ejemplo: '/about/contact/'. Asegúrese de que pone barras al principio y al final." + +#: contrib/flatpages/models.py:9 +msgid "title" +msgstr "título" + +#: contrib/flatpages/models.py:10 +msgid "content" +msgstr "contenido" + +#: contrib/flatpages/models.py:11 +msgid "enable comments" +msgstr "admitir comentarios" + +#: contrib/flatpages/models.py:12 +msgid "template name" +msgstr "nombre de plantilla" + +#: contrib/flatpages/models.py:13 +msgid "Example: 'flatpages/contact_page.html'. If this isn't provided, the system will use 'flatpages/default.html'." +msgstr "Ejemplo: 'flatpages/contact_page.html'. Si no es proporcionado, el sistema usará 'flatpages/default.html'." + +#: contrib/flatpages/models.py:14 +msgid "registration required" +msgstr "debe estar registrado" + +#: contrib/flatpages/models.py:14 +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "Si está marcado, sólo los usuarios registrados podrán ver la página." + +#: contrib/flatpages/models.py:18 +msgid "flat page" +msgstr "página estática" + +#: contrib/flatpages/models.py:19 +msgid "flat pages" +msgstr "páginas estáticas" + +#: contrib/redirects/models.py:7 +msgid "redirect from" +msgstr "redirigir desde" + +#: contrib/redirects/models.py:8 +msgid "This should be an absolute path, excluding the domain name. Example: '/events/search/'." +msgstr "Esta ruta debería ser absoluta, excluyendo el nombre de dominio. Ejeplo: '/events/search/'." + +#: contrib/redirects/models.py:9 +msgid "redirect to" +msgstr "redirigir a" + +#: contrib/redirects/models.py:10 +msgid "This can be either an absolute path (as above) or a full URL starting with 'http://'." +msgstr "Esto puede ser bien una ruta absoluta (como antes) o una URL completa que empiece con 'http://'." + +#: contrib/redirects/models.py:13 +msgid "redirect" +msgstr "redirección" + +#: contrib/redirects/models.py:14 +msgid "redirects" +msgstr "redirecciones" + +#: contrib/comments/models.py:67 +#: contrib/comments/models.py:169 +msgid "object ID" +msgstr "ID de objeto" + +#: contrib/comments/models.py:68 +msgid "headline" +msgstr "encabezado" + +#: contrib/comments/models.py:69 +#: contrib/comments/models.py:90 +#: contrib/comments/models.py:170 +msgid "comment" +msgstr "comentario" + +#: contrib/comments/models.py:70 +msgid "rating #1" +msgstr "calificación 1" + +#: contrib/comments/models.py:71 +msgid "rating #2" +msgstr "calificación 2" + +#: contrib/comments/models.py:72 +msgid "rating #3" +msgstr "calificación 3" + +#: contrib/comments/models.py:73 +msgid "rating #4" +msgstr "calificación 4" + +#: contrib/comments/models.py:74 +msgid "rating #5" +msgstr "calificación 5" + +#: contrib/comments/models.py:75 +msgid "rating #6" +msgstr "calificación 6" + +#: contrib/comments/models.py:76 +msgid "rating #7" +msgstr "calificación 7" + +#: contrib/comments/models.py:77 +msgid "rating #8" +msgstr "calificación 8" + +#: contrib/comments/models.py:82 +msgid "is valid rating" +msgstr "es calificación válida" + +#: contrib/comments/models.py:83 +#: contrib/comments/models.py:172 +msgid "date/time submitted" +msgstr "fecha/hora de envío" + +#: contrib/comments/models.py:84 +#: contrib/comments/models.py:173 +msgid "is public" +msgstr "es público" + +#: contrib/comments/models.py:86 +msgid "is removed" +msgstr "está eliminado" + +#: contrib/comments/models.py:86 +msgid "Check this box if the comment is inappropriate. A \"This comment has been removed\" message will be displayed instead." +msgstr "Marque esta caja si el comentario es inapropiado. En su lugar se mostrará \"Este comentario ha sido eliminado\"." + +#: contrib/comments/models.py:91 +msgid "comments" +msgstr "comentarios" + +#: contrib/comments/models.py:134 +#: contrib/comments/models.py:213 +msgid "Content object" +msgstr "Objeto contenido" + +#: contrib/comments/models.py:162 +#, python-format msgid "" +"Posted by %(user)s at %(date)s\n" "\n" -"<p class=\"help\">To install bookmarklets, drag the link to your bookmarks\n" -"toolbar, or right-click the link and add it to your bookmarks. Now you can\n" -"select the bookmarklet from any page in the site. Note that some of these\n" -"bookmarklets require you to be viewing the site from a computer designated\n" -"as \"internal\" (talk to your system administrator if you aren't sure if\n" -"your computer is \"internal\").</p>\n" +"%(comment)s\n" +"\n" +"http://%(domain)s%(url)s" msgstr "" +"Enviado por %(user)s en %(date)s\n" "\n" -"<p class=\"help\">Para instalar bookmarklets, arrastre el enlace a su barra\n" -"de favoritos, o pulse con el botón derecho el enlace y añádalo a sus " -"favoritos.\n" -"Ahora puede escoger el bookmarklet desde cualquier página en el sitio.\n" -"Observer que algunos de estos bookmarklets precisan que esté viendo\n" -"el sitio desde un computador señalado como \"interno\" (hable\n" -"con su administrador de sistemas si no está seguro de si el suyo lo es).</" -"p>\n" +"%(comment)s\n" +"\n" +"http://%(domain)s%(url)s" -#: contrib/admin/templates/admin_doc/bookmarklets.html:19 -msgid "Documentation for this page" -msgstr "Documentación de esta página" +#: contrib/comments/models.py:171 +msgid "person's name" +msgstr "nombre de la persona" -#: contrib/admin/templates/admin_doc/bookmarklets.html:20 +#: contrib/comments/models.py:174 +msgid "ip address" +msgstr "dirección ip" + +#: contrib/comments/models.py:176 +msgid "approved by staff" +msgstr "aprobado por el staff" + +#: contrib/comments/models.py:179 +msgid "free comment" +msgstr "comentario libre" + +#: contrib/comments/models.py:180 +msgid "free comments" +msgstr "comentarios libres" + +#: contrib/comments/models.py:239 +msgid "score" +msgstr "puntuación" + +#: contrib/comments/models.py:240 +msgid "score date" +msgstr "fecha de la puntuación" + +#: contrib/comments/models.py:243 +msgid "karma score" +msgstr "punto karma" + +#: contrib/comments/models.py:244 +msgid "karma scores" +msgstr "puntos karma" + +#: contrib/comments/models.py:248 +#, python-format +msgid "%(score)d rating by %(user)s" +msgstr "puntuado %(score)d por %(user)s" + +#: contrib/comments/models.py:264 +#, python-format msgid "" -"Jumps you from any page to the documentation for the view that generates " -"that page." +"This comment was flagged by %(user)s:\n" +"\n" +"%(text)s" msgstr "" -"Le lleva desde cualquier página a la documentación de la vista que la genera." +"Este comentario fue marcado por %(user)s:\n" +"\n" +"%(text)s" -#: contrib/admin/templates/admin_doc/bookmarklets.html:22 -msgid "Show object ID" -msgstr "Mostrar ID de objeto" +#: contrib/comments/models.py:271 +msgid "flag date" +msgstr "fecha de la marca" -#: contrib/admin/templates/admin_doc/bookmarklets.html:23 +#: contrib/comments/models.py:274 +msgid "user flag" +msgstr "marca de usuario" + +#: contrib/comments/models.py:275 +msgid "user flags" +msgstr "marcas de usuario" + +#: contrib/comments/models.py:279 +#, python-format +msgid "Flag by %r" +msgstr "Marca de %r" + +#: contrib/comments/models.py:284 +msgid "deletion date" +msgstr "fecha de eliminación" + +#: contrib/comments/models.py:286 +msgid "moderator deletion" +msgstr "eliminación de moderador" + +#: contrib/comments/models.py:287 +msgid "moderator deletions" +msgstr "eliminaciones de moderador" + +#: contrib/comments/models.py:291 +#, python-format +msgid "Moderator deletion by %r" +msgstr "Eliminación del moderador %r" + +#: contrib/comments/views/karma.py:20 +msgid "Anonymous users cannot vote" +msgstr "Los usuarios anónimos no pueden votar" + +#: contrib/comments/views/karma.py:24 +msgid "Invalid comment ID" +msgstr "ID de comentario no válido" + +#: contrib/comments/views/karma.py:26 +msgid "No voting for yourself" +msgstr "No puedes votarte tú mismo" + +#: contrib/comments/views/comments.py:28 +msgid "This rating is required because you've entered at least one other rating." +msgstr "Se precisa esta puntuación porque ha introducido al menos otra más." + +#: contrib/comments/views/comments.py:112 +#, python-format msgid "" -"Shows the content-type and unique ID for pages that represent a single " -"object." +"This comment was posted by a user who has posted fewer than %(count)s comment:\n" +"\n" +"%(text)s" +msgid_plural "" +"This comment was posted by a user who has posted fewer than %(count)s comments:\n" +"\n" +"%(text)s" +msgstr[0] "" +"Este comentario lo envió un usuario que ha enviado menos de %(count)s comentario:\n" +"\n" +"%(text)s" +msgstr[1] "" +"Este comentario lo envió un usuario que ha enviado menos de %(count)s comentarios:\n" +"\n" +"%(text)s" + +#: contrib/comments/views/comments.py:117 +#, python-format +msgid "" +"This comment was posted by a sketchy user:\n" +"\n" +"%(text)s" msgstr "" -"Muestra el tipo de contenido e ID unívoco de las páginas que representan un " -"único objeto." +"Este comentario ha sido colocado por un usuario poco preciso: \n" +"\n" +"%(text)s" -#: contrib/admin/templates/admin_doc/bookmarklets.html:25 -msgid "Edit this object (current window)" -msgstr "Editar este objeto (ventana actual)" +#: contrib/comments/views/comments.py:189 +#: contrib/comments/views/comments.py:281 +msgid "Only POSTs are allowed" +msgstr "Sólo se admite POST" -#: contrib/admin/templates/admin_doc/bookmarklets.html:26 -msgid "Jumps to the admin page for pages that represent a single object." -msgstr "" -"Le lleva a la página de administración de páginas que representan un único " -"objeto." +#: contrib/comments/views/comments.py:193 +#: contrib/comments/views/comments.py:285 +msgid "One or more of the required fields wasn't submitted" +msgstr "No se proporcionó uno o más de los siguientes campos requeridos" -#: contrib/admin/templates/admin_doc/bookmarklets.html:28 -msgid "Edit this object (new window)" -msgstr "Editar este objeto (nueva ventana)" +#: contrib/comments/views/comments.py:197 +#: contrib/comments/views/comments.py:287 +msgid "Somebody tampered with the comment form (security violation)" +msgstr "Alguien está jugando con el formulario de comentarios (violación de seguridad)" -#: contrib/admin/templates/admin_doc/bookmarklets.html:29 -msgid "As above, but opens the admin page in a new window." -msgstr "" -"Como antes, pero abre la página de administración en una nueva ventana." +#: contrib/comments/views/comments.py:207 +#: contrib/comments/views/comments.py:293 +msgid "The comment form had an invalid 'target' parameter -- the object ID was invalid" +msgstr "El formulario de comentarios tiene un parámetro 'target' no válido (el ID de objeto era inválido)" -#: contrib/localflavor/uk/forms.py:18 -msgid "Enter a postcode. A space is required between the two postcode parts." -msgstr "" -"Introduzca un código postal. Se necesita un espacio entre las dos partes del " -"código." +#: contrib/comments/views/comments.py:258 +#: contrib/comments/views/comments.py:322 +msgid "The comment form didn't provide either 'preview' or 'post'" +msgstr "El formulario de comentario no proporcionó 'previsualizar' ni 'enviar'" + +#: contrib/comments/templates/comments/form.html:8 +msgid "Forgotten your password?" +msgstr "¿Has olvidado tu contraseña?" + +#: contrib/comments/templates/comments/form.html:12 +msgid "Ratings" +msgstr "Calificaciones" + +#: contrib/comments/templates/comments/form.html:12 +#: contrib/comments/templates/comments/form.html:23 +msgid "Required" +msgstr "Requerido" + +#: contrib/comments/templates/comments/form.html:12 +#: contrib/comments/templates/comments/form.html:23 +msgid "Optional" +msgstr "Opcional" + +#: contrib/comments/templates/comments/form.html:23 +msgid "Post a photo" +msgstr "Postea una fotografía" + +#: contrib/comments/templates/comments/form.html:28 +#: contrib/comments/templates/comments/freeform.html:5 +msgid "Comment:" +msgstr "Comentario:" + +#: contrib/comments/templates/comments/form.html:35 +#: contrib/comments/templates/comments/freeform.html:10 +msgid "Preview comment" +msgstr "Previsualizar comentario" + +#: contrib/comments/templates/comments/freeform.html:4 +msgid "Your name:" +msgstr "Tu nombre:" + +#: contrib/localflavor/ar/forms.py:30 +#: contrib/localflavor/ar/forms.py:38 +msgid "Enter a postal code in the format NNNN or ANNNNAAA." +msgstr "Introduzca un código postal en el formato NNNN or ANNNNAAA." + +#: contrib/localflavor/ar/forms.py:61 +#: contrib/localflavor/br/forms.py:103 +msgid "This field requires only numbers." +msgstr "Este campo sólo acepta números." + +#: contrib/localflavor/ar/forms.py:64 +msgid "This field requires 7 or 8 digits." +msgstr "Este campo necesita 7 o 8 dígitos." + +#: contrib/localflavor/ar/forms.py:75 +msgid "Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format." +msgstr "Introduzca un CUIT válido en el formato XX-XXXXXXXX-X or XXXXXXXXXXXX." + +#: contrib/localflavor/ar/forms.py:88 +msgid "Invalid CUIT." +msgstr "CUIT inválido." + +#: contrib/localflavor/au/forms.py:18 +msgid "Enter a 4 digit post code." +msgstr "Introduzca un código postal de 4 dígitos." + +#: contrib/localflavor/br/forms.py:23 +msgid "Enter a zip code in the format XXXXX-XXX." +msgstr "Introduzca un código postal en el formato XXXX-XXXX." + +#: contrib/localflavor/br/forms.py:35 +msgid "Phone numbers must be in XX-XXXX-XXXX format." +msgstr "Los números de teléfono deben tener el formato XXX-XXX-XXXX." + +#: contrib/localflavor/br/forms.py:68 +msgid "Select a valid brazilian state. That state is not one of the available states." +msgstr "Seleccione un estado brasileño válido. Este estado no es uno de los estados disponibles." + +#: contrib/localflavor/br/forms.py:105 +msgid "This field requires at most 11 digits or 14 characters." +msgstr "Este campo necesita al menos 11 o 14 caracteres" + +#: contrib/localflavor/br/forms.py:115 +msgid "Invalid CPF number." +msgstr "Número CPF inválido." + +#: contrib/localflavor/br/forms.py:137 +msgid "This field requires at least 14 digits" +msgstr "Este campo necesita 14 dígitos como máximo" + +#: contrib/localflavor/br/forms.py:147 +msgid "Invalid CNPJ number." +msgstr "Número CNPJ inválido" + +#: contrib/localflavor/ch/forms.py:18 +#: contrib/localflavor/no/forms.py:14 +msgid "Enter a zip code in the format XXXX." +msgstr "Introduzca un código postal en el formato XXXX." + +#: contrib/localflavor/ch/forms.py:90 +msgid "Enter a valid Swiss identity or passport card number in X1234567<0 or 1234567890 format." +msgstr "Introduzca una identificación suiza válida o un número de pasaporte en el formato X1234567<0 or 1234567890." + +#: contrib/localflavor/ch/ch_states.py:5 +msgid "Aargau" +msgstr "Aargau" + +#: contrib/localflavor/ch/ch_states.py:6 +msgid "Appenzell Innerrhoden" +msgstr "Appenzell Innerrhoden" + +#: contrib/localflavor/ch/ch_states.py:7 +msgid "Appenzell Ausserrhoden" +msgstr "Appenzell Ausserrhoden" + +#: contrib/localflavor/ch/ch_states.py:8 +msgid "Basel-Stadt" +msgstr "Basel-Stadt" + +#: contrib/localflavor/ch/ch_states.py:9 +msgid "Basel-Land" +msgstr "Basel-Land" + +#: contrib/localflavor/ch/ch_states.py:10 +msgid "Berne" +msgstr "Berne" + +#: contrib/localflavor/ch/ch_states.py:11 +msgid "Fribourg" +msgstr "Fribourg" + +#: contrib/localflavor/ch/ch_states.py:12 +msgid "Geneva" +msgstr "Geneva" + +#: contrib/localflavor/ch/ch_states.py:13 +msgid "Glarus" +msgstr "Glarus" + +#: contrib/localflavor/ch/ch_states.py:14 +msgid "Graubuenden" +msgstr "Graubuenden" + +#: contrib/localflavor/ch/ch_states.py:15 +msgid "Jura" +msgstr "Jura" + +#: contrib/localflavor/ch/ch_states.py:16 +msgid "Lucerne" +msgstr "Lucerne" + +#: contrib/localflavor/ch/ch_states.py:17 +msgid "Neuchatel" +msgstr "Neuchatel" + +#: contrib/localflavor/ch/ch_states.py:18 +msgid "Nidwalden" +msgstr "Nidwalden" + +#: contrib/localflavor/ch/ch_states.py:19 +msgid "Obwalden" +msgstr "Obwalden" + +#: contrib/localflavor/ch/ch_states.py:20 +msgid "Schaffhausen" +msgstr "Schaffhausen" + +#: contrib/localflavor/ch/ch_states.py:21 +msgid "Schwyz" +msgstr "Schwyz" + +#: contrib/localflavor/ch/ch_states.py:22 +msgid "Solothurn" +msgstr "Solothurn" + +#: contrib/localflavor/ch/ch_states.py:23 +msgid "St. Gallen" +msgstr "St. Gallen" + +#: contrib/localflavor/ch/ch_states.py:24 +msgid "Thurgau" +msgstr "Thurgau" + +#: contrib/localflavor/ch/ch_states.py:25 +msgid "Ticino" +msgstr "Ticino" + +#: contrib/localflavor/ch/ch_states.py:26 +msgid "Uri" +msgstr "Uri" + +#: contrib/localflavor/ch/ch_states.py:27 +msgid "Valais" +msgstr "Valais" + +#: contrib/localflavor/ch/ch_states.py:28 +msgid "Vaud" +msgstr "Vaud" + +#: contrib/localflavor/ch/ch_states.py:29 +msgid "Zug" +msgstr "Zug" + +#: contrib/localflavor/ch/ch_states.py:30 +msgid "Zurich" +msgstr "Zurich" + +#: contrib/localflavor/cl/forms.py:32 +msgid "Enter valid a Chilean RUT. The format is XX.XXX.XXX-X." +msgstr "Introduzca un RUT chileno válido. El formato es XX.XXX.XXX-X." + +#: contrib/localflavor/cl/forms.py:37 +msgid "Enter valid a Chilean RUT" +msgstr "Introduzca un RUT chileno válido" -#: contrib/localflavor/fr/forms.py:17 contrib/localflavor/fi/forms.py:14 #: contrib/localflavor/de/forms.py:16 +#: contrib/localflavor/fi/forms.py:14 +#: contrib/localflavor/fr/forms.py:17 msgid "Enter a zip code in the format XXXXX." msgstr "Introduzca un código postal en el formato XXXXX." +#: contrib/localflavor/de/forms.py:60 +msgid "Enter a valid German identity card number in XXXXXXXXXXX-XXXXXXX-XXXXXXX-X format." +msgstr "Introduzca un número de tarjeta de identidad de Alemania válida en el formato XXXXXXXXXXX-XXXXXXX-XXXXXXX-X." + +#: contrib/localflavor/de/de_states.py:5 +msgid "Baden-Wuerttemberg" +msgstr "Baden-Wuerttemberg" + +#: contrib/localflavor/de/de_states.py:6 +msgid "Bavaria" +msgstr "Bavaria" + +#: contrib/localflavor/de/de_states.py:7 +msgid "Berlin" +msgstr "Berlín" + +#: contrib/localflavor/de/de_states.py:8 +msgid "Brandenburg" +msgstr "Brandenburg" + +#: contrib/localflavor/de/de_states.py:9 +msgid "Bremen" +msgstr "Bremen" + +#: contrib/localflavor/de/de_states.py:10 +msgid "Hamburg" +msgstr "Hamburg" + +#: contrib/localflavor/de/de_states.py:11 +msgid "Hessen" +msgstr "Hessen" + +#: contrib/localflavor/de/de_states.py:12 +msgid "Mecklenburg-Western Pomerania" +msgstr "Mecklenburg-Western Pomerania" + +#: contrib/localflavor/de/de_states.py:13 +msgid "Lower Saxony" +msgstr "Lower Saxony" + +#: contrib/localflavor/de/de_states.py:14 +msgid "North Rhine-Westphalia" +msgstr "North Rhine-Westphalia" + +#: contrib/localflavor/de/de_states.py:15 +msgid "Rhineland-Palatinate" +msgstr "Rhineland-Palatinate" + +#: contrib/localflavor/de/de_states.py:16 +msgid "Saarland" +msgstr "Saarland" + +#: contrib/localflavor/de/de_states.py:17 +msgid "Saxony" +msgstr "Saxony" + +#: contrib/localflavor/de/de_states.py:18 +msgid "Saxony-Anhalt" +msgstr "Saxony-Anhalt" + +#: contrib/localflavor/de/de_states.py:19 +msgid "Schleswig-Holstein" +msgstr "Schleswig-Holstein" + +#: contrib/localflavor/de/de_states.py:20 +msgid "Thuringia" +msgstr "Thuringia" + +#: contrib/localflavor/fi/forms.py:40 +#: contrib/localflavor/fi/forms.py:45 +msgid "Enter a valid Finnish social security number." +msgstr "Introduzca un número de seguro social finlandés válido." + +#: contrib/localflavor/it/forms.py:16 +msgid "Enter a valid zip code." +msgstr "Introduzca un código postal válido." + +#: contrib/localflavor/it/forms.py:41 +msgid "Enter a valid Social Security number." +msgstr "Introduzca un número de Seguro Social válido." + +#: contrib/localflavor/it/forms.py:68 +msgid "Enter a valid VAT number." +msgstr "Introduzca un número VAT válido." + +#: contrib/localflavor/jp/forms.py:21 +msgid "Enter a postal code in the format XXXXXXX or XXX-XXXX." +msgstr "Introduzca un código postal en el formato XXXXX o XXXX-XXXX." + #: contrib/localflavor/jp/jp_prefectures.py:4 msgid "Hokkaido" msgstr "Hokkaido" @@ -2454,309 +2470,153 @@ msgstr "Kagoshima" msgid "Okinawa" msgstr "Okinawa" -#: contrib/localflavor/jp/forms.py:21 -msgid "Enter a postal code in the format XXXXXXX or XXX-XXXX." -msgstr "Introduzca un código postal en el formato XXXXX o XXXX-XXXX." +#: contrib/localflavor/nl/forms.py:25 +msgid "Enter a valid postal code" +msgstr "Introduzca un código postal válido" -#: contrib/localflavor/br/forms.py:18 -msgid "Enter a zip code in the format XXXXX-XXX." -msgstr "Introduzca un código postal en el formato XXXX-XXXX." +#: contrib/localflavor/nl/forms.py:53 +msgid "Enter a valid phone number" +msgstr "Introduzca un número de teléfono válido" -#: contrib/localflavor/br/forms.py:30 -msgid "Phone numbers must be in XX-XXXX-XXXX format." -msgstr "Los números de teléfono deben tener el formato XXX-XXX-XXXX." +#: contrib/localflavor/nl/forms.py:76 +msgid "Enter a valid SoFi number" +msgstr "Introduzca un número SoFi válido" -#: contrib/localflavor/br/forms.py:72 -msgid "This field requires only numbers." -msgstr "Este campo sólo acepta números." +#: contrib/localflavor/nl/nl_provinces.py:4 +msgid "Drente" +msgstr "Drente" -#: contrib/localflavor/br/forms.py:74 -msgid "This field requires at most 11 digits or 14 characters." -msgstr "Este campo necesita al menos 11 o 14 caracteres" +#: contrib/localflavor/nl/nl_provinces.py:5 +msgid "Flevoland" +msgstr "Flevoland" -#: contrib/localflavor/br/forms.py:84 -msgid "Invalid CPF number." -msgstr "Número CPF inválido." +#: contrib/localflavor/nl/nl_provinces.py:6 +msgid "Friesland" +msgstr "Friesland" -#: contrib/localflavor/br/forms.py:106 -msgid "This field requires at least 14 digits" -msgstr "Este campo necesita 14 dígitos como máximo" +#: contrib/localflavor/nl/nl_provinces.py:7 +msgid "Gelderland" +msgstr "Gelderland" -#: contrib/localflavor/br/forms.py:116 -msgid "Invalid CNPJ number." -msgstr "Número CNPJ inválido" +#: contrib/localflavor/nl/nl_provinces.py:8 +msgid "Groningen" +msgstr "Groningen" -#: contrib/localflavor/it/forms.py:16 -msgid "Enter a valid zip code." -msgstr "Introduzca un código postal válido." +#: contrib/localflavor/nl/nl_provinces.py:9 +msgid "Limburg" +msgstr "Limburg" -#: contrib/localflavor/it/forms.py:41 -msgid "Enter a valid Social Security number." -msgstr "Introduzca un número de Seguro Social válido." +#: contrib/localflavor/nl/nl_provinces.py:10 +msgid "Noord-Brabant" +msgstr "Noord-Brabant" -#: contrib/localflavor/it/forms.py:68 -msgid "Enter a valid VAT number." -msgstr "Introduzca un número VAT válido." - -#: contrib/localflavor/no/forms.py:14 contrib/localflavor/ch/forms.py:18 -msgid "Enter a zip code in the format XXXX." -msgstr "Introduzca un código postal en el formato XXXX." - -#: contrib/localflavor/no/forms.py:35 -msgid "Enter a valid Norwegian social security number." -msgstr "Introduzca un número de seguro social de Noruega válido." - -#: contrib/localflavor/fi/forms.py:40 contrib/localflavor/fi/forms.py:45 -msgid "Enter a valid Finnish social security number." -msgstr "Introduzca un número de seguro social finlandés válido." - -#: contrib/localflavor/de/de_states.py:5 -msgid "Baden-Wuerttemberg" -msgstr "Baden-Wuerttemberg" - -#: contrib/localflavor/de/de_states.py:6 -msgid "Bavaria" -msgstr "Bavaria" - -#: contrib/localflavor/de/de_states.py:7 -msgid "Berlin" -msgstr "Berlín" - -#: contrib/localflavor/de/de_states.py:8 -msgid "Brandenburg" -msgstr "Brandenburg" - -#: contrib/localflavor/de/de_states.py:9 -msgid "Bremen" -msgstr "Bremen" - -#: contrib/localflavor/de/de_states.py:10 -msgid "Hamburg" -msgstr "Hamburg" - -#: contrib/localflavor/de/de_states.py:11 -msgid "Hessen" -msgstr "Hessen" - -#: contrib/localflavor/de/de_states.py:12 -msgid "Mecklenburg-Western Pomerania" -msgstr "Mecklenburg-Western Pomerania" - -#: contrib/localflavor/de/de_states.py:13 -msgid "Lower Saxony" -msgstr "Lower Saxony" - -#: contrib/localflavor/de/de_states.py:14 -msgid "North Rhine-Westphalia" -msgstr "North Rhine-Westphalia" - -#: contrib/localflavor/de/de_states.py:15 -msgid "Rhineland-Palatinate" -msgstr "Rhineland-Palatinate" - -#: contrib/localflavor/de/de_states.py:16 -msgid "Saarland" -msgstr "Saarland" - -#: contrib/localflavor/de/de_states.py:17 -msgid "Saxony" -msgstr "Saxony" - -#: contrib/localflavor/de/de_states.py:18 -msgid "Saxony-Anhalt" -msgstr "Saxony-Anhalt" - -#: contrib/localflavor/de/de_states.py:19 -msgid "Schleswig-Holstein" -msgstr "Schleswig-Holstein" - -#: contrib/localflavor/de/de_states.py:20 -msgid "Thuringia" -msgstr "Thuringia" - -#: contrib/localflavor/de/forms.py:60 -msgid "" -"Enter a valid German identity card number in XXXXXXXXXXX-XXXXXXX-XXXXXXX-X " -"format." -msgstr "" -"Introduzca un número de tarjeta de identidad de Alemania válida en el " -"formato XXXXXXXXXXX-XXXXXXX-XXXXXXX-X." - -#: contrib/localflavor/au/forms.py:18 -msgid "Enter a 4 digit post code." -msgstr "Introduzca un código postal de 4 dígitos." - -#: contrib/localflavor/us/forms.py:18 -msgid "Enter a zip code in the format XXXXX or XXXXX-XXXX." -msgstr "Introduzca un código postal en el formato XXXXX o XXXX-XXXX." - -#: contrib/localflavor/us/forms.py:51 -msgid "Enter a valid U.S. Social Security number in XXX-XX-XXXX format." -msgstr "" -"Introduzca un Número Seguro Social de EEUU válido en el formato XXX-XX-XXXX" - -#: contrib/localflavor/is_/forms.py:17 -msgid "" -"Enter a valid Icelandic identification number. The format is XXXXXX-XXXX." -msgstr "" -"Introduzca un número de identificación de Islandia válido. El formato es " -"XXXXXX-XXXX." - -#: contrib/localflavor/is_/forms.py:31 -msgid "The Icelandic identification number is not valid." -msgstr "El número de identificación de Islandia no es válido." +#: contrib/localflavor/nl/nl_provinces.py:11 +msgid "Noord-Holland" +msgstr "Noord-Holland" -#: contrib/localflavor/cl/forms.py:32 -msgid "Enter valid a Chilean RUT. The format is XX.XXX.XXX-X." -msgstr "Introduzca un RUT chileno válido. El formato es XX.XXX.XXX-X." +#: contrib/localflavor/nl/nl_provinces.py:12 +msgid "Overijssel" +msgstr "Overijssel" -#: contrib/localflavor/cl/forms.py:37 -msgid "Enter valid a Chilean RUT" -msgstr "Introduzca un RUT chileno válido" +#: contrib/localflavor/nl/nl_provinces.py:13 +msgid "Utrecht" +msgstr "Utrecht" -#: contrib/localflavor/ch/ch_states.py:5 -msgid "Aargau" -msgstr "Aargau" +#: contrib/localflavor/nl/nl_provinces.py:14 +msgid "Zeeland" +msgstr "Zeeland" -#: contrib/localflavor/ch/ch_states.py:6 -msgid "Appenzell Innerrhoden" -msgstr "Appenzell Innerrhoden" +#: contrib/localflavor/nl/nl_provinces.py:15 +msgid "Zuid-Holland" +msgstr "Zuid-Holland" -#: contrib/localflavor/ch/ch_states.py:7 -msgid "Appenzell Ausserrhoden" -msgstr "Appenzell Ausserrhoden" +#: contrib/localflavor/no/forms.py:35 +msgid "Enter a valid Norwegian social security number." +msgstr "Introduzca un número de seguro social de Noruega válido." -#: contrib/localflavor/ch/ch_states.py:8 -msgid "Basel-Stadt" -msgstr "Basel-Stadt" +#: contrib/localflavor/pl/forms.py:53 +msgid "National Identification Number consists of 11 digits." +msgstr "Número de Identificación Nacional consiste en 11 dígitos" -#: contrib/localflavor/ch/ch_states.py:9 -msgid "Basel-Land" -msgstr "Basel-Land" +#: contrib/localflavor/pl/forms.py:59 +msgid "Wrong checksum for the National Identification Number." +msgstr "El Número de Identificación Nacional es incorrecto." -#: contrib/localflavor/ch/ch_states.py:10 -msgid "Berne" -msgstr "Berne" +#: contrib/localflavor/pl/forms.py:71 +msgid "Enter a tax number field (NIP) in the format XXX-XXX-XX-XX or XX-XX-XXX-XXX." +msgstr "Introduzca un número de impuesto (NIP) en el formato XXX-XXX-XX-XX or XX-XX-XXX-XXX." -#: contrib/localflavor/ch/ch_states.py:11 -msgid "Fribourg" -msgstr "Fribourg" +#: contrib/localflavor/pl/forms.py:82 +msgid "Enter a postal code in the format XX-XXX." +msgstr "Introduzca un código postal en el formato XX-XXX." -#: contrib/localflavor/ch/ch_states.py:12 -msgid "Geneva" -msgstr "Geneva" +#: contrib/localflavor/pl/pl_voivodeships.py:8 +msgid "Lower Silesia" +msgstr "Lower Silesia" -#: contrib/localflavor/ch/ch_states.py:13 -msgid "Glarus" -msgstr "Glarus" +#: contrib/localflavor/pl/pl_voivodeships.py:9 +msgid "Kuyavia-Pomerania" +msgstr "Kuyavia-Pomerania" -#: contrib/localflavor/ch/ch_states.py:14 -msgid "Graubuenden" -msgstr "Graubuenden" +#: contrib/localflavor/pl/pl_voivodeships.py:10 +msgid "Lublin" +msgstr "Lublin" -#: contrib/localflavor/ch/ch_states.py:15 -msgid "Jura" -msgstr "Jura" +#: contrib/localflavor/pl/pl_voivodeships.py:11 +msgid "Lubusz" +msgstr "Lubusz" -#: contrib/localflavor/ch/ch_states.py:16 -msgid "Lucerne" -msgstr "Lucerne" +#: contrib/localflavor/pl/pl_voivodeships.py:12 +msgid "Lodz" +msgstr "Lodz" -#: contrib/localflavor/ch/ch_states.py:17 -msgid "Neuchatel" -msgstr "Neuchatel" - -#: contrib/localflavor/ch/ch_states.py:18 -msgid "Nidwalden" -msgstr "Nidwalden" - -#: contrib/localflavor/ch/ch_states.py:19 -msgid "Obwalden" -msgstr "Obwalden" - -#: contrib/localflavor/ch/ch_states.py:20 -msgid "Schaffhausen" -msgstr "Schaffhausen" - -#: contrib/localflavor/ch/ch_states.py:21 -msgid "Schwyz" -msgstr "Schwyz" +#: contrib/localflavor/pl/pl_voivodeships.py:13 +msgid "Lesser Poland" +msgstr "Lesser Poland" -#: contrib/localflavor/ch/ch_states.py:22 -msgid "Solothurn" -msgstr "Solothurn" +#: contrib/localflavor/pl/pl_voivodeships.py:14 +msgid "Masovia" +msgstr "Masovia" -#: contrib/localflavor/ch/ch_states.py:23 -msgid "St. Gallen" -msgstr "St. Gallen" +#: contrib/localflavor/pl/pl_voivodeships.py:15 +msgid "Opole" +msgstr "Opole" -#: contrib/localflavor/ch/ch_states.py:24 -msgid "Thurgau" -msgstr "Thurgau" +#: contrib/localflavor/pl/pl_voivodeships.py:16 +msgid "Subcarpatia" +msgstr "Subcarpatia" -#: contrib/localflavor/ch/ch_states.py:25 -msgid "Ticino" -msgstr "Ticino" +#: contrib/localflavor/pl/pl_voivodeships.py:17 +msgid "Podlasie" +msgstr "Podlasie" -#: contrib/localflavor/ch/ch_states.py:26 -msgid "Uri" -msgstr "Uri" +#: contrib/localflavor/pl/pl_voivodeships.py:18 +msgid "Pomerania" +msgstr "Pomerania" -#: contrib/localflavor/ch/ch_states.py:27 -msgid "Valais" -msgstr "Valais" +#: contrib/localflavor/pl/pl_voivodeships.py:19 +msgid "Silesia" +msgstr "Silesia" -#: contrib/localflavor/ch/ch_states.py:28 -msgid "Vaud" -msgstr "Vaud" +#: contrib/localflavor/pl/pl_voivodeships.py:20 +msgid "Swietokrzyskie" +msgstr "Swietokrzyskie" -#: contrib/localflavor/ch/ch_states.py:29 -msgid "Zug" -msgstr "Zug" +#: contrib/localflavor/pl/pl_voivodeships.py:21 +msgid "Warmia-Masuria" +msgstr "Warmia-Masuria" -#: contrib/localflavor/ch/ch_states.py:30 -msgid "Zurich" -msgstr "Zurich" +#: contrib/localflavor/pl/pl_voivodeships.py:22 +msgid "Greater Poland" +msgstr "Greater Poland" -#: contrib/localflavor/ch/forms.py:90 -msgid "" -"Enter a valid Swiss identity or passport card number in X1234567<0 or " -"1234567890 format." -msgstr "" -"Introduzca una identificación suiza válida o un número de pasaporte en el " -"formato X1234567<0 or 1234567890." +#: contrib/localflavor/pl/pl_voivodeships.py:23 +msgid "West Pomerania" +msgstr "West Pomerania" -#: contrib/localflavor/sk/sk_regions.py:8 -msgid "Banska Bystrica region" -msgstr "Región de Banska Bystrica" - -#: contrib/localflavor/sk/sk_regions.py:9 -msgid "Bratislava region" -msgstr "Región de Bratislava" - -#: contrib/localflavor/sk/sk_regions.py:10 -msgid "Kosice region" -msgstr "Región de Kosice" - -#: contrib/localflavor/sk/sk_regions.py:11 -msgid "Nitra region" -msgstr "Región de Nitra" - -#: contrib/localflavor/sk/sk_regions.py:12 -msgid "Presov region" -msgstr "Región de Presov" - -#: contrib/localflavor/sk/sk_regions.py:13 -msgid "Trencin region" -msgstr "Región de Trencin" - -#: contrib/localflavor/sk/sk_regions.py:14 -msgid "Trnava region" -msgstr "Región de Trnava" - -#: contrib/localflavor/sk/sk_regions.py:15 -msgid "Zilina region" -msgstr "Región de Zilina" +#: contrib/localflavor/sk/forms.py:32 +msgid "Enter a postal code in the format XXXXX or XXX XX." +msgstr "Introduzca un código postal en el formato XXXXX o XXX XX." #: contrib/localflavor/sk/sk_districts.py:8 msgid "Banska Bystrica" @@ -3074,39 +2934,93 @@ msgstr "Ziar nad Hronom" msgid "Zilina" msgstr "Zilina" -#: contrib/localflavor/sk/forms.py:32 -msgid "Enter a postal code in the format XXXXX or XXX XX." -msgstr "Introduzca un código postal en el formato XXXXX o XXX XX." +#: contrib/localflavor/sk/sk_regions.py:8 +msgid "Banska Bystrica region" +msgstr "Región de Banska Bystrica" + +#: contrib/localflavor/sk/sk_regions.py:9 +msgid "Bratislava region" +msgstr "Región de Bratislava" + +#: contrib/localflavor/sk/sk_regions.py:10 +msgid "Kosice region" +msgstr "Región de Kosice" + +#: contrib/localflavor/sk/sk_regions.py:11 +msgid "Nitra region" +msgstr "Región de Nitra" + +#: contrib/localflavor/sk/sk_regions.py:12 +msgid "Presov region" +msgstr "Región de Presov" + +#: contrib/localflavor/sk/sk_regions.py:13 +msgid "Trencin region" +msgstr "Región de Trencin" + +#: contrib/localflavor/sk/sk_regions.py:14 +msgid "Trnava region" +msgstr "Región de Trnava" + +#: contrib/localflavor/sk/sk_regions.py:15 +msgid "Zilina region" +msgstr "Región de Zilina" + +#: contrib/localflavor/uk/forms.py:18 +msgid "Enter a postcode. A space is required between the two postcode parts." +msgstr "Introduzca un código postal. Se necesita un espacio entre las dos partes del código." + +#: contrib/localflavor/us/forms.py:18 +msgid "Enter a zip code in the format XXXXX or XXXXX-XXXX." +msgstr "Introduzca un código postal en el formato XXXXX o XXXX-XXXX." + +#: contrib/localflavor/us/forms.py:51 +msgid "Enter a valid U.S. Social Security number in XXX-XX-XXXX format." +msgstr "Introduzca un Número Seguro Social de EEUU válido en el formato XXX-XX-XXXX" #: contrib/localflavor/in_/forms.py:16 msgid "Enter a zip code in the format XXXXXXX." msgstr "Introduzca un código postal en el formato XXXXXXX." -#: template/defaultfilters.py:485 -msgid "yes,no,maybe" -msgstr "sí,no,tal vez" +#: contrib/localflavor/is_/forms.py:17 +msgid "Enter a valid Icelandic identification number. The format is XXXXXX-XXXX." +msgstr "Introduzca un número de identificación de Islandia válido. El formato es XXXXXX-XXXX." -#: template/defaultfilters.py:514 -#, python-format -msgid "%(size)d byte" -msgid_plural "%(size)d bytes" -msgstr[0] "%(size)d byte" -msgstr[1] "%(size)d bytes" +#: contrib/localflavor/is_/forms.py:31 +msgid "The Icelandic identification number is not valid." +msgstr "El número de identificación de Islandia no es válido." -#: template/defaultfilters.py:516 -#, python-format -msgid "%.1f KB" -msgstr "%.1f KB" +#: contrib/sessions/models.py:68 +msgid "session key" +msgstr "clave de sesión" -#: template/defaultfilters.py:518 -#, python-format -msgid "%.1f MB" -msgstr "%.1f MB" +#: contrib/sessions/models.py:69 +msgid "session data" +msgstr "datos de sesión" -#: template/defaultfilters.py:519 -#, python-format -msgid "%.1f GB" -msgstr "%.1f GB" +#: contrib/sessions/models.py:70 +msgid "expire date" +msgstr "fecha de caducidad" + +#: contrib/sessions/models.py:74 +msgid "session" +msgstr "sesión" + +#: contrib/sessions/models.py:75 +msgid "sessions" +msgstr "sesiones" + +#: contrib/contenttypes/models.py:37 +msgid "python model class name" +msgstr "nombre de módulo python" + +#: contrib/contenttypes/models.py:40 +msgid "content type" +msgstr "tipo de contenido" + +#: contrib/contenttypes/models.py:41 +msgid "content types" +msgstr "tipos de contenido" #: oldforms/__init__.py:408 #, python-format @@ -3119,11 +3033,18 @@ msgstr[1] "Asegúrese de que su texto tiene menos de %s caracteres." msgid "Line breaks are not allowed here." msgstr "No se permiten saltos de línea." -#: oldforms/__init__.py:511 oldforms/__init__.py:585 oldforms/__init__.py:624 +#: oldforms/__init__.py:511 +#: oldforms/__init__.py:585 +#: oldforms/__init__.py:624 #, python-format msgid "Select a valid choice; '%(data)s' is not in %(choices)s." msgstr "Escoja una opción válida; '%(data)s' no está en %(choices)s." +#: oldforms/__init__.py:688 +#: newforms/fields.py:381 +msgid "The submitted file is empty." +msgstr "El fichero enviado está vacío." + #: oldforms/__init__.py:744 msgid "Enter a whole number between -32,768 and 32,767." msgstr "Introduzca un número entero entre -32,768 y 32,767." @@ -3136,299 +3057,415 @@ msgstr "Introduzca un número positivo." msgid "Enter a whole number between 0 and 32,767." msgstr "Introduzca un número entero entre 0 y 32,767." -#: core/validators.py:71 -msgid "This value must contain only letters, numbers and underscores." -msgstr "Este valor debe contener sólo letras, números y guiones bajos." +#: views/generic/create_update.py:43 +#, python-format +msgid "The %(verbose_name)s was created successfully." +msgstr "El %(verbose_name)s se ha creado correctamente." -#: core/validators.py:75 -msgid "" -"This value must contain only letters, numbers, underscores, dashes or " -"slashes." -msgstr "" -"Este valor debe contener letras, números, guiones bajos o barras solamente." +#: views/generic/create_update.py:117 +#, python-format +msgid "The %(verbose_name)s was updated successfully." +msgstr "Se actualizó con éxito el %(verbose_name)s." -#: core/validators.py:79 -msgid "This value must contain only letters, numbers, underscores or hyphens." -msgstr "Este valor debe contener sólo letras, números, guiones bajos o medios." +#: views/generic/create_update.py:184 +#, python-format +msgid "The %(verbose_name)s was deleted." +msgstr "El %(verbose_name)s ha sido eliminado." -#: core/validators.py:83 -msgid "Uppercase letters are not allowed here." -msgstr "No se admiten letras mayúsculas." +#: utils/dates.py:6 +msgid "Monday" +msgstr "Lunes" -#: core/validators.py:87 -msgid "Lowercase letters are not allowed here." -msgstr "No se admiten letras minúsculas." +#: utils/dates.py:6 +msgid "Tuesday" +msgstr "Martes" -#: core/validators.py:94 -msgid "Enter only digits separated by commas." -msgstr "Introduzca sólo dígitos separados por comas." +#: utils/dates.py:6 +msgid "Wednesday" +msgstr "Miércoles" -#: core/validators.py:106 -msgid "Enter valid e-mail addresses separated by commas." -msgstr "Introduzca direcciones de correo válidas separadas por comas." +#: utils/dates.py:6 +msgid "Thursday" +msgstr "Jueves" -#: core/validators.py:110 -msgid "Please enter a valid IP address." -msgstr "Por favor introduzca una dirección IP válida." +#: utils/dates.py:6 +msgid "Friday" +msgstr "Viernes" -#: core/validators.py:114 -msgid "Empty values are not allowed here." -msgstr "No se admiten valores vacíos." +#: utils/dates.py:7 +msgid "Saturday" +msgstr "Sábado" -#: core/validators.py:118 -msgid "Non-numeric characters aren't allowed here." -msgstr "No se admiten caracteres no numéricos." +#: utils/dates.py:7 +msgid "Sunday" +msgstr "Domingo" -#: core/validators.py:122 -msgid "This value can't be comprised solely of digits." -msgstr "Este valor no puede comprender sólo dígitos." +#: utils/dates.py:10 +msgid "Mon" +msgstr "Lun" -#: core/validators.py:131 -msgid "Only alphabetical characters are allowed here." -msgstr "Sólo se admiten caracteres alfabéticos." +#: utils/dates.py:10 +msgid "Tue" +msgstr "Mar" -#: core/validators.py:146 -msgid "Year must be 1900 or later." -msgstr "El año debe ser 1900 o posterior." +#: utils/dates.py:10 +msgid "Wed" +msgstr "Mie" -#: core/validators.py:150 -#, python-format -msgid "Invalid date: %s" -msgstr "Fecha no válida: %s" +#: utils/dates.py:10 +msgid "Thu" +msgstr "Jue" -#: core/validators.py:160 -msgid "Enter a valid time in HH:MM format." -msgstr "Introduzca una hora válida en formato HH:MM." +#: utils/dates.py:10 +msgid "Fri" +msgstr "Vie" -#: core/validators.py:192 -#, python-format -msgid "The URL %s does not point to a valid image." -msgstr "La URL %s no apunta a una imagen válida." +#: utils/dates.py:11 +msgid "Sat" +msgstr "Sab" -#: core/validators.py:196 -#, python-format -msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid." -msgstr "" -"Los números de teléfono deben guardar el formato XXX-XXX-XXXX. \"%s\" no es " -"válido." +#: utils/dates.py:11 +msgid "Sun" +msgstr "Dom" -#: core/validators.py:204 -#, python-format -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." +#: utils/dates.py:18 +msgid "January" +msgstr "Enero" -#: core/validators.py:208 -msgid "A valid URL is required." -msgstr "Se precisa una URL válida." +#: utils/dates.py:18 +msgid "February" +msgstr "Febrero" -#: core/validators.py:222 -#, python-format -msgid "" -"Valid HTML is required. Specific errors are:\n" -"%s" -msgstr "" -"Se precisa HTML válido. Los errores específicos son:\n" -"%s" +#: utils/dates.py:18 +#: utils/dates.py:31 +msgid "March" +msgstr "Marzo" -#: core/validators.py:229 -#, python-format -msgid "Badly formed XML: %s" -msgstr "XML mal formado: %s" +#: utils/dates.py:18 +#: utils/dates.py:31 +msgid "April" +msgstr "Abril" -#: core/validators.py:246 -#, python-format -msgid "Invalid URL: %s" -msgstr "URL no válida: %s" +#: utils/dates.py:18 +#: utils/dates.py:31 +msgid "May" +msgstr "Mayo" -#: core/validators.py:251 core/validators.py:253 -#, python-format -msgid "The URL %s is a broken link." -msgstr "La URL %s es un enlace roto." +#: utils/dates.py:18 +#: utils/dates.py:31 +msgid "June" +msgstr "Junio" -#: core/validators.py:259 -msgid "Enter a valid U.S. state abbreviation." -msgstr "Introduzca una abreviatura válida de estado de los EEUU." +#: utils/dates.py:19 +#: utils/dates.py:31 +msgid "July" +msgstr "Julio" -#: core/validators.py:273 -#, python-format -msgid "Watch your mouth! The word %s is not allowed here." -msgid_plural "Watch your mouth! The words %s are not allowed here." -msgstr[0] "¡Cuida tu vocabulario! Aquí no admitimos la palabra %s." -msgstr[1] "¡Cuida tu vocabulario! Aquí no admitimos las palabras %s." +#: utils/dates.py:19 +msgid "August" +msgstr "Agosto" -#: core/validators.py:280 -#, python-format -msgid "This field must match the '%s' field." -msgstr "Este campo debe concordar con el campo '%s'." +#: utils/dates.py:19 +msgid "September" +msgstr "Septiembre" -#: core/validators.py:299 -msgid "Please enter something for at least one field." -msgstr "Por favor, introduzca algo en al menos un campo." +#: utils/dates.py:19 +msgid "October" +msgstr "Octubre" -#: core/validators.py:308 core/validators.py:319 -msgid "Please enter both fields or leave them both empty." -msgstr "Por favor, rellene ambos campos o deje ambos vacíos." +#: utils/dates.py:19 +msgid "November" +msgstr "Noviembre" -#: core/validators.py:327 -#, python-format -msgid "This field must be given if %(field)s is %(value)s" -msgstr "Se debe proporcionar este campo si %(field)s es %(value)s" +#: utils/dates.py:20 +msgid "December" +msgstr "Diciembre" -#: core/validators.py:340 -#, python-format -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" +#: utils/dates.py:23 +msgid "jan" +msgstr "ene" -#: core/validators.py:359 -msgid "Duplicate values are not allowed." -msgstr "No se admiten valores duplicados." +#: utils/dates.py:23 +msgid "feb" +msgstr "feb" -#: core/validators.py:374 -#, python-format -msgid "This value must be between %(lower)s and %(upper)s." -msgstr "Este valor debe estar entre %(lower)s y %(upper)s." +#: utils/dates.py:23 +msgid "mar" +msgstr "mar" -#: core/validators.py:376 -#, python-format -msgid "This value must be at least %s." -msgstr "Este valor debe ser como mínimo %s." +#: utils/dates.py:23 +msgid "apr" +msgstr "abr" -#: core/validators.py:378 -#, python-format -msgid "This value must be no more than %s." -msgstr "Este valor no debe ser mayor que %s." +#: utils/dates.py:23 +msgid "may" +msgstr "may" -#: core/validators.py:414 -#, python-format -msgid "This value must be a power of %s." -msgstr "Este valor debe ser una potencia de %s." +#: utils/dates.py:23 +msgid "jun" +msgstr "jun" -#: core/validators.py:424 -msgid "Please enter a valid decimal number." -msgstr "Por favor, introduzca un número decimal válido." +#: utils/dates.py:24 +msgid "jul" +msgstr "jul" -#: core/validators.py:431 -#, python-format -msgid "Please enter a valid decimal number with at most %s total digit." -msgid_plural "" -"Please enter a valid decimal number with at most %s total digits." -msgstr[0] "" -"Por favor, introduzca un número decimal válido con a lo más %s dígito en " -"total." -msgstr[1] "" -"Por favor, introduzca un número decimal válido con a lo más %s dígitos en " -"total." +#: utils/dates.py:24 +msgid "aug" +msgstr "ago" + +#: utils/dates.py:24 +msgid "sep" +msgstr "sep" + +#: utils/dates.py:24 +msgid "oct" +msgstr "oct" + +#: utils/dates.py:24 +msgid "nov" +msgstr "nov" + +#: utils/dates.py:24 +msgid "dec" +msgstr "dic" + +#: utils/dates.py:31 +msgid "Jan." +msgstr "Ene." + +#: utils/dates.py:31 +msgid "Feb." +msgstr "Feb." + +#: utils/dates.py:32 +msgid "Aug." +msgstr "Ago." + +#: utils/dates.py:32 +msgid "Sept." +msgstr "Sept." + +#: utils/dates.py:32 +msgid "Oct." +msgstr "Oct." + +#: utils/dates.py:32 +msgid "Nov." +msgstr "Nov." + +#: utils/dates.py:32 +msgid "Dec." +msgstr "Dic." + +#: utils/text.py:127 +msgid "or" +msgstr "o" + +#: utils/timesince.py:12 +msgid "year" +msgid_plural "years" +msgstr[0] "año" +msgstr[1] "años" + +#: utils/timesince.py:13 +msgid "month" +msgid_plural "months" +msgstr[0] "mes" +msgstr[1] "meses" + +#: utils/timesince.py:14 +msgid "week" +msgid_plural "weeks" +msgstr[0] "semana" +msgstr[1] "semanas" + +#: utils/timesince.py:15 +msgid "day" +msgid_plural "days" +msgstr[0] "día" +msgstr[1] "días" + +#: utils/timesince.py:16 +msgid "hour" +msgid_plural "hours" +msgstr[0] "hora" +msgstr[1] "horas" + +#: utils/timesince.py:17 +msgid "minute" +msgid_plural "minutes" +msgstr[0] "minuto" +msgstr[1] "minutos" -#: core/validators.py:434 +#: utils/timesince.py:39 #, python-format -msgid "" -"Please enter a valid decimal number with a whole part of at most %s digit." -msgid_plural "" -"Please enter a valid decimal number with a whole part of at most %s digits." -msgstr[0] "" -"Por favor, introduzca un número decimal válido con a lo más %s dígito en su " -"parte entera." -msgstr[1] "" -"Por favor, introduzca un número decimal válido con a lo más %s dígitos en su " -"parte entera." +msgid "%(number)d %(type)s" +msgstr "%(number)d %(type)s" -#: core/validators.py:437 +#: utils/timesince.py:45 #, python-format -msgid "Please enter a valid decimal number with at most %s decimal place." -msgid_plural "" -"Please enter a valid decimal number with at most %s decimal places." -msgstr[0] "" -"Por favor, introduzca un número decimal válido con a lo más %s dígito " -"decimal." -msgstr[1] "" -"Por favor, introduzca un número decimal válido con a lo más %s dígitos " -"decimales." +msgid ", %(number)d %(type)s" +msgstr ", %(number)d %(type)s" -#: core/validators.py:445 -msgid "Please enter a valid floating point number." -msgstr "Por favor, introduzca un número decimal válido." +#: utils/dateformat.py:41 +msgid "p.m." +msgstr "p.m" + +#: utils/dateformat.py:42 +msgid "a.m." +msgstr "a.m" + +#: utils/dateformat.py:47 +msgid "PM" +msgstr "PM" + +#: utils/dateformat.py:48 +msgid "AM" +msgstr "AM" + +#: utils/dateformat.py:97 +msgid "midnight" +msgstr "media noche" + +#: utils/dateformat.py:99 +msgid "noon" +msgstr "medio día" + +#: utils/translation/trans_real.py:391 +msgid "DATE_FORMAT" +msgstr "j N Y" + +#: utils/translation/trans_real.py:392 +msgid "DATETIME_FORMAT" +msgstr "j N Y P" -#: core/validators.py:454 +#: utils/translation/trans_real.py:393 +msgid "TIME_FORMAT" +msgstr "P" + +#: utils/translation/trans_real.py:409 +msgid "YEAR_MONTH_FORMAT" +msgstr "F Y" + +#: utils/translation/trans_real.py:410 +msgid "MONTH_DAY_FORMAT" +msgstr "j \\de F" + +#: template/defaultfilters.py:532 +msgid "yes,no,maybe" +msgstr "sí,no,tal vez" + +#: template/defaultfilters.py:561 #, python-format -msgid "Make sure your uploaded file is at least %s bytes big." -msgstr "Asegúrese de que el fichero que envía tiene al menos %s bytes." +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d byte" +msgstr[1] "%(size)d bytes" -#: core/validators.py:455 +#: template/defaultfilters.py:563 #, python-format -msgid "Make sure your uploaded file is at most %s bytes big." -msgstr "Asegúrese de que el fichero que envía tiene como máximo %s bytes." +msgid "%.1f KB" +msgstr "%.1f KB" -#: core/validators.py:472 -msgid "The format for this field is wrong." -msgstr "El formato de este campo es incorrecto." +#: template/defaultfilters.py:565 +#, python-format +msgid "%.1f MB" +msgstr "%.1f MB" -#: core/validators.py:487 -msgid "This field is invalid." -msgstr "Este campo no es válido." +#: template/defaultfilters.py:566 +#, python-format +msgid "%.1f GB" +msgstr "%.1f GB" -#: core/validators.py:523 +#: newforms/fields.py:123 #, python-format -msgid "Could not retrieve anything from %s." -msgstr "No pude obtener nada de %s." +msgid "Ensure this value has at most %(max)d characters (it has %(length)d)." +msgstr "Asegúrese de que su texto tiene a lo más %(max)d caracteres (actualmente tiene %(length)d)." -#: core/validators.py:526 +#: newforms/fields.py:125 #, python-format -msgid "" -"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'." -msgstr "" -"La URL %(url)s devolvió la cabecera Content-Type '%(contenttype)s', que no " -"es válida." +msgid "Ensure this value has at least %(min)d characters (it has %(length)d)." +msgstr "Asegúrese de que su texto tiene al menos %(min)d caracteres (actualmente tiene %(length)d)." -#: core/validators.py:559 +#: newforms/fields.py:151 +#: newforms/fields.py:174 +#: newforms/fields.py:204 #, python-format -msgid "" -"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with " -"\"%(start)s\".)" -msgstr "" -"Por favor, cierre la etiqueta %(tag)s de la línea %(line)s. (La línea " -"empieza por \"%(start)s\".)" +msgid "Ensure this value is less than or equal to %s." +msgstr "Asegúrese de que este valor es menor o igual a %s." -#: core/validators.py:563 +#: newforms/fields.py:153 +#: newforms/fields.py:176 +#: newforms/fields.py:206 #, python-format -msgid "" -"Some text starting on line %(line)s is not allowed in that context. (Line " -"starts with \"%(start)s\".)" -msgstr "" -"Parte del texto que comienza en la línea %(line)s no está permitido en ese " -"contexto. (La línea empieza por \"%(start)s\".)" +msgid "Ensure this value is greater than or equal to %s." +msgstr "Asegúrese de que este valor es mayor o igual a %s." + +#: newforms/fields.py:172 +#: newforms/fields.py:199 +msgid "Enter a number." +msgstr "Introduzca un número." -#: core/validators.py:568 +#: newforms/fields.py:208 #, python-format -msgid "" -"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%" -"(start)s\".)" -msgstr "" -"El \"%(attr)s\" de la línea %(line)s no es un atributo válido. (La línea " -"empieza por \"%(start)s\".)" +msgid "Ensure that there are no more than %s digits in total." +msgstr "Asegúrese de que no hay más de %s dígitos en total." -#: core/validators.py:573 +#: newforms/fields.py:210 #, python-format -msgid "" -"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%" -"(start)s\".)" -msgstr "" -"La \"<%(tag)s>\" de la línea %(line)s no es una etiqueta válida. (La línea " -"empieza por \"%(start)s\".)" +msgid "Ensure that there are no more than %s decimal places." +msgstr "Asegúrese de que no hay más de %s decimales." -#: core/validators.py:577 +#: newforms/fields.py:212 #, python-format -msgid "" -"A tag on line %(line)s is missing one or more required attributes. (Line " -"starts with \"%(start)s\".)" -msgstr "" -"A una etiqueta de la línea %(line)s le faltan uno o más atributos " -"requeridos. (La línea empieza por \"%(start)s\".)" +msgid "Ensure that there are no more than %s digits before the decimal point." +msgstr "Asegúrese de que no hay más de %s dígitos antes del punto decimal." + +#: newforms/fields.py:245 +#: newforms/fields.py:629 +msgid "Enter a valid date." +msgstr "Introduzca una fecha válida." + +#: newforms/fields.py:272 +#: newforms/fields.py:631 +msgid "Enter a valid time." +msgstr "Introduzca una hora válida." + +#: newforms/fields.py:308 +msgid "Enter a valid date/time." +msgstr "Introduzca una fecha/hora válida." + +#: newforms/fields.py:321 +msgid "Enter a valid value." +msgstr "Introduzca un valor correcto." + +#: newforms/fields.py:379 +msgid "No file was submitted." +msgstr "No se ha enviado ningún fichero" + +#: newforms/fields.py:419 +#: newforms/fields.py:444 +msgid "Enter a valid URL." +msgstr "Introduzca una URL válida." + +#: newforms/fields.py:446 +msgid "This URL appears to be a broken link." +msgstr "La URL parece ser un enlace roto." + +#: newforms/fields.py:497 +#: newforms/models.py:180 +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Escoja una opción válida. Esa opción no está entre las aceptadas." + +#: newforms/fields.py:513 +#: newforms/fields.py:589 +#: newforms/models.py:197 +msgid "Enter a list of values." +msgstr "Introduzca una lista de valores." -#: core/validators.py:582 +#: newforms/fields.py:519 +#: newforms/models.py:203 #, python-format -msgid "" -"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line " -"starts with \"%(start)s\".)" -msgstr "" -"El atributo \"%(attr)s\" de la línea %(line)s tiene un valor que no es " -"válido. (La línea empieza por \"%(start)s\".)" +msgid "Select a valid choice. %s is not one of the available choices." +msgstr "Escoja una opción válida; '%s' no es una de las opciones disponibles." + diff --git a/django/conf/locale/fi/LC_MESSAGES/django.mo b/django/conf/locale/fi/LC_MESSAGES/django.mo Binary files differindex 024d2ad98b..6d4ebd3283 100644 --- a/django/conf/locale/fi/LC_MESSAGES/django.mo +++ b/django/conf/locale/fi/LC_MESSAGES/django.mo diff --git a/django/conf/locale/fi/LC_MESSAGES/django.po b/django/conf/locale/fi/LC_MESSAGES/django.po index 275feaaf81..d068f2adfe 100644 --- a/django/conf/locale/fi/LC_MESSAGES/django.po +++ b/django/conf/locale/fi/LC_MESSAGES/django.po @@ -1,292 +1,137 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# Finnish translation of Django +# Copyright (C) 2006-2007 +# This file is distributed under the same license as the Django package. # msgid "" msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" +"Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2006-08-05 14:41+0300\n" -"PO-Revision-Date: 2006-08-12 23:41+0300\n" +"POT-Creation-Date: 2007-09-14 23:33+0300\n" +"PO-Revision-Date: 2007-09-15 00:34+0300\n" "Last-Translator: Antti Kaihola <antti.kaihola@ambitone.com>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" +"Language-Team: Django I18N <Django-I18N@googlegroups.com>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Poedit-Language: Finnish\n" +"X-Poedit-Country: FINLAND\n" -#: db/models/manipulators.py:302 -#, python-format -msgid "%(object)s with this %(type)s already exists for the given %(field)s." -msgstr "" - -#: db/models/fields/related.py:51 -#, python-format -msgid "Please enter a valid %s." -msgstr "Syöttämäsi %s ei kelpaa." - -#: db/models/fields/related.py:618 -msgid "Separate multiple IDs with commas." -msgstr "Erottele tunnisteet pilkuilla." - -#: db/models/fields/related.py:620 -msgid "" -"Hold down \"Control\", or \"Command\" on a Mac, to select more than one." -msgstr "" -" Pidä \"Ctrl\"-näppäin (tai Macin \"Command\") pohjassa valitaksesi useita " -"vaihtoehtoja." - -#: db/models/fields/related.py:664 -#, python-format -msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid." -msgid_plural "" -"Please enter valid %(self)s IDs. The values %(value)r are invalid." -msgstr[0] "Syöttämäsi %(self)s-tunniste %(value)r ei kelpaa." -msgstr[1] "Syöttämäsi %(self)s-tunnisteet %(value)r eivät kelpaa." - -#: db/models/fields/__init__.py:40 -#, python-format -msgid "%(optname)s with this %(fieldname)s already exists." -msgstr "%(optname)s, jolla on tämä %(fieldname)s, on jo olemassa." - -#: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265 -#: db/models/fields/__init__.py:551 db/models/fields/__init__.py:562 -#: forms/__init__.py:346 -msgid "This field is required." -msgstr "Tämä kenttä vaaditaan." - -#: db/models/fields/__init__.py:340 -msgid "This value must be an integer." -msgstr "Tarvitaan kokonaisluku." - -#: db/models/fields/__init__.py:372 -msgid "This value must be either True or False." -msgstr "Tarvitaan tosi (True) tai epätosi (False)." - -#: db/models/fields/__init__.py:388 -msgid "This field cannot be null." -msgstr "Tämän kentän arvo ei voi olla \"null\"." - -#: db/models/fields/__init__.py:415 core/validators.py:127 -msgid "Enter a valid date in YYYY-MM-DD format." -msgstr "Päivämäärän pitää olla muodossa VVVV-KK-PP." - -#: db/models/fields/__init__.py:477 core/validators.py:135 -msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format." -msgstr "Ajankohdan pitää olla muodossa VVVV-KK-PP TT:MM." - -#: db/models/fields/__init__.py:571 -msgid "Enter a valid filename." -msgstr "Tiedostonimi ei kelpaa." - -#: conf/global_settings.py:39 -msgid "Arabic" -msgstr "arabia" - -#: conf/global_settings.py:40 -msgid "Bengali" -msgstr "bengali" - -#: conf/global_settings.py:41 -msgid "Czech" -msgstr "tšekki" - -#: conf/global_settings.py:42 -msgid "Welsh" -msgstr "wales" - -#: conf/global_settings.py:43 -msgid "Danish" -msgstr "tanska" - -#: conf/global_settings.py:44 -msgid "German" -msgstr "saksa" - -#: conf/global_settings.py:45 -msgid "Greek" -msgstr "kreikka" - -#: conf/global_settings.py:46 -msgid "English" -msgstr "englanti" - -#: conf/global_settings.py:47 -msgid "Spanish" -msgstr "espanja" - -#: conf/global_settings.py:48 -msgid "Argentinean Spanish" -msgstr "Argentiinan espanja" - -#: conf/global_settings.py:49 -msgid "French" -msgstr "ranska" - -#: conf/global_settings.py:50 -msgid "Galician" -msgstr "" - -#: conf/global_settings.py:51 -msgid "Hungarian" -msgstr "unkari" - -#: conf/global_settings.py:52 -msgid "Hebrew" -msgstr "heprea" - -#: conf/global_settings.py:53 -msgid "Icelandic" -msgstr "islanti" - -#: conf/global_settings.py:54 -msgid "Italian" -msgstr "italia" - -#: conf/global_settings.py:55 -msgid "Japanese" -msgstr "japani" - -#: conf/global_settings.py:56 -msgid "Dutch" -msgstr "hollanti" - -#: conf/global_settings.py:57 -msgid "Norwegian" -msgstr "norja" - -#: conf/global_settings.py:58 -msgid "Brazilian" -msgstr "" - -#: conf/global_settings.py:59 -msgid "Romanian" -msgstr "romania" - -#: conf/global_settings.py:60 -msgid "Russian" -msgstr "venäjä" - -#: conf/global_settings.py:61 -msgid "Slovak" -msgstr "slovakia" - -#: conf/global_settings.py:62 -msgid "Slovenian" -msgstr "slovenia" - -#: conf/global_settings.py:63 -msgid "Serbian" -msgstr "serbia" - -#: conf/global_settings.py:64 -msgid "Swedish" -msgstr "ruotsi" - -#: conf/global_settings.py:65 -msgid "Tamil" -msgstr "" - -#: conf/global_settings.py:66 -msgid "Ukrainian" -msgstr "ukraina" - -#: conf/global_settings.py:67 -msgid "Simplified Chinese" -msgstr "kiina (yksinkertaistettu)" - -#: conf/global_settings.py:68 -msgid "Traditional Chinese" -msgstr "kiina (perinteinen)" - -#: core/validators.py:63 +#: core/validators.py:72 msgid "This value must contain only letters, numbers and underscores." -msgstr "Tässä voidaan käyttää vain kirjaimia (a-z), numeroita (0-9) ja alaviivoja (_)." +msgstr "" +"Tässä voidaan käyttää vain kirjaimia (a-z), numeroita (0-9) ja alaviivoja " +"(_)." -#: core/validators.py:67 +#: core/validators.py:76 msgid "" "This value must contain only letters, numbers, underscores, dashes or " "slashes." -msgstr "Tässä voidaan käyttää vain kirjaimia (a-z), numeroita (0-9) sekä ala-, tavu- ja kauttaviivoja (_ - /)." +msgstr "" +"Tässä voidaan käyttää vain kirjaimia (a-z), numeroita (0-9) sekä ala-, tavu- " +"ja kauttaviivoja (_ - /)." + +#: core/validators.py:80 +msgid "This value must contain only letters, numbers, underscores or hyphens." +msgstr "Tässä voidaan käyttää vain kirjaimia (a-z), numeroita (0-9) sekä ala- ja tavuviivoja (_ -)." -#: core/validators.py:75 +#: core/validators.py:84 msgid "Uppercase letters are not allowed here." msgstr "Isot kirjaimet (ABC) eivät kelpaa tässä." -#: core/validators.py:79 +#: core/validators.py:88 msgid "Lowercase letters are not allowed here." msgstr "Pienet kirjaimet (abc) eivät kelpaa tässä." -#: core/validators.py:86 +#: core/validators.py:95 msgid "Enter only digits separated by commas." msgstr "Vain pilkulla erotetut luvut kelpaavat tässä." -#: core/validators.py:98 +#: core/validators.py:107 msgid "Enter valid e-mail addresses separated by commas." msgstr "Syötä sähköpostiosoitteita pilkuilla erotettuina." -#: core/validators.py:102 +#: core/validators.py:111 msgid "Please enter a valid IP address." msgstr "IP-osoite ei kelpaa." -#: core/validators.py:106 +#: core/validators.py:115 msgid "Empty values are not allowed here." msgstr "Tätä kohtaa ei voi jättää tyhjäksi." -#: core/validators.py:110 +#: core/validators.py:119 msgid "Non-numeric characters aren't allowed here." msgstr "Vain numerot (0-9) kelpaavat tässä." -#: core/validators.py:114 +#: core/validators.py:123 msgid "This value can't be comprised solely of digits." msgstr "Tarvitaan vähintään yksi merkki, joka ei ole numero (0-9)." -#: core/validators.py:119 +#: core/validators.py:128 newforms/fields.py:149 msgid "Enter a whole number." msgstr "Syötä kokonaisluku." -#: core/validators.py:123 +#: core/validators.py:132 msgid "Only alphabetical characters are allowed here." msgstr "Vain kirjaimet kelpaavat tässä." -#: core/validators.py:131 +#: core/validators.py:147 +msgid "Year must be 1900 or later." +msgstr "Vuosiluvuksi kelpaa vain 1900 tai myöhempi." + +#: core/validators.py:151 +#, python-format +msgid "Invalid date: %s" +msgstr "Päivämäärä %s ei kelpaa" + +#: core/validators.py:156 db/models/fields/__init__.py:505 +msgid "Enter a valid date in YYYY-MM-DD format." +msgstr "Päivämäärän pitää olla muodossa VVVV-KK-PP." + +#: core/validators.py:161 msgid "Enter a valid time in HH:MM format." msgstr "Ajan täytyy olla muodossa TT:MM." -#: core/validators.py:139 +#: core/validators.py:165 db/models/fields/__init__.py:579 +msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format." +msgstr "Ajankohdan pitää olla muodossa VVVV-KK-PP TT:MM." + +#: core/validators.py:170 newforms/fields.py:343 msgid "Enter a valid e-mail address." msgstr "Syötä kelvollinen sähköpostiosoite." -#: core/validators.py:151 core/validators.py:379 forms/__init__.py:661 +#: core/validators.py:182 core/validators.py:469 newforms/fields.py:377 +#: oldforms/__init__.py:686 msgid "No file was submitted. Check the encoding type on the form." msgstr "Tiedostoa ei lähetetty. Tarkista lomakkeen koodaus (encoding)." -#: core/validators.py:155 +#: core/validators.py:193 newforms/fields.py:405 msgid "" "Upload a valid image. The file you uploaded was either not an image or a " "corrupted image." -msgstr "Kuva ei kelpaa. Lähettämäsi tiedosto ei ole kuva, tai tiedosto on vioittunut." +msgstr "" +"Kuva ei kelpaa. Lähettämäsi tiedosto ei ole kuva, tai tiedosto on vioittunut." -#: core/validators.py:162 +#: core/validators.py:200 #, python-format msgid "The URL %s does not point to a valid image." msgstr "Osoittessa %s ei ole kuvaa tai se on vioittunut." -#: core/validators.py:166 +#: core/validators.py:204 #, python-format msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid." msgstr "Puhelinnumeron tulee olla muodossa XXX-XXX-XXXX. \"%s\" ei kelpaa." -#: core/validators.py:174 +#: core/validators.py:212 #, python-format msgid "The URL %s does not point to a valid QuickTime video." msgstr "Osoitteessa %s ei ole QuickTime-videota tai se on vioittunut." -#: core/validators.py:178 +#: core/validators.py:216 msgid "A valid URL is required." msgstr "URL-osoite ei kelpaa." -#: core/validators.py:192 +#: core/validators.py:230 #, python-format msgid "" "Valid HTML is required. Specific errors are:\n" @@ -295,671 +140,1213 @@ msgstr "" "HTML-koodi ei kelpaa. Virheilmoitus on:\n" "%s" -#: core/validators.py:199 +#: core/validators.py:237 #, python-format msgid "Badly formed XML: %s" msgstr "Vääränmuotoinen XML: %s" -#: core/validators.py:209 +#: core/validators.py:254 #, python-format msgid "Invalid URL: %s" msgstr "URL-osoite %s ei kelpaa." -#: core/validators.py:213 core/validators.py:215 +#: core/validators.py:259 core/validators.py:261 #, python-format msgid "The URL %s is a broken link." msgstr "Osoite %s on rikkoutunut tai väärä linkki." -#: core/validators.py:221 +#: core/validators.py:267 msgid "Enter a valid U.S. state abbreviation." msgstr "Syötä USA:n osavaltion lyhenne." -#: core/validators.py:236 +#: core/validators.py:281 #, python-format msgid "Watch your mouth! The word %s is not allowed here." msgid_plural "Watch your mouth! The words %s are not allowed here." msgstr[0] "Sanaa \"%s\" ei saa käyttää tässä." msgstr[1] "Sanoja \"%s\" ei saa käyttää tässä." -#: core/validators.py:243 +#: core/validators.py:283 db/models/manipulators.py:310 +#: contrib/admin/views/main.py:342 contrib/admin/views/main.py:344 +#: contrib/admin/views/main.py:346 +msgid "and" +msgstr "ja" + +#: core/validators.py:288 #, python-format msgid "This field must match the '%s' field." msgstr "Arvon täytyy olla sama kuin kentässä '%s'." -#: core/validators.py:262 +#: core/validators.py:307 msgid "Please enter something for at least one field." msgstr "Täytä ainakin yksi kenttä." -#: core/validators.py:271 core/validators.py:282 +#: core/validators.py:316 core/validators.py:327 msgid "Please enter both fields or leave them both empty." msgstr "Täytä tai jätä tyhjäksi kummatkin kentät." -#: core/validators.py:289 +#: core/validators.py:335 #, python-format msgid "This field must be given if %(field)s is %(value)s" msgstr "Tämä kenttä pitää täyttää, jos %(field)s on %(value)s." -#: core/validators.py:301 +#: core/validators.py:348 #, python-format msgid "This field must be given if %(field)s is not %(value)s" msgstr "Tämä kenttä pitää täyttää, jos %(field)s ei ole %(value)s." -#: core/validators.py:320 +#: core/validators.py:367 msgid "Duplicate values are not allowed." msgstr "Samaa arvoa ei voi käyttää kahdesti." -#: core/validators.py:343 +#: core/validators.py:382 +#, python-format +msgid "This value must be between %(lower)s and %(upper)s." +msgstr "Tämän luvun on oltava välillä %(lower)s–%(upper)s." + +#: core/validators.py:384 +#, python-format +msgid "This value must be at least %s." +msgstr "Tämän luvun on oltava vähintään %s." + +#: core/validators.py:386 +#, python-format +msgid "This value must be no more than %s." +msgstr "Tämän luvun on oltava enintään %s." + +#: core/validators.py:422 #, python-format msgid "This value must be a power of %s." msgstr "Tämän luvun on oltava %s:n potenssi." -#: core/validators.py:354 +#: core/validators.py:432 msgid "Please enter a valid decimal number." msgstr "Desimaaliluku ei kelpaa." -#: core/validators.py:356 +#: core/validators.py:439 #, python-format msgid "Please enter a valid decimal number with at most %s total digit." msgid_plural "" "Please enter a valid decimal number with at most %s total digits." -msgstr[0] "Desimaaliluvussa saa tässä olla yhteensä vain %s merkitsevä numero. Huomaa, että desimaalierottimena käytetään pilkun (,) sijasta pistettä (.)." -msgstr[1] "Desimaaliluvussa saa tässä olla yhteensä vain %s merkitsevää numeroa. Huomaa, että desimaalierottimena käytetään pilkun (,) sijasta pistettä (.)." +msgstr[0] "" +"Desimaaliluvussa saa tässä olla yhteensä vain %s merkitsevä numero. Huomaa, " +"että desimaalierottimena käytetään pilkun (,) sijasta pistettä (.)." +msgstr[1] "" +"Desimaaliluvussa saa tässä olla yhteensä vain %s merkitsevää numeroa. " +"Huomaa, että desimaalierottimena käytetään pilkun (,) sijasta pistettä (.)." -#: core/validators.py:359 +#: core/validators.py:442 #, python-format msgid "" "Please enter a valid decimal number with a whole part of at most %s digit." msgid_plural "" "Please enter a valid decimal number with a whole part of at most %s digits." -msgstr[0] "Desimaaliluvun kokonaisosassa saa tässä olla vain %s numero. Huomaa, että desimaalierottimena käytetään pilkun (,) sijasta pistettä (.)." -msgstr[1] "Desimaaliluvun kokonaisosassa saa tässä olla vain %s numeroa. Huomaa, että desimaalierottimena käytetään pilkun (,) sijasta pistettä (.)." +msgstr[0] "" +"Desimaaliluvun kokonaisosassa saa tässä olla vain %s numero. Huomaa, että " +"desimaalierottimena käytetään pilkun (,) sijasta pistettä (.)." +msgstr[1] "" +"Desimaaliluvun kokonaisosassa saa tässä olla vain %s numeroa. Huomaa, että " +"desimaalierottimena käytetään pilkun (,) sijasta pistettä (.)." -#: core/validators.py:362 +#: core/validators.py:445 #, python-format msgid "Please enter a valid decimal number with at most %s decimal place." msgid_plural "" "Please enter a valid decimal number with at most %s decimal places." -msgstr[0] "Tässä saa olla vain %s desimaali. Huomaa, että desimaalierottimena käytetään pilkun (,) sijasta pistettä (.)." -msgstr[1] "Tässä saa olla vain %s desimaalia. Huomaa, että desimaalierottimena käytetään pilkun (,) sijasta pistettä (.)." +msgstr[0] "" +"Tässä saa olla vain %s desimaali. Huomaa, että desimaalierottimena käytetään " +"pilkun (,) sijasta pistettä (.)." +msgstr[1] "" +"Tässä saa olla vain %s desimaalia. Huomaa, että desimaalierottimena " +"käytetään pilkun (,) sijasta pistettä (.)." -#: core/validators.py:372 +#: core/validators.py:453 +msgid "Please enter a valid floating point number." +msgstr "Syötä liukuluku." + +#: core/validators.py:462 #, python-format msgid "Make sure your uploaded file is at least %s bytes big." msgstr "Lähetä vähintään %s tavun kokoinen tiedosto." -#: core/validators.py:373 +#: core/validators.py:463 #, python-format msgid "Make sure your uploaded file is at most %s bytes big." msgstr "Lähetä enintään %s tavun kokoinen tiedosto." -#: core/validators.py:390 +#: core/validators.py:480 msgid "The format for this field is wrong." msgstr "Muoto ei kelpaa." -#: core/validators.py:405 +#: core/validators.py:495 msgid "This field is invalid." msgstr "Tämä arvo ei kelpaa." -#: core/validators.py:441 +#: core/validators.py:531 #, python-format msgid "Could not retrieve anything from %s." msgstr "Tietoja ei voida noutaa kohteesta: %s." -#: core/validators.py:444 +#: core/validators.py:534 #, python-format msgid "" "The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'." -msgstr "Osoitteesta %(url)s saatiin virheellinen Content-Type '%(contenttype)s'." +msgstr "" +"Osoitteesta %(url)s saatiin virheellinen Content-Type '%(contenttype)s'." -#: core/validators.py:477 +#: core/validators.py:567 #, python-format msgid "" "Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with " "\"%(start)s\".)" -msgstr "Rivillä %(line)s oleva tagi %(tag)s pitää sulkea. (Rivi alkaa \"%(start)s\")" +msgstr "" +"Rivillä %(line)s oleva tagi %(tag)s pitää sulkea. (Rivi alkaa \"%(start)s\")" -#: core/validators.py:481 +#: core/validators.py:571 #, python-format msgid "" "Some text starting on line %(line)s is not allowed in that context. (Line " "starts with \"%(start)s\".)" -msgstr "Rivillä %(line)s on tekstiä, joka ei kelpaa tässä yhteydessä. (Rivi alkaa \"%(start)s\")" +msgstr "" +"Rivillä %(line)s on tekstiä, joka ei kelpaa tässä yhteydessä. (Rivi alkaa \"%" +"(start)s\")" -#: core/validators.py:486 +#: core/validators.py:576 #, python-format msgid "" "\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%" "(start)s\".)" -msgstr "Rivillä %(line)s attribuutti %(attr)s ei kelpaa. (Rivi alkaa \"%(start)s\")" +msgstr "" +"Rivillä %(line)s attribuutti %(attr)s ei kelpaa. (Rivi alkaa \"%(start)s\")" -#: core/validators.py:491 +#: core/validators.py:581 #, python-format msgid "" "\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%" "(start)s\".)" -msgstr "Rivillä %(line)s tagi \"<%(tag)s>\" ei kelpaa. (Rivi alkaa \"%(start)s\")" +msgstr "" +"Rivillä %(line)s tagi \"<%(tag)s>\" ei kelpaa. (Rivi alkaa \"%(start)s\")" -#: core/validators.py:495 +#: core/validators.py:585 #, python-format msgid "" "A tag on line %(line)s is missing one or more required attributes. (Line " "starts with \"%(start)s\".)" -msgstr "Rivillä %(line)s yhdestä tagista puuttuu yksi tai useampi attribuutti. (Rivi alkaa \"%(start)s\")" +msgstr "" +"Rivillä %(line)s yhdestä tagista puuttuu yksi tai useampi attribuutti. (Rivi " +"alkaa \"%(start)s\")" -#: core/validators.py:500 +#: core/validators.py:590 #, python-format msgid "" "The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line " "starts with \"%(start)s\".)" -msgstr "Rivillä %(line)s attribuutin %(attr)s arvo ei kelpaa. (Rivi alkaa \"%(start)s\")" +msgstr "" +"Rivillä %(line)s attribuutin %(attr)s arvo ei kelpaa. (Rivi alkaa \"%(start)s" +"\")" -#: contrib/auth/forms.py:52 -msgid "" -"Your Web browser doesn't appear to have cookies enabled. Cookies are " -"required for logging in." -msgstr "Selaimesi ei salli evästeitä. Sisäänkirjautuminen vaatii evästeen." +#: newforms/fields.py:93 newforms/fields.py:509 newforms/fields.py:585 +#: newforms/fields.py:596 newforms/models.py:193 +#: db/models/fields/__init__.py:159 db/models/fields/__init__.py:316 +#: db/models/fields/__init__.py:731 db/models/fields/__init__.py:742 +#: oldforms/__init__.py:373 +msgid "This field is required." +msgstr "Tämä kenttä vaaditaan." -#: contrib/auth/forms.py:59 contrib/admin/views/decorators.py:10 -msgid "" -"Please enter a correct username and password. Note that both fields are case-" -"sensitive." -msgstr "Käyttäjätunnus tai salasana ei kelpaa. Huomaa, että isot ja pienet kirjaimet ovat merkitseviä." +#: newforms/fields.py:123 +#, python-format +msgid "Ensure this value has at most %(max)d characters (it has %(length)d)." +msgstr "Tähän kelpaa enintään %(max)d merkkiä (nyt niitä on %(length)d)." -#: contrib/auth/forms.py:61 -msgid "This account is inactive." -msgstr "Tämä käyttäjätili ei ole voimassa." +#: newforms/fields.py:125 +#, python-format +msgid "Ensure this value has at least %(min)d characters (it has %(length)d)." +msgstr "Tähän tarvitaan vähintään %(min)d merkkiä (nyt on vain %(length)d)." -#: contrib/auth/models.py:38 contrib/auth/models.py:57 -msgid "name" -msgstr "nimi" +#: newforms/fields.py:151 newforms/fields.py:174 newforms/fields.py:204 +#, python-format +msgid "Ensure this value is less than or equal to %s." +msgstr "Tämän luvun on oltava enintään %s." -#: contrib/auth/models.py:40 -msgid "codename" -msgstr "koodinimi" +#: newforms/fields.py:153 newforms/fields.py:176 newforms/fields.py:206 +#, python-format +msgid "Ensure this value is greater than or equal to %s." +msgstr "Tämän luvun on oltava vähintään %s." -#: contrib/auth/models.py:42 -msgid "permission" -msgstr "oikeus" +#: newforms/fields.py:172 newforms/fields.py:199 +msgid "Enter a number." +msgstr "Syötä kokonaisluku." -#: contrib/auth/models.py:43 contrib/auth/models.py:58 -msgid "permissions" -msgstr "oikeudet" +#: newforms/fields.py:208 +#, python-format +msgid "Ensure that there are no more than %s digits in total." +msgstr "Tässä luvussa voi olla yhteensä enintään %s numeroa." -#: contrib/auth/models.py:60 -msgid "group" -msgstr "ryhmä" +#: newforms/fields.py:210 +#, python-format +msgid "Ensure that there are no more than %s decimal places." +msgstr "Tässä luvussa saa olla enintään %s desimaalia." -#: contrib/auth/models.py:61 contrib/auth/models.py:100 -msgid "groups" -msgstr "ryhmät" +#: newforms/fields.py:212 +#, python-format +msgid "Ensure that there are no more than %s digits before the decimal point." +msgstr "Tässä luvussa saa olla enintään %s numeroa ennen desimaalipilkkua." -#: contrib/auth/models.py:90 -msgid "username" -msgstr "tunnus" +#: newforms/fields.py:245 newforms/fields.py:629 +msgid "Enter a valid date." +msgstr "Syötä oikea päivämäärä." -#: contrib/auth/models.py:90 -msgid "" -"Required. 30 characters or fewer. Alphanumeric characters only (letters, " -"digits and underscores)." -msgstr " Vaaditaan. Enintään 30 kirjanta (a-z), numeroa (0-9) tai alaviivaa (_)." +#: newforms/fields.py:272 newforms/fields.py:631 +msgid "Enter a valid time." +msgstr "Syötä oikea kellonaika." -#: contrib/auth/models.py:91 -msgid "first name" -msgstr "etunimi" +#: newforms/fields.py:308 +msgid "Enter a valid date/time." +msgstr "Syötä oikea pvm/kellonaika." -#: contrib/auth/models.py:92 -msgid "last name" -msgstr "sukunimi" +#: newforms/fields.py:321 +msgid "Enter a valid value." +msgstr "Syötä oikea arvo." -#: contrib/auth/models.py:93 -msgid "e-mail address" -msgstr "sähköposti" +#: newforms/fields.py:379 +msgid "No file was submitted." +msgstr "Yhtään tiedostoa ei ole lähetetty." -#: contrib/auth/models.py:94 -msgid "password" -msgstr "salasana" +#: newforms/fields.py:381 oldforms/__init__.py:688 +msgid "The submitted file is empty." +msgstr "Lähetetty tiedosto on tyhjä." -#: contrib/auth/models.py:94 -msgid "Use '[algo]$[salt]$[hexdigest]'" -msgstr "(Salasanaa ei näytetä selväkielisenä)" +#: newforms/fields.py:419 newforms/fields.py:444 +msgid "Enter a valid URL." +msgstr "Syötä oikea URL-osoite." -#: contrib/auth/models.py:95 -msgid "staff status" -msgstr "ylläpitäjä" +#: newforms/fields.py:446 +msgid "This URL appears to be a broken link." +msgstr "Tämä URL-osoite on rikkinäinen linkki." -#: contrib/auth/models.py:95 -msgid "Designates whether the user can log into this admin site." -msgstr "Ylläpitäjillä on pääsy tähän sivuston ylläpito-osioon." +#: newforms/fields.py:497 newforms/models.py:180 +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Valitse oikea vaihtoehto. Valintasi ei löydy vaihtoehtojen joukosta." -#: contrib/auth/models.py:96 -msgid "active" -msgstr "voimassa" +#: newforms/fields.py:513 newforms/fields.py:589 newforms/models.py:197 +msgid "Enter a list of values." +msgstr "Syötä lista." -#: contrib/auth/models.py:96 -msgid "" -"Designates whether this user can log into the Django admin. Unselect this " -"instead of deleting accounts." -msgstr "Määrää, voiko käyttäjä kirjautua sisään. Tällä voi estää käyttäjätilin käytön poistamatta sitä." +#: newforms/fields.py:519 newforms/models.py:203 +#, python-format +msgid "Select a valid choice. %s is not one of the available choices." +msgstr "Valitse oikea vaihtoehto. %s ei löydy vaihtoehtojen joukosta." -#: contrib/auth/models.py:97 -msgid "superuser status" -msgstr "pääkäyttäjä" +#: newforms/widgets.py:188 contrib/admin/filterspecs.py:152 +#: oldforms/__init__.py:591 +msgid "Unknown" +msgstr "Tuntematon" -#: contrib/auth/models.py:97 -msgid "" -"Designates that this user has all permissions without explicitly assigning " -"them." -msgstr "Antaa käyttäjälle kaikki oikeudet ilman, että niitä täytyy erikseen luetella." +#: newforms/widgets.py:188 contrib/admin/filterspecs.py:145 +#: oldforms/__init__.py:591 +msgid "Yes" +msgstr "Kyllä" -#: contrib/auth/models.py:98 -msgid "last login" -msgstr "viimeksi kirjautunut" +#: newforms/widgets.py:188 contrib/admin/filterspecs.py:145 +#: oldforms/__init__.py:591 +msgid "No" +msgstr "Ei" -#: contrib/auth/models.py:99 -msgid "date joined" -msgstr "liittynyt" +#: views/generic/create_update.py:43 +#, python-format +msgid "The %(verbose_name)s was created successfully." +msgstr "%(verbose_name)s luotiin onnistuneesti." -#: contrib/auth/models.py:101 -msgid "" -"In addition to the permissions manually assigned, this user will also get " -"all permissions granted to each group he/she is in." -msgstr "" -"Tässä valittujen oikeuksien lisäksi käyttäjä saa myös kaikki niiden ryhmien " -"oikeudet, joiden jäsen hän on." +#: views/generic/create_update.py:117 +#, python-format +msgid "The %(verbose_name)s was updated successfully." +msgstr "%(verbose_name)s päivitettiin onnistuneesti." -#: contrib/auth/models.py:102 -msgid "user permissions" -msgstr "käyttäjän oikeudet" +#: views/generic/create_update.py:184 +#, python-format +msgid "The %(verbose_name)s was deleted." +msgstr "%(verbose_name)s on poistettu." -#: contrib/auth/models.py:105 -msgid "user" -msgstr "käyttäjä" +#: template/defaultfilters.py:532 +msgid "yes,no,maybe" +msgstr "kyllä,ei,ehkä" -#: contrib/auth/models.py:106 -msgid "users" -msgstr "käyttäjät" +#: template/defaultfilters.py:561 +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "" +msgstr[1] "" -#: contrib/auth/models.py:111 -msgid "Personal info" -msgstr "Henkilökohtaiset tiedot" +#: template/defaultfilters.py:563 +#, python-format +msgid "%.1f KB" +msgstr "%.1f Kt" -#: contrib/auth/models.py:112 -msgid "Permissions" -msgstr "Oikeudet" +#: template/defaultfilters.py:565 +#, python-format +msgid "%.1f MB" +msgstr "%.1f Mt" -#: contrib/auth/models.py:113 -msgid "Important dates" -msgstr "Tärkeät päivämäärät" +#: template/defaultfilters.py:566 +#, python-format +msgid "%.1f GB" +msgstr "%.1f Gt" -#: contrib/auth/models.py:114 -msgid "Groups" -msgstr "Ryhmät" +#: db/models/manipulators.py:309 +#, python-format +msgid "%(object)s with this %(type)s already exists for the given %(field)s." +msgstr "%(field)s omaa jo kohteen %(object)s, joka on tyyppiä %(type)s." -#: contrib/auth/models.py:256 -msgid "message" -msgstr "viesti" +#: db/models/fields/__init__.py:52 +#, python-format +msgid "%(optname)s with this %(fieldname)s already exists." +msgstr "%(optname)s, jolla on tämä %(fieldname)s, on jo olemassa." -#: contrib/auth/views.py:39 -msgid "Logged out" -msgstr "Kirjautunut ulos" +#: db/models/fields/__init__.py:414 +msgid "This value must be an integer." +msgstr "Tarvitaan kokonaisluku." -#: contrib/admin/models.py:16 -msgid "action time" -msgstr "tapahtumahetki" +#: db/models/fields/__init__.py:450 +msgid "This value must be either True or False." +msgstr "Tarvitaan tosi (True) tai epätosi (False)." -#: contrib/admin/models.py:19 -msgid "object id" -msgstr "kohteen tunniste" +#: db/models/fields/__init__.py:471 +msgid "This field cannot be null." +msgstr "Tämän kentän arvo ei voi olla \"null\"." -#: contrib/admin/models.py:20 -msgid "object repr" -msgstr "kohteen tiedot" +#: db/models/fields/__init__.py:640 +msgid "This value must be a decimal number." +msgstr "Tähän tarvitaan desimaaliluku." -#: contrib/admin/models.py:21 -msgid "action flag" -msgstr "tapahtumatyyppi" +#: db/models/fields/__init__.py:751 +msgid "Enter a valid filename." +msgstr "Tiedostonimi ei kelpaa." -#: contrib/admin/models.py:22 -msgid "change message" -msgstr "selitys" +#: db/models/fields/__init__.py:894 +msgid "This value must be either None, True or False." +msgstr "Tähän tarvitaan tyhjä (None), tosi (True) tai epätosi (False)." -#: contrib/admin/models.py:25 -msgid "log entry" -msgstr "lokimerkintä" +#: db/models/fields/related.py:55 +#, python-format +msgid "Please enter a valid %s." +msgstr "Syöttämäsi %s ei kelpaa." -#: contrib/admin/models.py:26 -msgid "log entries" -msgstr "lokimerkinnät" +#: db/models/fields/related.py:658 +msgid "Separate multiple IDs with commas." +msgstr "Erottele tunnisteet pilkuilla." + +#: db/models/fields/related.py:660 +msgid "" +"Hold down \"Control\", or \"Command\" on a Mac, to select more than one." +msgstr "" +" Pidä \"Ctrl\"-näppäin (tai Macin \"Command\") pohjassa valitaksesi useita " +"vaihtoehtoja." -#: contrib/admin/filterspecs.py:40 +#: db/models/fields/related.py:707 #, python-format +msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid." +msgid_plural "" +"Please enter valid %(self)s IDs. The values %(value)r are invalid." +msgstr[0] "Syöttämäsi %(self)s-tunniste %(value)r ei kelpaa." +msgstr[1] "Syöttämäsi %(self)s-tunnisteet %(value)r eivät kelpaa." + +#: contrib/sites/models.py:33 +msgid "domain name" +msgstr "domain-nimi" + +#: contrib/sites/models.py:34 +msgid "display name" +msgstr "näyttönimi" + +#: contrib/sites/models.py:38 +msgid "site" +msgstr "sivusto" + +#: contrib/sites/models.py:39 +msgid "sites" +msgstr "sivustot" + +#: contrib/redirects/models.py:7 +msgid "redirect from" +msgstr "ohjaa osoitteesta" + +#: contrib/redirects/models.py:8 msgid "" -"<h3>By %s:</h3>\n" -"<ul>\n" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." msgstr "" -"<h3>Yksi %s:</h3>\n" -"<ul>\n" +"Tässä on käytettävä absoluuttista polkua ilman verkkotunnusta. Esimerkki: " +"'\\\n" +"events/search/'" -#: contrib/admin/filterspecs.py:70 contrib/admin/filterspecs.py:88 -#: contrib/admin/filterspecs.py:143 contrib/admin/filterspecs.py:169 -msgid "All" -msgstr "Kaikki" +#: contrib/redirects/models.py:9 +msgid "redirect to" +msgstr "ohjaa osoitteeseen" -#: contrib/admin/filterspecs.py:109 -msgid "Any date" -msgstr "Mikä tahansa päivä" +#: contrib/redirects/models.py:10 +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"Tässä on käytettävä joko absoluuttista polkua (kuten yllä) tai täydellistä " +"'http://'-alkuista URL-osoitetta." -#: contrib/admin/filterspecs.py:110 -msgid "Today" -msgstr "Tänään" +#: contrib/redirects/models.py:13 +msgid "redirect" +msgstr "edelleenohjaus" -#: contrib/admin/filterspecs.py:113 -msgid "Past 7 days" -msgstr "Viimeiset 7 päivää" +#: contrib/redirects/models.py:14 +msgid "redirects" +msgstr "edelleenohjaukset" -#: contrib/admin/filterspecs.py:115 -msgid "This month" -msgstr "Tässä kuussa" +#: contrib/comments/models.py:67 contrib/comments/models.py:169 +msgid "object ID" +msgstr "kohteen tunniste" -#: contrib/admin/filterspecs.py:117 -msgid "This year" -msgstr "Tänä vuonna" +#: contrib/comments/models.py:68 +msgid "headline" +msgstr "otsikko" -#: contrib/admin/filterspecs.py:143 -msgid "Yes" -msgstr "Kyllä" +#: contrib/comments/models.py:69 contrib/comments/models.py:90 +#: contrib/comments/models.py:170 +msgid "comment" +msgstr "kommentti" -#: contrib/admin/filterspecs.py:143 -msgid "No" -msgstr "Ei" +#: contrib/comments/models.py:70 +msgid "rating #1" +msgstr "1. pisteytys" -#: contrib/admin/filterspecs.py:150 -msgid "Unknown" -msgstr "Tuntematon" +#: contrib/comments/models.py:71 +msgid "rating #2" +msgstr "2. pisteytys" -#: contrib/admin/views/decorators.py:24 -#: contrib/admin/templates/admin/login.html:25 -msgid "Log in" -msgstr "Kirjaudu sisään" +#: contrib/comments/models.py:72 +msgid "rating #3" +msgstr "3. pisteytys" -#: contrib/admin/views/decorators.py:62 -msgid "" -"Please log in again, because your session has expired. Don't worry: Your " -"submission has been saved." -msgstr "Kirjaudu uudelleen sisään, koska istuntosi on mennyt umpeen. Muutoksesi ovat silti tallessa." +#: contrib/comments/models.py:73 +msgid "rating #4" +msgstr "4. pisteytys" -#: contrib/admin/views/decorators.py:69 +#: contrib/comments/models.py:74 +msgid "rating #5" +msgstr "5. pisteytys" + +#: contrib/comments/models.py:75 +msgid "rating #6" +msgstr "6. pisteytys" + +#: contrib/comments/models.py:76 +msgid "rating #7" +msgstr "7. pisteytys" + +#: contrib/comments/models.py:77 +msgid "rating #8" +msgstr "8. pisteytys" + +#: contrib/comments/models.py:82 +msgid "is valid rating" +msgstr "on sallittu pisteytys" + +#: contrib/comments/models.py:83 contrib/comments/models.py:172 +msgid "date/time submitted" +msgstr "lähetyshetki" + +#: contrib/comments/models.py:84 contrib/comments/models.py:173 +msgid "is public" +msgstr "on julkinen" + +#: contrib/comments/models.py:85 contrib/admin/views/doc.py:306 +msgid "IP address" +msgstr "IP-osoite" + +#: contrib/comments/models.py:86 +msgid "is removed" +msgstr "on poistettu" + +#: contrib/comments/models.py:86 msgid "" -"Looks like your browser isn't configured to accept cookies. Please enable " -"cookies, reload this page, and try again." -msgstr "Selaimesi ei salli evästeitä. Muuta asetukset sallimaan evästeet, lataa tämä sivu uudelleen ja yritä toistamiseen." +"Check this box if the comment is inappropriate. A \"This comment has been " +"removed\" message will be displayed instead." +msgstr "" +"Rastita jos kommentti on asiaankuulumaton. Kommentin tilalla näytetään\n" +"viesti \"Tämä kommentti on poistettu\"." -#: contrib/admin/views/decorators.py:83 -msgid "Usernames cannot contain the '@' character." -msgstr "Käyttäjätunnuksessa ei saa olla '@'-merkkiä." +#: contrib/comments/models.py:91 +msgid "comments" +msgstr "kommentit" -#: contrib/admin/views/decorators.py:85 +#: contrib/comments/models.py:134 contrib/comments/models.py:213 +msgid "Content object" +msgstr "Kommentoitu kohde" + +#: contrib/comments/models.py:162 #, python-format -msgid "Your e-mail address is not your username. Try '%s' instead." -msgstr "Käyttäjätunnus ei ole sama kuin sähköpostiosoite. Kokeile '%s'." +msgid "" +"Posted by %(user)s at %(date)s\n" +"\n" +"%(comment)s\n" +"\n" +"http://%(domain)s%(url)s" +msgstr "" +" Kirjoittanut %(user)s, pvm %(date)s\\n\n" +" \\n\n" +" %(comment)s\\n\n" +" \\n\n" +" http://%(domain)s%(url)s" -#: contrib/admin/views/main.py:223 -msgid "Site administration" -msgstr "Sivuston ylläpito" +#: contrib/comments/models.py:171 +msgid "person's name" +msgstr "henkilön nimi" -#: contrib/admin/views/main.py:257 contrib/admin/views/auth.py:14 -#, python-format -msgid "The %(name)s \"%(obj)s\" was added successfully." -msgstr "%(name)s \"%(obj)s\" on nyt lisätty." +#: contrib/comments/models.py:174 +msgid "ip address" +msgstr "IP-osoite" -#: contrib/admin/views/main.py:261 contrib/admin/views/main.py:345 -#: contrib/admin/views/auth.py:19 -msgid "You may edit it again below." -msgstr "Voit muokata sitä uudelleen alla." +#: contrib/comments/models.py:176 +msgid "approved by staff" +msgstr "ylläpidon hyväksymä" -#: contrib/admin/views/main.py:269 contrib/admin/views/main.py:354 -#, python-format -msgid "You may add another %s below." -msgstr "Uusi %s on lisättävissä alla." +#: contrib/comments/models.py:179 +msgid "free comment" +msgstr "vapaa kommentti" -#: contrib/admin/views/main.py:287 -#, python-format -msgid "Add %s" -msgstr "Uusi %s" +#: contrib/comments/models.py:180 +msgid "free comments" +msgstr "vapaat kommentit" -#: contrib/admin/views/main.py:333 -#, python-format -msgid "Added %s." -msgstr "Lisätty %s." +#: contrib/comments/models.py:239 +msgid "score" +msgstr "pisteet" -#: contrib/admin/views/main.py:333 contrib/admin/views/main.py:335 -#: contrib/admin/views/main.py:337 -msgid "and" -msgstr "ja" +#: contrib/comments/models.py:240 +msgid "score date" +msgstr "pisteytyspäivä" + +#: contrib/comments/models.py:243 +msgid "karma score" +msgstr "karma-pisteytys" -#: contrib/admin/views/main.py:335 +#: contrib/comments/models.py:244 +msgid "karma scores" +msgstr "karma-pisteytykset" + +#: contrib/comments/models.py:248 #, python-format -msgid "Changed %s." -msgstr "Muokattu: %s." +msgid "%(score)d rating by %(user)s" +msgstr "%(score)d pistettä käyttäjältä %(user)s" -#: contrib/admin/views/main.py:337 +#: contrib/comments/models.py:264 #, python-format -msgid "Deleted %s." -msgstr "Poistettu %s." +msgid "" +"This comment was flagged by %(user)s:\n" +"\n" +"%(text)s" +msgstr "" +" %(user)s on merkinnyt tämän kommentin:\\n\n" +" \\n\n" +" %(text)s" -#: contrib/admin/views/main.py:340 -msgid "No fields changed." -msgstr "Ei muutoksia kenttiin." +#: contrib/comments/models.py:271 +msgid "flag date" +msgstr "merkintäpäivä" + +#: contrib/comments/models.py:274 +msgid "user flag" +msgstr "käyttäjän merkki" -#: contrib/admin/views/main.py:343 +#: contrib/comments/models.py:275 +msgid "user flags" +msgstr "käyttäjien merkit" + +#: contrib/comments/models.py:279 #, python-format -msgid "The %(name)s \"%(obj)s\" was changed successfully." -msgstr "%(name)s \"%(obj)s\" on nyt muutettu." +msgid "Flag by %r" +msgstr "Käyttäjän %r merkki" + +#: contrib/comments/models.py:284 +msgid "deletion date" +msgstr "poistamispäivä" -#: contrib/admin/views/main.py:351 +#: contrib/comments/models.py:286 +msgid "moderator deletion" +msgstr "valvojan poisto" + +#: contrib/comments/models.py:287 +msgid "moderator deletions" +msgstr "valvojien poistot" + +#: contrib/comments/models.py:291 #, python-format +msgid "Moderator deletion by %r" +msgstr "Valvojan %r poisto" + +#: contrib/comments/templates/comments/freeform.html:4 +msgid "Your name:" +msgstr "Nimesi:" + +#: contrib/comments/templates/comments/freeform.html:5 +#: contrib/comments/templates/comments/form.html:28 +msgid "Comment:" +msgstr "Kommentti:" + +#: contrib/comments/templates/comments/freeform.html:10 +#: contrib/comments/templates/comments/form.html:35 +msgid "Preview comment" +msgstr "Esikatsele kommenttia" + +#: contrib/comments/templates/comments/form.html:6 +#: contrib/comments/templates/comments/form.html:8 +#: contrib/admin/templates/admin/login.html:17 +msgid "Username:" +msgstr "Käyttäjätunnus:" + +#: contrib/comments/templates/comments/form.html:6 +#: contrib/admin/templates/admin_doc/template_tag_index.html:5 +#: contrib/admin/templates/admin_doc/model_detail.html:3 +#: contrib/admin/templates/admin_doc/template_detail.html:4 +#: contrib/admin/templates/admin_doc/index.html:4 +#: contrib/admin/templates/admin_doc/view_detail.html:4 +#: contrib/admin/templates/admin_doc/missing_docutils.html:4 +#: contrib/admin/templates/admin_doc/bookmarklets.html:4 +#: contrib/admin/templates/admin_doc/template_filter_index.html:5 +#: contrib/admin/templates/admin_doc/model_index.html:5 +#: contrib/admin/templates/admin_doc/view_index.html:5 +#: contrib/admin/templates/registration/password_change_form.html:3 +#: contrib/admin/templates/registration/password_change_done.html:3 +#: contrib/admin/templates/admin/delete_confirmation.html:3 +#: contrib/admin/templates/admin/base.html:25 +#: contrib/admin/templates/admin/object_history.html:3 +#: contrib/admin/templates/admin/change_list.html:5 +#: contrib/admin/templates/admin/change_form.html:10 +#: contrib/admin/templates/admin/auth/user/change_password.html:9 +msgid "Log out" +msgstr "Kirjaudu ulos" + +#: contrib/comments/templates/comments/form.html:8 +#: contrib/admin/templates/admin/login.html:20 +msgid "Password:" +msgstr "Salasana:" + +#: contrib/comments/templates/comments/form.html:8 +msgid "Forgotten your password?" +msgstr "Unohditko salasanasi?" + +#: contrib/comments/templates/comments/form.html:12 +msgid "Ratings" +msgstr "Pisteytykset" + +#: contrib/comments/templates/comments/form.html:12 +#: contrib/comments/templates/comments/form.html:23 +msgid "Required" +msgstr "Vaaditaan" + +#: contrib/comments/templates/comments/form.html:12 +#: contrib/comments/templates/comments/form.html:23 +msgid "Optional" +msgstr "Vapaavalintainen" + +#: contrib/comments/templates/comments/form.html:23 +msgid "Post a photo" +msgstr "Lähetä valokuva" + +#: contrib/comments/views/karma.py:20 +msgid "Anonymous users cannot vote" +msgstr "Anonyymit käyttäjät eivät voi äänestää" + +#: contrib/comments/views/karma.py:24 +msgid "Invalid comment ID" +msgstr "Kommentin tunniste on virheellinen" + +#: contrib/comments/views/karma.py:26 +msgid "No voting for yourself" +msgstr "Itseään ei voi äänestää" + +#: contrib/comments/views/comments.py:28 msgid "" -"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below." -msgstr "%(name)s \"%(obj)s\" on nyt lisätty. Voit muokata sitä uudelleen alla." +"This rating is required because you've entered at least one other rating." +msgstr "" +"Tämä pisteytys on annettava, koska olet syöttänyt ainakin yhden muunkin " +"pisteytyksen." -#: contrib/admin/views/main.py:389 +#: contrib/comments/views/comments.py:112 #, python-format -msgid "Change %s" -msgstr "Muokkaa: %s" +msgid "" +"This comment was posted by a user who has posted fewer than %(count)s " +"comment:\n" +"\n" +"%(text)s" +msgid_plural "" +"This comment was posted by a user who has posted fewer than %(count)s " +"comments:\n" +"\n" +"%(text)s" +msgstr[0] "" +"Kommentin kirjoittanut käyttäjä on kirjoittanut vain yhden kommentin:\n" +"\n" +"%(text)s" +msgstr[1] "" +"Kommentin kirjoittanut käyttäjä on kirjoittanut alle %(count)s kommenttia:\n" +"\n" +"%(text)s" -#: contrib/admin/views/main.py:471 +# Mitä "sketchy user" tarkoittaa? +#: contrib/comments/views/comments.py:117 #, python-format -msgid "One or more %(fieldname)s in %(name)s: %(obj)s" -msgstr "Yksi tai useampi %(fieldname)s kohteessa %(name)s: %(obj)s" +msgid "" +"This comment was posted by a sketchy user:\n" +"\n" +"%(text)s" +msgstr "" +"Tämä on \"sketchy\"-käyttäjän kirjoittama kommentti:\n" +"\n" +"%(text)s" -#: contrib/admin/views/main.py:476 -#, python-format -msgid "One or more %(fieldname)s in %(name)s:" -msgstr "Yksi tai useampi %(fieldname)s kohteessa %(name)s:" +#: contrib/comments/views/comments.py:189 +#: contrib/comments/views/comments.py:281 +msgid "Only POSTs are allowed" +msgstr "Vain POST-kutsut sallittu" -#: contrib/admin/views/main.py:509 -#, python-format -msgid "The %(name)s \"%(obj)s\" was deleted successfully." -msgstr "%(name)s \"%(obj)s\" on poistettu." +#: contrib/comments/views/comments.py:193 +#: contrib/comments/views/comments.py:285 +msgid "One or more of the required fields wasn't submitted" +msgstr "Yksi tai useampi vaadittu kenttä on jäänyt täyttämättä" -#: contrib/admin/views/main.py:512 -msgid "Are you sure?" -msgstr "Oletko varma?" +#: contrib/comments/views/comments.py:197 +#: contrib/comments/views/comments.py:287 +msgid "Somebody tampered with the comment form (security violation)" +msgstr "Kommenttilomaketta on käpälöity (turvallisuusrike)" + +#: contrib/comments/views/comments.py:207 +#: contrib/comments/views/comments.py:293 +msgid "" +"The comment form had an invalid 'target' parameter -- the object ID was " +"invalid" +msgstr "" +"Kommenttilomakkeen 'target'-parametri ei kelpaa -- kohteen ID oli " +"virheellinen" -#: contrib/admin/views/main.py:534 +#: contrib/comments/views/comments.py:258 +#: contrib/comments/views/comments.py:322 +msgid "The comment form didn't provide either 'preview' or 'post'" +msgstr "Kommenttilomake ei pyytänyt esikatselua tai lähettämistä" + +#: contrib/humanize/templatetags/humanize.py:20 +msgid "th" +msgstr "." + +#: contrib/humanize/templatetags/humanize.py:20 +msgid "st" +msgstr "." + +#: contrib/humanize/templatetags/humanize.py:20 +msgid "nd" +msgstr "." + +#: contrib/humanize/templatetags/humanize.py:20 +msgid "rd" +msgstr "." + +#: contrib/humanize/templatetags/humanize.py:50 #, python-format -msgid "Change history: %s" -msgstr "Muokkaushistoria: %s" +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "" +msgstr[1] "" -#: contrib/admin/views/main.py:568 +#: contrib/humanize/templatetags/humanize.py:53 #, python-format -msgid "Select %s" -msgstr "Valitse %s" +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "" +msgstr[1] "" -#: contrib/admin/views/main.py:568 +#: contrib/humanize/templatetags/humanize.py:56 #, python-format -msgid "Select %s to change" -msgstr "Valitse muokattava %s" +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "" +msgstr[1] "" -#: contrib/admin/views/main.py:744 -msgid "Database error" -msgstr "Tietokantavirhe" +#: contrib/humanize/templatetags/humanize.py:71 +msgid "one" +msgstr "yksi" -#: contrib/admin/views/doc.py:291 contrib/admin/views/doc.py:301 -#: contrib/admin/views/doc.py:303 contrib/admin/views/doc.py:309 -#: contrib/admin/views/doc.py:310 contrib/admin/views/doc.py:312 -msgid "Integer" -msgstr "Kokonaisluku" +#: contrib/humanize/templatetags/humanize.py:71 +msgid "two" +msgstr "kaksi" -#: contrib/admin/views/doc.py:292 -msgid "Boolean (Either True or False)" -msgstr "Totuusarvo: joko tosi (True) tai epätosi (False)" +#: contrib/humanize/templatetags/humanize.py:71 +msgid "three" +msgstr "kolme" -#: contrib/admin/views/doc.py:293 contrib/admin/views/doc.py:311 -#, python-format -msgid "String (up to %(maxlength)s)" -msgstr "Merkkijono (enintään %(maxlength)s merkkiä)" +#: contrib/humanize/templatetags/humanize.py:71 +msgid "four" +msgstr "neljä" -#: contrib/admin/views/doc.py:294 -msgid "Comma-separated integers" -msgstr "Pilkulla erotetut kokonaisluvut" +#: contrib/humanize/templatetags/humanize.py:71 +msgid "five" +msgstr "viisi" -#: contrib/admin/views/doc.py:295 -msgid "Date (without time)" -msgstr "Päivämäärä" +#: contrib/humanize/templatetags/humanize.py:71 +msgid "six" +msgstr "kuusi" -#: contrib/admin/views/doc.py:296 -msgid "Date (with time)" -msgstr "Päivämäärä ja kellonaika" +#: contrib/humanize/templatetags/humanize.py:71 +msgid "seven" +msgstr "seitsemän" -#: contrib/admin/views/doc.py:297 -msgid "E-mail address" -msgstr "Sähköpostios." +#: contrib/humanize/templatetags/humanize.py:71 +msgid "eight" +msgstr "kahdeksan" -#: contrib/admin/views/doc.py:298 contrib/admin/views/doc.py:299 -#: contrib/admin/views/doc.py:302 -msgid "File path" -msgstr "Tiedostopolku" +#: contrib/humanize/templatetags/humanize.py:71 +msgid "nine" +msgstr "yhdeksän" -#: contrib/admin/views/doc.py:300 -msgid "Decimal number" -msgstr "Desimaaliluku" +#: contrib/humanize/templatetags/humanize.py:90 +msgid "today" +msgstr "tänään" -#: contrib/admin/views/doc.py:304 contrib/comments/models.py:85 -msgid "IP address" -msgstr "IP-osoite" +#: contrib/humanize/templatetags/humanize.py:92 +msgid "tomorrow" +msgstr "huomenna" -#: contrib/admin/views/doc.py:306 -msgid "Boolean (Either True, False or None)" -msgstr "Totuusarvo: joko tosi (True), epätosi (False) tai ei mikään (None)" +#: contrib/humanize/templatetags/humanize.py:94 +msgid "yesterday" +msgstr "eilen" -#: contrib/admin/views/doc.py:307 -msgid "Relation to parent model" -msgstr "Relaatio emomalliin" +#: contrib/sessions/models.py:68 +msgid "session key" +msgstr "istunnon avain" -#: contrib/admin/views/doc.py:308 -msgid "Phone number" -msgstr "Puhelinnumero" +#: contrib/sessions/models.py:69 +msgid "session data" +msgstr "istunnon tiedot" -#: contrib/admin/views/doc.py:313 -msgid "Text" -msgstr "Tekstiä" +#: contrib/sessions/models.py:70 +msgid "expire date" +msgstr "vanhenee" -#: contrib/admin/views/doc.py:314 -msgid "Time" -msgstr "Kellonaika" +#: contrib/sessions/models.py:74 +msgid "session" +msgstr "istunto" -#: contrib/admin/views/doc.py:315 contrib/flatpages/models.py:7 -msgid "URL" -msgstr "URL-osoite" +#: contrib/sessions/models.py:75 +msgid "sessions" +msgstr "istunnot" -#: contrib/admin/views/doc.py:316 -msgid "U.S. state (two uppercase letters)" -msgstr "USA:n osavaltio (kaksikirjaiminen versaalein)" +#: contrib/contenttypes/models.py:37 +msgid "python model class name" +msgstr "mallin python-luokan nimi" -#: contrib/admin/views/doc.py:317 -msgid "XML text" -msgstr "XML-teksti" +#: contrib/contenttypes/models.py:40 +msgid "content type" +msgstr "sisältötyyppi" -#: contrib/admin/views/auth.py:25 -msgid "Add user" -msgstr "Uusi käyttäjä" +#: contrib/contenttypes/models.py:41 +msgid "content types" +msgstr "sisältötyypit" -#: contrib/admin/templatetags/admin_list.py:230 -msgid "All dates" -msgstr "Kaikki päivät" +#: contrib/admin/filterspecs.py:42 +#, python-format +msgid "" +"<h3>By %s:</h3>\n" +"<ul>\n" +msgstr "" +"<h3>Yksi %s:</h3>\n" +"<ul>\n" -#: contrib/admin/templates/admin/pagination.html:10 -msgid "Show all" -msgstr "Näytä kaikki" +#: contrib/admin/filterspecs.py:72 contrib/admin/filterspecs.py:90 +#: contrib/admin/filterspecs.py:145 contrib/admin/filterspecs.py:171 +msgid "All" +msgstr "Kaikki" -#: contrib/admin/templates/admin/delete_confirmation.html:3 -#: contrib/admin/templates/admin/change_form.html:10 -#: contrib/admin/templates/admin/change_list.html:5 -#: contrib/admin/templates/admin/object_history.html:3 -#: contrib/admin/templates/admin/base.html:24 -#: contrib/admin/templates/admin_doc/bookmarklets.html:3 -#: contrib/admin/templates/registration/password_change_form.html:3 -#: contrib/admin/templates/registration/password_change_done.html:3 -msgid "Documentation" -msgstr "Ohjeita" +#: contrib/admin/filterspecs.py:111 +msgid "Any date" +msgstr "Mikä tahansa päivä" + +#: contrib/admin/filterspecs.py:112 +msgid "Today" +msgstr "Tänään" + +#: contrib/admin/filterspecs.py:115 +msgid "Past 7 days" +msgstr "Viimeiset 7 päivää" + +#: contrib/admin/filterspecs.py:117 +msgid "This month" +msgstr "Tässä kuussa" + +#: contrib/admin/filterspecs.py:119 +msgid "This year" +msgstr "Tänä vuonna" + +#: contrib/admin/models.py:17 +msgid "action time" +msgstr "tapahtumahetki" + +#: contrib/admin/models.py:20 +msgid "object id" +msgstr "kohteen tunniste" + +#: contrib/admin/models.py:21 +msgid "object repr" +msgstr "kohteen tiedot" + +#: contrib/admin/models.py:22 +msgid "action flag" +msgstr "tapahtumatyyppi" + +#: contrib/admin/models.py:23 +msgid "change message" +msgstr "selitys" + +#: contrib/admin/models.py:26 +msgid "log entry" +msgstr "lokimerkintä" + +#: contrib/admin/models.py:27 +msgid "log entries" +msgstr "lokimerkinnät" + +#: contrib/admin/templatetags/admin_list.py:254 +msgid "All dates" +msgstr "Kaikki päivät" -#: contrib/admin/templates/admin/delete_confirmation.html:3 -#: contrib/admin/templates/admin/change_form.html:10 -#: contrib/admin/templates/admin/change_list.html:5 -#: contrib/admin/templates/admin/object_history.html:3 -#: contrib/admin/templates/admin/base.html:24 -#: contrib/admin/templates/admin_doc/template_filter_index.html:5 -#: contrib/admin/templates/admin_doc/bookmarklets.html:4 #: contrib/admin/templates/admin_doc/template_tag_index.html:5 -#: contrib/admin/templates/admin_doc/index.html:4 #: contrib/admin/templates/admin_doc/model_detail.html:3 -#: contrib/admin/templates/admin_doc/missing_docutils.html:4 #: contrib/admin/templates/admin_doc/template_detail.html:4 -#: contrib/admin/templates/admin_doc/view_index.html:5 -#: contrib/admin/templates/admin_doc/model_index.html:5 -#: contrib/admin/templates/admin_doc/view_detail.html:4 -#: contrib/admin/templates/registration/password_change_form.html:3 -#: contrib/admin/templates/registration/password_change_done.html:3 -msgid "Change password" -msgstr "Vaihda salasana" - -#: contrib/admin/templates/admin/delete_confirmation.html:3 -#: contrib/admin/templates/admin/change_form.html:10 -#: contrib/admin/templates/admin/change_list.html:5 -#: contrib/admin/templates/admin/object_history.html:3 -#: contrib/admin/templates/admin/base.html:24 -#: contrib/admin/templates/admin_doc/template_filter_index.html:5 -#: contrib/admin/templates/admin_doc/bookmarklets.html:4 -#: contrib/admin/templates/admin_doc/template_tag_index.html:5 #: contrib/admin/templates/admin_doc/index.html:4 -#: contrib/admin/templates/admin_doc/model_detail.html:3 +#: contrib/admin/templates/admin_doc/view_detail.html:4 #: contrib/admin/templates/admin_doc/missing_docutils.html:4 -#: contrib/admin/templates/admin_doc/template_detail.html:4 -#: contrib/admin/templates/admin_doc/view_index.html:5 +#: contrib/admin/templates/admin_doc/bookmarklets.html:4 +#: contrib/admin/templates/admin_doc/template_filter_index.html:5 #: contrib/admin/templates/admin_doc/model_index.html:5 -#: contrib/admin/templates/admin_doc/view_detail.html:4 +#: contrib/admin/templates/admin_doc/view_index.html:5 #: contrib/admin/templates/registration/password_change_form.html:3 #: contrib/admin/templates/registration/password_change_done.html:3 -#: contrib/comments/templates/comments/form.html:6 -msgid "Log out" -msgstr "Kirjaudu ulos" +#: contrib/admin/templates/admin/delete_confirmation.html:3 +#: contrib/admin/templates/admin/base.html:25 +#: contrib/admin/templates/admin/object_history.html:3 +#: contrib/admin/templates/admin/change_list.html:5 +#: contrib/admin/templates/admin/change_form.html:10 +#: contrib/admin/templates/admin/auth/user/change_password.html:9 +#: contrib/admin/templates/admin/auth/user/change_password.html:15 +#: contrib/admin/templates/admin/auth/user/change_password.html:46 +msgid "Change password" +msgstr "Vaihda salasana" +#: contrib/admin/templates/admin_doc/bookmarklets.html:3 +#: contrib/admin/templates/registration/password_reset_done.html:4 +#: contrib/admin/templates/registration/password_change_form.html:4 +#: contrib/admin/templates/registration/logged_out.html:4 +#: contrib/admin/templates/registration/password_reset_form.html:4 +#: contrib/admin/templates/registration/password_change_done.html:4 #: contrib/admin/templates/admin/delete_confirmation.html:6 -#: contrib/admin/templates/admin/change_form.html:13 -#: contrib/admin/templates/admin/change_list.html:6 +#: contrib/admin/templates/admin/base.html:30 +#: contrib/admin/templates/admin/invalid_setup.html:4 #: contrib/admin/templates/admin/object_history.html:5 +#: contrib/admin/templates/admin/change_list.html:6 +#: contrib/admin/templates/admin/change_form.html:13 #: contrib/admin/templates/admin/500.html:4 -#: contrib/admin/templates/admin/invalid_setup.html:4 -#: contrib/admin/templates/admin/base.html:29 +#: contrib/admin/templates/admin/auth/user/change_password.html:12 +msgid "Home" +msgstr "Etusivu" + #: contrib/admin/templates/admin_doc/bookmarklets.html:3 -#: contrib/admin/templates/registration/password_reset_form.html:4 -#: contrib/admin/templates/registration/logged_out.html:4 +#: contrib/admin/templates/registration/password_change_form.html:3 +#: contrib/admin/templates/registration/password_change_done.html:3 +#: contrib/admin/templates/admin/delete_confirmation.html:3 +#: contrib/admin/templates/admin/base.html:25 +#: contrib/admin/templates/admin/object_history.html:3 +#: contrib/admin/templates/admin/change_list.html:5 +#: contrib/admin/templates/admin/change_form.html:10 +#: contrib/admin/templates/admin/auth/user/change_password.html:9 +msgid "Documentation" +msgstr "Ohjeita" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:3 +msgid "Bookmarklets" +msgstr "Kirjanmerkkiset" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:5 +msgid "Documentation bookmarklets" +msgstr "Ohjeiden kirjanmerkkiset" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:9 +msgid "" +"\n" +"<p class=\"help\">To install bookmarklets, drag the link to your bookmarks\n" +"toolbar, or right-click the link and add it to your bookmarks. Now you can\n" +"select the bookmarklet from any page in the site. Note that some of these\n" +"bookmarklets require you to be viewing the site from a computer designated\n" +"as \"internal\" (talk to your system administrator if you aren't sure if\n" +"your computer is \"internal\").</p>\n" +msgstr "" +"\n" +"<p class=\"help\">Asenna kirjanmerkkinen raahaamalla linkki kirjanmerkkien " +"työkalupalkkiin tai napsauttamalla linkkiä oikeanpuoleisella hiiren " +"painikkeella ja valitsemalla kirjanmerkkeihin lisäämisen. Sen jälkeen voit " +"valita kirjanmerkkisen miltä tahansa sivuston sivulta. Huomaa, että jotkin " +"näistä kirjanmerkkisistä toimivat vain, jos selaat sivustoa \"paikalliseksi" +"\" määritellyltä tietokoneelta (kysy lisätietoja verkkonne ylläpitäjältä).</" +"p>\n" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:19 +msgid "Documentation for this page" +msgstr "Tämän sivun ohjeita" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:20 +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "Vie avoinna olevan sivun luoneen näkymän ohjeisiin." + +#: contrib/admin/templates/admin_doc/bookmarklets.html:22 +msgid "Show object ID" +msgstr "Näytä kohteen tunniste" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:23 +msgid "" +"Shows the content-type and unique ID for pages that represent a single " +"object." +msgstr "" +"Näyttää yksittäistä kohdetta vastaavilla sivuilla kohteen tyypin ja " +"tunnisteen." + +#: contrib/admin/templates/admin_doc/bookmarklets.html:25 +msgid "Edit this object (current window)" +msgstr "Muokkaa tätä kohdetta (tässä ikkunassa)" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:26 +msgid "Jumps to the admin page for pages that represent a single object." +msgstr "" +"Siirtyy yksittäistä kohdetta vastaavalta sivulta kohteen ylläpitosivulle." + +#: contrib/admin/templates/admin_doc/bookmarklets.html:28 +msgid "Edit this object (new window)" +msgstr "Muokkaa tätä kohdetta (uudessa ikkunassa)" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:29 +msgid "As above, but opens the admin page in a new window." +msgstr "Kuten yllä, mutta avaa ylläpitosivun uuteen ikkunaan." + #: contrib/admin/templates/registration/password_reset_done.html:4 +#: contrib/admin/templates/registration/password_reset_form.html:4 +#: contrib/admin/templates/registration/password_reset_form.html:6 +#: contrib/admin/templates/registration/password_reset_form.html:10 +msgid "Password reset" +msgstr "Salasanan nollaus" + +#: contrib/admin/templates/registration/password_reset_done.html:6 +#: contrib/admin/templates/registration/password_reset_done.html:10 +msgid "Password reset successful" +msgstr "Salasanan nollaus onnistui" + +#: contrib/admin/templates/registration/password_reset_done.html:12 +msgid "" +"We've e-mailed a new password to the e-mail address you submitted. You " +"should be receiving it shortly." +msgstr "" +"Uusi salasanasi on lähetetty antamaasi sähköpostiosoitteeseen.\n" +"Se saapuu tuota pikaa." + #: contrib/admin/templates/registration/password_change_form.html:4 +#: contrib/admin/templates/registration/password_change_form.html:6 +#: contrib/admin/templates/registration/password_change_form.html:10 #: contrib/admin/templates/registration/password_change_done.html:4 -msgid "Home" -msgstr "Etusivu" +msgid "Password change" +msgstr "Salasanan muuttaminen" + +#: contrib/admin/templates/registration/password_change_form.html:12 +msgid "" +"Please enter your old password, for security's sake, and then enter your new " +"password twice so we can verify you typed it in correctly." +msgstr "" +"Syötä vanha salasanasi varmistukseksi, ja syötä sitten uusi salasanasi\n" +"kaksi kertaa, jotta se tulee varmasti oikein." + +#: contrib/admin/templates/registration/password_change_form.html:17 +msgid "Old password:" +msgstr "Vanha salasana:" + +#: contrib/admin/templates/registration/password_change_form.html:19 +msgid "New password:" +msgstr "Uusi salasana:" + +#: contrib/admin/templates/registration/password_change_form.html:21 +msgid "Confirm password:" +msgstr "Varmista uusi salasana:" + +#: contrib/admin/templates/registration/password_change_form.html:23 +msgid "Change my password" +msgstr "Vaihda salasana" + +#: contrib/admin/templates/registration/logged_out.html:8 +msgid "Thanks for spending some quality time with the Web site today." +msgstr "Kiitos sivuillamme viettämästäsi ajasta." + +#: contrib/admin/templates/registration/logged_out.html:10 +msgid "Log in again" +msgstr "Kirjaudu uudelleen sisään" + +#: contrib/admin/templates/registration/password_reset_email.html:2 +msgid "You're receiving this e-mail because you requested a password reset" +msgstr "Sait tämän viestin, koska pyysit uutta salasanaa" + +#: contrib/admin/templates/registration/password_reset_email.html:3 +#, python-format +msgid "for your user account at %(site_name)s" +msgstr "sivuston %(site_name)s käyttäjätilillesi" + +#: contrib/admin/templates/registration/password_reset_email.html:5 +#, python-format +msgid "Your new password is: %(new_password)s" +msgstr "Uusi salasanasi on: %(new_password)s" + +#: contrib/admin/templates/registration/password_reset_email.html:7 +msgid "Feel free to change this password by going to this page:" +msgstr "Voit vaihtaa salasanan sivulla:" + +#: contrib/admin/templates/registration/password_reset_email.html:11 +msgid "Your username, in case you've forgotten:" +msgstr "Käyttäjätunnuksesi siltä varalta, että olet unohtanut sen:" + +#: contrib/admin/templates/registration/password_reset_email.html:13 +msgid "Thanks for using our site!" +msgstr "Kiitos vierailustasi sivuillemme!" + +#: contrib/admin/templates/registration/password_reset_email.html:15 +#, python-format +msgid "The %(site_name)s team" +msgstr "%(site_name)s ylläpitäjät" + +#: contrib/admin/templates/registration/password_reset_form.html:12 +msgid "" +"Forgotten your password? Enter your e-mail address below, and we'll reset " +"your password and e-mail the new one to you." +msgstr "" +"Unohditko salasanasi? Syötä alle sähköpostiosoitteesi, niin \n" +"lähetämme sinulle uuden salasanan." + +#: contrib/admin/templates/registration/password_reset_form.html:16 +msgid "E-mail address:" +msgstr "Sähköpostiosoite:" + +#: contrib/admin/templates/registration/password_reset_form.html:16 +msgid "Reset my password" +msgstr "Nollaa salasana" + +#: contrib/admin/templates/registration/password_change_done.html:6 +#: contrib/admin/templates/registration/password_change_done.html:10 +msgid "Password change successful" +msgstr "Salasanan muuttaminen onnistui" + +#: contrib/admin/templates/registration/password_change_done.html:12 +msgid "Your password was changed." +msgstr "Salasanasi on muutettu." #: contrib/admin/templates/admin/delete_confirmation.html:9 #: contrib/admin/templates/admin/submit_line.html:3 @@ -972,81 +1359,74 @@ msgid "" "Deleting the %(object_name)s '%(escaped_object)s' would result in deleting " "related objects, but your account doesn't have permission to delete the " "following types of objects:" -msgstr "Kohteen '%(escaped_object)s' (%(object_name)s) poisto poistaisi myös siihen liittyviä kohteita, mutta sinulla ei ole oikeutta näiden kohteiden poistamiseen:" +msgstr "" +"Kohteen '%(escaped_object)s' (%(object_name)s) poisto poistaisi myös siihen " +"liittyviä kohteita, mutta sinulla ei ole oikeutta näiden kohteiden " +"poistamiseen:" #: contrib/admin/templates/admin/delete_confirmation.html:21 #, python-format msgid "" "Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? " "All of the following related items will be deleted:" -msgstr "Haluatko varmasti poistaa kohteen \"%(escaped_object)s\" (%(object_name)s)? Myös seuraavat kohteet poistettaisiin samalla:" +msgstr "" +"Haluatko varmasti poistaa kohteen \"%(escaped_object)s\" (%(object_name)s)? " +"Myös seuraavat kohteet poistettaisiin samalla:" #: contrib/admin/templates/admin/delete_confirmation.html:26 msgid "Yes, I'm sure" msgstr "Kyllä, olen varma" -#: contrib/admin/templates/admin/404.html:4 -#: contrib/admin/templates/admin/404.html:8 -msgid "Page not found" -msgstr "Sivua ei löydy" - -#: contrib/admin/templates/admin/404.html:10 -msgid "We're sorry, but the requested page could not be found." -msgstr "Pahoittelemme, pyydettyä sivua ei voitu löytää." - -#: contrib/admin/templates/admin/change_form.html:15 -#: contrib/admin/templates/admin/index.html:28 -msgid "Add" -msgstr "Lisää uusi" - -#: contrib/admin/templates/admin/change_form.html:20 -#: contrib/admin/templates/admin/object_history.html:5 -msgid "History" -msgstr "Muokkaushistoria" - -#: contrib/admin/templates/admin/change_form.html:21 -msgid "View on site" -msgstr "Näytä lopputulos" - -#: contrib/admin/templates/admin/change_form.html:30 -msgid "Please correct the error below." -msgid_plural "Please correct the errors below." -msgstr[0] "Korjaa virhe." -msgstr[1] "Korjaa virheet." +#: contrib/admin/templates/admin/filters.html:4 +msgid "Filter" +msgstr "Suodatin" -#: contrib/admin/templates/admin/change_form.html:48 -msgid "Ordering" -msgstr "Järjestys" +#: contrib/admin/templates/admin/base.html:25 +msgid "Welcome," +msgstr "Tervetuloa," -#: contrib/admin/templates/admin/change_form.html:51 -msgid "Order:" -msgstr "Järjestysnumero:" +#: contrib/admin/templates/admin/invalid_setup.html:8 +msgid "" +"Something's wrong with your database installation. Make sure the appropriate " +"database tables have been created, and make sure the database is readable by " +"the appropriate user." +msgstr "" +"Tietokanta-asennuksessasi on jotain vialla. Varmistu, että sopivat taulut on " +"luotu ja että oikea käyttäjä voi lukea tietokantaa." #: contrib/admin/templates/admin/filter.html:2 #, python-format msgid " By %(filter_title)s " msgstr " %(filter_title)s:" -#: contrib/admin/templates/admin/submit_line.html:4 -msgid "Save as new" -msgstr "Tallenna uutena" +#: contrib/admin/templates/admin/object_history.html:5 +#: contrib/admin/templates/admin/change_form.html:21 +msgid "History" +msgstr "Muokkaushistoria" -#: contrib/admin/templates/admin/submit_line.html:5 -msgid "Save and add another" -msgstr "Tallenna ja lisää seuraava" +#: contrib/admin/templates/admin/object_history.html:18 +msgid "Date/time" +msgstr "Pvm/klo" -#: contrib/admin/templates/admin/submit_line.html:6 -msgid "Save and continue editing" -msgstr "Tallenna välillä ja jatka muokkaamista" +#: contrib/admin/templates/admin/object_history.html:19 +msgid "User" +msgstr "Käyttäjä" -#: contrib/admin/templates/admin/submit_line.html:7 -msgid "Save" -msgstr "Tallenna ja poistu" +#: contrib/admin/templates/admin/object_history.html:20 +msgid "Action" +msgstr "Toiminto" -#: contrib/admin/templates/admin/change_list.html:11 -#, python-format -msgid "Add %(name)s" -msgstr "Lisää uusi %(name)s" +#: contrib/admin/templates/admin/object_history.html:26 +msgid "DATE_WITH_TIME_FULL" +msgstr "N j, Y, P" + +#: contrib/admin/templates/admin/object_history.html:36 +msgid "" +"This object doesn't have a change history. It probably wasn't added via this " +"admin site." +msgstr "" +"Tällä kohteella ei ole muutoshistoriaa. Sitä ei ole lisätty tämän " +"ylläpitosivun avulla." #: contrib/admin/templates/admin/index.html:17 #, python-format @@ -1058,6 +1438,11 @@ msgstr "Sovelluksen %(name)s mallit." msgid "%(name)s" msgstr "%(name)s" +#: contrib/admin/templates/admin/index.html:28 +#: contrib/admin/templates/admin/change_form.html:15 +msgid "Add" +msgstr "Lisää uusi" + #: contrib/admin/templates/admin/index.html:34 msgid "Change" msgstr "Muokkaa" @@ -1078,54 +1463,31 @@ msgstr "Sinun tekemäsi muutokset" msgid "None available" msgstr "Ei yhtään" -#: contrib/admin/templates/admin/base_site.html:4 -msgid "Django site admin" -msgstr "Django-sivuston ylläpito" - -#: contrib/admin/templates/admin/base_site.html:7 -msgid "Django administration" -msgstr "Djangon ylläpito" - -#: contrib/admin/templates/admin/object_history.html:18 -msgid "Date/time" -msgstr "Pvm/klo" - -#: contrib/admin/templates/admin/object_history.html:19 -msgid "User" -msgstr "Käyttäjä" - -#: contrib/admin/templates/admin/object_history.html:20 -msgid "Action" -msgstr "Toiminto" - -#: contrib/admin/templates/admin/object_history.html:26 -msgid "DATE_WITH_TIME_FULL" -msgstr "N j, Y, P" +#: contrib/admin/templates/admin/login.html:25 +#: contrib/admin/views/decorators.py:24 +msgid "Log in" +msgstr "Kirjaudu sisään" -#: contrib/admin/templates/admin/object_history.html:36 -msgid "" -"This object doesn't have a change history. It probably wasn't added via this " -"admin site." -msgstr "Tällä kohteella ei ole muutoshistoriaa. Sitä ei ole lisätty tämän ylläpitosivun avulla." +#: contrib/admin/templates/admin/change_list.html:12 +#, python-format +msgid "Add %(name)s" +msgstr "Lisää uusi %(name)s" -#: contrib/admin/templates/admin/500.html:4 -msgid "Server error" -msgstr "Palvelinvirhe" +#: contrib/admin/templates/admin/submit_line.html:4 +msgid "Save as new" +msgstr "Tallenna uutena" -#: contrib/admin/templates/admin/500.html:6 -msgid "Server error (500)" -msgstr "Palvelinvirhe (500)" +#: contrib/admin/templates/admin/submit_line.html:5 +msgid "Save and add another" +msgstr "Tallenna ja lisää seuraava" -#: contrib/admin/templates/admin/500.html:9 -msgid "Server Error <em>(500)</em>" -msgstr "Palvelinvirhe <em>(500)</em>" +#: contrib/admin/templates/admin/submit_line.html:6 +msgid "Save and continue editing" +msgstr "Tallenna välillä ja jatka muokkaamista" -#: contrib/admin/templates/admin/invalid_setup.html:8 -msgid "" -"Something's wrong with your database installation. Make sure the appropriate " -"database tables have been created, and make sure the database is readable by " -"the appropriate user." -msgstr "Tietokanta-asennuksessasi on jotain vialla. Varmistu, että sopivat taulut on luotu ja että oikea käyttäjä voi lukea tietokantaa." +#: contrib/admin/templates/admin/submit_line.html:7 +msgid "Save" +msgstr "Tallenna ja poistu" #: contrib/admin/templates/admin/search_form.html:8 msgid "Go" @@ -1143,105 +1505,95 @@ msgstr[1] "%(counter)s hakutulosta" msgid "%(full_result_count)s total" msgstr "yhteensä %(full_result_count)s" -#: contrib/admin/templates/admin/filters.html:4 -msgid "Filter" -msgstr "Suodatin" +#: contrib/admin/templates/admin/change_form.html:22 +msgid "View on site" +msgstr "Näytä lopputulos" -#: contrib/admin/templates/admin/login.html:17 -#: contrib/comments/templates/comments/form.html:6 -#: contrib/comments/templates/comments/form.html:8 -msgid "Username:" -msgstr "Käyttäjätunnus" +#: contrib/admin/templates/admin/change_form.html:32 +#: contrib/admin/templates/admin/auth/user/change_password.html:24 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "Korjaa virhe." +msgstr[1] "Korjaa virheet." -#: contrib/admin/templates/admin/login.html:20 -#: contrib/comments/templates/comments/form.html:8 -msgid "Password:" -msgstr "Salasana:" +#: contrib/admin/templates/admin/change_form.html:50 +msgid "Ordering" +msgstr "Järjestys" -#: contrib/admin/templates/admin/login.html:22 -msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?" -msgstr "Oletko <a href=\"/password_reset\">unohtanut salasanasi</a>?" +#: contrib/admin/templates/admin/change_form.html:53 +msgid "Order:" +msgstr "Järjestysnumero:" -#: contrib/admin/templates/admin/base.html:24 -msgid "Welcome," -msgstr "Tervetuloa," +#: contrib/admin/templates/admin/pagination.html:10 +msgid "Show all" +msgstr "Näytä kaikki" + +#: contrib/admin/templates/admin/404.html:4 +#: contrib/admin/templates/admin/404.html:8 +msgid "Page not found" +msgstr "Sivua ei löydy" + +#: contrib/admin/templates/admin/404.html:10 +msgid "We're sorry, but the requested page could not be found." +msgstr "Pahoittelemme, pyydettyä sivua ei voitu löytää." + +#: contrib/admin/templates/admin/base_site.html:4 +msgid "Django site admin" +msgstr "Django-sivuston ylläpito" + +#: contrib/admin/templates/admin/base_site.html:7 +msgid "Django administration" +msgstr "Djangon ylläpito" + +#: contrib/admin/templates/admin/500.html:4 +msgid "Server error" +msgstr "Palvelinvirhe" + +#: contrib/admin/templates/admin/500.html:6 +msgid "Server error (500)" +msgstr "Palvelinvirhe (500)" + +#: contrib/admin/templates/admin/500.html:9 +msgid "Server Error <em>(500)</em>" +msgstr "Palvelinvirhe <em>(500)</em>" + +#: contrib/admin/templates/admin/500.html:10 +msgid "" +"There's been an error. It's been reported to the site administrators via e-" +"mail and should be fixed shortly. Thanks for your patience." +msgstr "Palvelimella on tapahtunut virhe. Se on ilmoitettu sivuston ylläpitäjille sähköpostilla ja korjataan pian. Kiitämme kärsivällisyydestä." #: contrib/admin/templates/admin/auth/user/add_form.html:6 msgid "" "First, enter a username and password. Then, you'll be able to edit more user " "options." -msgstr "Syötä ensin käyttäjätunnus ja salasana. Sen jälkeen voit muokata muita käyttäjän tietoja." +msgstr "" +"Syötä ensin käyttäjätunnus ja salasana. Sen jälkeen voit muokata muita " +"käyttäjän tietoja." #: contrib/admin/templates/admin/auth/user/add_form.html:12 msgid "Username" msgstr "Käyttäjätunnus" #: contrib/admin/templates/admin/auth/user/add_form.html:18 +#: contrib/admin/templates/admin/auth/user/change_password.html:34 msgid "Password" -msgstr "Salasana:" +msgstr "Salasana" #: contrib/admin/templates/admin/auth/user/add_form.html:23 +#: contrib/admin/templates/admin/auth/user/change_password.html:39 msgid "Password (again)" msgstr "Salasana toistamiseen" #: contrib/admin/templates/admin/auth/user/add_form.html:24 +#: contrib/admin/templates/admin/auth/user/change_password.html:40 msgid "Enter the same password as above, for verification." msgstr "Syötä sama salasana tarkistuksen vuoksi toistamiseen." -#: contrib/admin/templates/admin_doc/bookmarklets.html:3 -msgid "Bookmarklets" -msgstr "Kirjanmerkkiset" - -#: contrib/admin/templates/admin_doc/bookmarklets.html:5 -msgid "Documentation bookmarklets" -msgstr "Ohjeiden kirjanmerkkiset" - -#: contrib/admin/templates/admin_doc/bookmarklets.html:9 -msgid "" -"\n" -"<p class=\"help\">To install bookmarklets, drag the link to your bookmarks\n" -"toolbar, or right-click the link and add it to your bookmarks. Now you can\n" -"select the bookmarklet from any page in the site. Note that some of these\n" -"bookmarklets require you to be viewing the site from a computer designated\n" -"as \"internal\" (talk to your system administrator if you aren't sure if\n" -"your computer is \"internal\").</p>\n" -msgstr "\n<p class=\"help\">Asenna kirjanmerkkinen raahaamalla linkki kirjanmerkkien työkalupalkkiin tai napsauttamalla linkkiä oikeanpuoleisella hiiren painikkeella ja valitsemalla kirjanmerkkeihin lisäämisen. Sen jälkeen voit valita kirjanmerkkisen miltä tahansa sivuston sivulta. Huomaa, että jotkin näistä kirjanmerkkisistä toimivat vain, jos selaat sivustoa \"paikalliseksi\" määritellyltä tietokoneelta (kysy lisätietoja verkkonne ylläpitäjältä).</p>\n" - -#: contrib/admin/templates/admin_doc/bookmarklets.html:19 -msgid "Documentation for this page" -msgstr "Tämän sivun ohjeita" - -#: contrib/admin/templates/admin_doc/bookmarklets.html:20 -msgid "" -"Jumps you from any page to the documentation for the view that generates " -"that page." -msgstr "Vie avoinna olevan sivun luoneen näkymän ohjeisiin." - -#: contrib/admin/templates/admin_doc/bookmarklets.html:22 -msgid "Show object ID" -msgstr "Näytä kohteen tunniste" - -#: contrib/admin/templates/admin_doc/bookmarklets.html:23 -msgid "" -"Shows the content-type and unique ID for pages that represent a single " -"object." -msgstr "Näyttää yksittäistä kohdetta vastaavilla sivuilla kohteen tyypin ja tunnisteen." - -#: contrib/admin/templates/admin_doc/bookmarklets.html:25 -msgid "Edit this object (current window)" -msgstr "Muokkaa tätä kohdetta (tässä ikkunassa)" - -#: contrib/admin/templates/admin_doc/bookmarklets.html:26 -msgid "Jumps to the admin page for pages that represent a single object." -msgstr "Siirtyy yksittäistä kohdetta vastaavalta sivulta kohteen ylläpitosivulle." - -#: contrib/admin/templates/admin_doc/bookmarklets.html:28 -msgid "Edit this object (new window)" -msgstr "Muokkaa tätä kohdetta (uudessa ikkunassa)" - -#: contrib/admin/templates/admin_doc/bookmarklets.html:29 -msgid "As above, but opens the admin page in a new window." -msgstr "Kuten yllä, mutta avaa ylläpitosivun uuteen ikkunaan." +#: contrib/admin/templates/admin/auth/user/change_password.html:28 +#, python-format +msgid "Enter a new password for the user <strong>%(username)s</strong>." +msgstr "Syötä käyttäjän <strong>%(username)s</strong> uusi salasana." #: contrib/admin/templates/widget/date_time.html:3 msgid "Date:" @@ -1259,136 +1611,456 @@ msgstr "Tällä hetkellä:" msgid "Change:" msgstr "Muokkaa:" -#: contrib/admin/templates/registration/password_reset_form.html:4 -#: contrib/admin/templates/registration/password_reset_form.html:6 -#: contrib/admin/templates/registration/password_reset_form.html:10 -#: contrib/admin/templates/registration/password_reset_done.html:4 -msgid "Password reset" -msgstr "Salasanan nollaus" +#: contrib/admin/views/auth.py:20 contrib/admin/views/main.py:264 +#, python-format +msgid "The %(name)s \"%(obj)s\" was added successfully." +msgstr "%(name)s \"%(obj)s\" on nyt lisätty." -#: contrib/admin/templates/registration/password_reset_form.html:12 +#: contrib/admin/views/auth.py:25 contrib/admin/views/main.py:268 +#: contrib/admin/views/main.py:354 +msgid "You may edit it again below." +msgstr "Voit muokata sitä uudelleen alla." + +#: contrib/admin/views/auth.py:31 +msgid "Add user" +msgstr "Uusi käyttäjä" + +#: contrib/admin/views/auth.py:58 +msgid "Password changed successfully." +msgstr "Salasanan muuttaminen onnistui." + +#: contrib/admin/views/auth.py:65 +#, python-format +msgid "Change password: %s" +msgstr "Vaihda salasana: %s" + +#: contrib/admin/views/doc.py:47 contrib/admin/views/doc.py:49 +#: contrib/admin/views/doc.py:51 +msgid "tag:" +msgstr "tag:" + +#: contrib/admin/views/doc.py:78 contrib/admin/views/doc.py:80 +#: contrib/admin/views/doc.py:82 +msgid "filter:" +msgstr "suodatin:" + +#: contrib/admin/views/doc.py:136 contrib/admin/views/doc.py:138 +#: contrib/admin/views/doc.py:140 +msgid "view:" +msgstr "view:" + +#: contrib/admin/views/doc.py:165 +#, python-format +msgid "App %r not found" +msgstr "Sovellusta %r ei löydy" + +#: contrib/admin/views/doc.py:172 +#, python-format +msgid "Model %(name)r not found in app %(label)r" +msgstr "Sovelluksesta %(label)r ei löydy mallia %(name)r" + +#: contrib/admin/views/doc.py:184 +#, python-format +msgid "the related `%(label)s.%(type)s` object" +msgstr "tähän liittyvä `%(label)s.%(type)s`-kohde" + +#: contrib/admin/views/doc.py:184 contrib/admin/views/doc.py:206 +#: contrib/admin/views/doc.py:220 contrib/admin/views/doc.py:225 +msgid "model:" +msgstr "malli:" + +#: contrib/admin/views/doc.py:215 +#, python-format +msgid "related `%(label)s.%(name)s` objects" +msgstr "tähän liittyvät `%(label)s.%(name)s`-kohteet" + +#: contrib/admin/views/doc.py:220 +#, python-format +msgid "all %s" +msgstr "kaikki %s" + +#: contrib/admin/views/doc.py:225 +#, python-format +msgid "number of %s" +msgstr "%s-kohteiden lukumäärä" + +#: contrib/admin/views/doc.py:230 +#, python-format +msgid "Fields on %s objects" +msgstr "%s-kohteiden kentät" + +#: contrib/admin/views/doc.py:292 contrib/admin/views/doc.py:303 +#: contrib/admin/views/doc.py:305 contrib/admin/views/doc.py:311 +#: contrib/admin/views/doc.py:312 contrib/admin/views/doc.py:314 +msgid "Integer" +msgstr "Kokonaisluku" + +#: contrib/admin/views/doc.py:293 +msgid "Boolean (Either True or False)" +msgstr "Totuusarvo: joko tosi (True) tai epätosi (False)" + +#: contrib/admin/views/doc.py:294 contrib/admin/views/doc.py:313 +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Merkkijono (enintään %(max_length)s merkkiä)" + +#: contrib/admin/views/doc.py:295 +msgid "Comma-separated integers" +msgstr "Pilkulla erotetut kokonaisluvut" + +#: contrib/admin/views/doc.py:296 +msgid "Date (without time)" +msgstr "Päivämäärä" + +#: contrib/admin/views/doc.py:297 +msgid "Date (with time)" +msgstr "Päivämäärä ja kellonaika" + +#: contrib/admin/views/doc.py:298 +msgid "Decimal number" +msgstr "Desimaaliluku" + +#: contrib/admin/views/doc.py:299 +msgid "E-mail address" +msgstr "Sähköpostios." + +#: contrib/admin/views/doc.py:300 contrib/admin/views/doc.py:301 +#: contrib/admin/views/doc.py:304 +msgid "File path" +msgstr "Tiedostopolku" + +#: contrib/admin/views/doc.py:302 +msgid "Floating point number" +msgstr "Liukuluku" + +#: contrib/admin/views/doc.py:308 +msgid "Boolean (Either True, False or None)" +msgstr "Totuusarvo: joko tosi (True), epätosi (False) tai ei mikään (None)" + +#: contrib/admin/views/doc.py:309 +msgid "Relation to parent model" +msgstr "Relaatio emomalliin" + +#: contrib/admin/views/doc.py:310 +msgid "Phone number" +msgstr "Puhelinnumero" + +#: contrib/admin/views/doc.py:315 +msgid "Text" +msgstr "Tekstiä" + +#: contrib/admin/views/doc.py:316 +msgid "Time" +msgstr "Kellonaika" + +#: contrib/admin/views/doc.py:317 contrib/flatpages/models.py:7 +msgid "URL" +msgstr "URL-osoite" + +#: contrib/admin/views/doc.py:318 +msgid "U.S. state (two uppercase letters)" +msgstr "USA:n osavaltio (kaksikirjaiminen versaalein)" + +#: contrib/admin/views/doc.py:319 +msgid "XML text" +msgstr "XML-teksti" + +#: contrib/admin/views/doc.py:345 +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s ei näytä urlpattern-objektilta" + +#: contrib/admin/views/main.py:230 +msgid "Site administration" +msgstr "Sivuston ylläpito" + +#: contrib/admin/views/main.py:278 contrib/admin/views/main.py:363 +#, python-format +msgid "You may add another %s below." +msgstr "Uusi %s on lisättävissä alla." + +#: contrib/admin/views/main.py:296 +#, python-format +msgid "Add %s" +msgstr "Uusi %s" + +#: contrib/admin/views/main.py:342 +#, python-format +msgid "Added %s." +msgstr "Lisätty %s." + +#: contrib/admin/views/main.py:344 +#, python-format +msgid "Changed %s." +msgstr "Muokattu: %s." + +#: contrib/admin/views/main.py:346 +#, python-format +msgid "Deleted %s." +msgstr "Poistettu %s." + +#: contrib/admin/views/main.py:349 +msgid "No fields changed." +msgstr "Ei muutoksia kenttiin." + +#: contrib/admin/views/main.py:352 +#, python-format +msgid "The %(name)s \"%(obj)s\" was changed successfully." +msgstr "%(name)s \"%(obj)s\" on nyt muutettu." + +#: contrib/admin/views/main.py:360 +#, python-format msgid "" -"Forgotten your password? Enter your e-mail address below, and we'll reset " -"your password and e-mail the new one to you." -msgstr "" -"Unohditko salasanasi? Syötä alle sähköpostiosoitteesi, niin \n" -"lähetämme sinulle uuden salasanan." +"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below." +msgstr "%(name)s \"%(obj)s\" on nyt lisätty. Voit muokata sitä uudelleen alla." -#: contrib/admin/templates/registration/password_reset_form.html:16 -msgid "E-mail address:" -msgstr "Sähköpostiosoite:" +#: contrib/admin/views/main.py:398 +#, python-format +msgid "Change %s" +msgstr "Muokkaa: %s" -#: contrib/admin/templates/registration/password_reset_form.html:16 -msgid "Reset my password" -msgstr "Nollaa salasana" +#: contrib/admin/views/main.py:483 +#, python-format +msgid "One or more %(fieldname)s in %(name)s: %(obj)s" +msgstr "Yksi tai useampi %(fieldname)s kohteessa %(name)s: %(obj)s" -#: contrib/admin/templates/registration/password_reset_email.html:2 -msgid "You're receiving this e-mail because you requested a password reset" -msgstr "Sait tämän viestin, koska pyysit uutta salasanaa" +#: contrib/admin/views/main.py:488 +#, python-format +msgid "One or more %(fieldname)s in %(name)s:" +msgstr "Yksi tai useampi %(fieldname)s kohteessa %(name)s:" -#: contrib/admin/templates/registration/password_reset_email.html:3 +#: contrib/admin/views/main.py:520 #, python-format -msgid "for your user account at %(site_name)s" -msgstr "sivuston %(site_name)s käyttäjätilillesi" +msgid "The %(name)s \"%(obj)s\" was deleted successfully." +msgstr "%(name)s \"%(obj)s\" on poistettu." -#: contrib/admin/templates/registration/password_reset_email.html:5 +#: contrib/admin/views/main.py:523 +msgid "Are you sure?" +msgstr "Oletko varma?" + +#: contrib/admin/views/main.py:545 #, python-format -msgid "Your new password is: %(new_password)s" -msgstr "Uusi salasanasi on: %(new_password)s" +msgid "Change history: %s" +msgstr "Muokkaushistoria: %s" -#: contrib/admin/templates/registration/password_reset_email.html:7 -msgid "Feel free to change this password by going to this page:" -msgstr "Voit vaihtaa salasanan sivulla:" +#: contrib/admin/views/main.py:579 +#, python-format +msgid "Select %s" +msgstr "Valitse %s" -#: contrib/admin/templates/registration/password_reset_email.html:11 -msgid "Your username, in case you've forgotten:" -msgstr "Käyttäjätunnuksesi siltä varalta, että olet unohtanut sen:" +#: contrib/admin/views/main.py:579 +#, python-format +msgid "Select %s to change" +msgstr "Valitse muokattava %s" -#: contrib/admin/templates/registration/password_reset_email.html:13 -msgid "Thanks for using our site!" -msgstr "Kiitos vierailustasi sivuillemme!" +#: contrib/admin/views/main.py:780 +msgid "Database error" +msgstr "Tietokantavirhe" -#: contrib/admin/templates/registration/password_reset_email.html:15 +#: contrib/admin/views/decorators.py:10 contrib/auth/forms.py:60 +msgid "" +"Please enter a correct username and password. Note that both fields are case-" +"sensitive." +msgstr "" +"Käyttäjätunnus tai salasana ei kelpaa. Huomaa, että isot ja pienet kirjaimet " +"ovat merkitseviä." + +#: contrib/admin/views/decorators.py:62 +msgid "" +"Please log in again, because your session has expired. Don't worry: Your " +"submission has been saved." +msgstr "" +"Kirjaudu uudelleen sisään, koska istuntosi on mennyt umpeen. Muutoksesi ovat " +"silti tallessa." + +#: contrib/admin/views/decorators.py:69 +msgid "" +"Looks like your browser isn't configured to accept cookies. Please enable " +"cookies, reload this page, and try again." +msgstr "" +"Selaimesi ei salli evästeitä. Muuta asetukset sallimaan evästeet, lataa tämä " +"sivu uudelleen ja yritä toistamiseen." + +#: contrib/admin/views/decorators.py:83 +msgid "Usernames cannot contain the '@' character." +msgstr "Käyttäjätunnuksessa ei saa olla '@'-merkkiä." + +#: contrib/admin/views/decorators.py:85 #, python-format -msgid "The %(site_name)s team" -msgstr "%(site_name)s ylläpitäjät" +msgid "Your e-mail address is not your username. Try '%s' instead." +msgstr "Käyttäjätunnus ei ole sama kuin sähköpostiosoite. Kokeile '%s'." -#: contrib/admin/templates/registration/logged_out.html:8 -msgid "Thanks for spending some quality time with the Web site today." -msgstr "Kiitos sivuillamme viettämästäsi ajasta." +#: contrib/auth/views.py:47 +msgid "Logged out" +msgstr "Kirjautunut ulos" -#: contrib/admin/templates/registration/logged_out.html:10 -msgid "Log in again" -msgstr "Kirjaudu uudelleen sisään" +#: contrib/auth/models.py:53 contrib/auth/models.py:73 +msgid "name" +msgstr "nimi" -#: contrib/admin/templates/registration/password_reset_done.html:6 -#: contrib/admin/templates/registration/password_reset_done.html:10 -msgid "Password reset successful" -msgstr "Salasanan nollaus onnistui" +#: contrib/auth/models.py:55 +msgid "codename" +msgstr "koodinimi" -#: contrib/admin/templates/registration/password_reset_done.html:12 +#: contrib/auth/models.py:58 +msgid "permission" +msgstr "oikeus" + +#: contrib/auth/models.py:59 contrib/auth/models.py:74 +msgid "permissions" +msgstr "oikeudet" + +#: contrib/auth/models.py:77 +msgid "group" +msgstr "ryhmä" + +#: contrib/auth/models.py:78 contrib/auth/models.py:121 +msgid "groups" +msgstr "ryhmät" + +#: contrib/auth/models.py:111 +msgid "username" +msgstr "tunnus" + +#: contrib/auth/models.py:111 msgid "" -"We've e-mailed a new password to the e-mail address you submitted. You " -"should be receiving it shortly." +"Required. 30 characters or fewer. Alphanumeric characters only (letters, " +"digits and underscores)." msgstr "" -"Uusi salasanasi on lähetetty antamaasi sähköpostiosoitteeseen.\n" -"Se saapuu tuota pikaa." +" Vaaditaan. Enintään 30 kirjanta (a-z), numeroa (0-9) tai alaviivaa (_)." -#: contrib/admin/templates/registration/password_change_form.html:4 -#: contrib/admin/templates/registration/password_change_form.html:6 -#: contrib/admin/templates/registration/password_change_form.html:10 -#: contrib/admin/templates/registration/password_change_done.html:4 -msgid "Password change" -msgstr "Salasanan muuttaminen" +#: contrib/auth/models.py:112 +msgid "first name" +msgstr "etunimi" -#: contrib/admin/templates/registration/password_change_form.html:12 +#: contrib/auth/models.py:113 +msgid "last name" +msgstr "sukunimi" + +#: contrib/auth/models.py:114 +msgid "e-mail address" +msgstr "sähköposti" + +#: contrib/auth/models.py:115 +msgid "password" +msgstr "salasana" + +#: contrib/auth/models.py:115 msgid "" -"Please enter your old password, for security's sake, and then enter your new " -"password twice so we can verify you typed it in correctly." +"Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change " +"password form</a>." +msgstr "Syötä muodossa '[algo]$[suola]$[heksa-digest]' tai käytä <a href=\"password/\">muutoslomaketta</a>." + +#: contrib/auth/models.py:116 +msgid "staff status" +msgstr "ylläpitäjä" + +#: contrib/auth/models.py:116 +msgid "Designates whether the user can log into this admin site." +msgstr "Ylläpitäjillä on pääsy tähän sivuston ylläpito-osioon." + +#: contrib/auth/models.py:117 +msgid "active" +msgstr "voimassa" + +#: contrib/auth/models.py:117 +msgid "" +"Designates whether this user can log into the Django admin. Unselect this " +"instead of deleting accounts." msgstr "" -"Syötä vanha salasanasi varmistukseksi, ja syötä sitten uusi salasanasi\n" -"kaksi kertaa, jotta se tulee varmasti oikein." +"Määrää, voiko käyttäjä kirjautua sisään. Tällä voi estää käyttäjätilin " +"käytön poistamatta sitä." -#: contrib/admin/templates/registration/password_change_form.html:17 -msgid "Old password:" -msgstr "Vanha salasana:" +#: contrib/auth/models.py:118 +msgid "superuser status" +msgstr "pääkäyttäjä" -#: contrib/admin/templates/registration/password_change_form.html:19 -msgid "New password:" -msgstr "Uusi salasana:" +#: contrib/auth/models.py:118 +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Antaa käyttäjälle kaikki oikeudet ilman, että niitä täytyy erikseen luetella." -#: contrib/admin/templates/registration/password_change_form.html:21 -msgid "Confirm password:" -msgstr "Varmista uusi salasana:" +#: contrib/auth/models.py:119 +msgid "last login" +msgstr "viimeksi kirjautunut" -#: contrib/admin/templates/registration/password_change_form.html:23 -msgid "Change my password" -msgstr "Vaihda salasana" +#: contrib/auth/models.py:120 +msgid "date joined" +msgstr "liittynyt" -#: contrib/admin/templates/registration/password_change_done.html:6 -#: contrib/admin/templates/registration/password_change_done.html:10 -msgid "Password change successful" -msgstr "Salasanan muuttaminen onnistui" +#: contrib/auth/models.py:122 +msgid "" +"In addition to the permissions manually assigned, this user will also get " +"all permissions granted to each group he/she is in." +msgstr "" +"Tässä valittujen oikeuksien lisäksi käyttäjä saa myös kaikki niiden ryhmien " +"oikeudet, joiden jäsen hän on." -#: contrib/admin/templates/registration/password_change_done.html:12 -msgid "Your password was changed." -msgstr "Salasanasi on muutettu." +#: contrib/auth/models.py:123 +msgid "user permissions" +msgstr "käyttäjän oikeudet" -#: contrib/sites/models.py:10 -msgid "domain name" -msgstr "domain-nimi" +#: contrib/auth/models.py:127 +msgid "user" +msgstr "käyttäjä" -#: contrib/sites/models.py:11 -msgid "display name" -msgstr "näyttönimi" +#: contrib/auth/models.py:128 +msgid "users" +msgstr "käyttäjät" -#: contrib/sites/models.py:15 -msgid "site" -msgstr "sivusto" +#: contrib/auth/models.py:134 +msgid "Personal info" +msgstr "Henkilökohtaiset tiedot" -#: contrib/sites/models.py:16 -msgid "sites" -msgstr "sivustot" +#: contrib/auth/models.py:135 +msgid "Permissions" +msgstr "Oikeudet" + +#: contrib/auth/models.py:136 +msgid "Important dates" +msgstr "Tärkeät päivämäärät" + +#: contrib/auth/models.py:137 +msgid "Groups" +msgstr "Ryhmät" + +#: contrib/auth/models.py:288 +msgid "message" +msgstr "viesti" + +#: contrib/auth/forms.py:17 contrib/auth/forms.py:138 +msgid "The two password fields didn't match." +msgstr "Salasanat eivät täsmää." + +#: contrib/auth/forms.py:25 +msgid "A user with that username already exists." +msgstr "Käyttäjätunnus on jo rekisteröity." + +#: contrib/auth/forms.py:53 +msgid "" +"Your Web browser doesn't appear to have cookies enabled. Cookies are " +"required for logging in." +msgstr "Selaimesi ei salli evästeitä. Sisäänkirjautuminen vaatii evästeen." + +#: contrib/auth/forms.py:62 +msgid "This account is inactive." +msgstr "Tämä käyttäjätili ei ole voimassa." + +#: contrib/auth/forms.py:84 +msgid "" +"That e-mail address doesn't have an associated user account. Are you sure " +"you've registered?" +msgstr "Sähköpostiosoitetta vastaavaa käyttäjätunnusta ei löydy. Oletko varmasti jo rekisteröitynyt?" + +#: contrib/auth/forms.py:117 +msgid "The two 'new password' fields didn't match." +msgstr "Salasanat eivät täsmää." + +#: contrib/auth/forms.py:124 +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Vanha salasana on virheellinen. Yritä uudelleen." #: contrib/flatpages/models.py:8 msgid "" @@ -1417,7 +2089,9 @@ msgstr "mallipohjan nimi" msgid "" "Example: 'flatpages/contact_page.html'. If this isn't provided, the system " "will use 'flatpages/default.html'." -msgstr "Esimerkiksi: 'flatpages/yhteydenotto.html'. Jos tämä jätetään tyhjäksi, käytetään oletuspohjaa 'flatpages/default.html'." +msgstr "" +"Esimerkiksi: 'flatpages/yhteydenotto.html'. Jos tämä jätetään tyhjäksi, " +"käytetään oletuspohjaa 'flatpages/default.html'." #: contrib/flatpages/models.py:14 msgid "registration required" @@ -1425,7 +2099,8 @@ msgstr "vaaditaan rekisteröityminen" #: contrib/flatpages/models.py:14 msgid "If this is checked, only logged-in users will be able to view the page." -msgstr "Jos tämä kohta on valittu, vain sisäänkirjautuneet käyttäjät näkevät sivun." +msgstr "" +"Jos tämä kohta on valittu, vain sisäänkirjautuneet käyttäjät näkevät sivun." #: contrib/flatpages/models.py:18 msgid "flat page" @@ -1435,393 +2110,1022 @@ msgstr "tekstisivu" msgid "flat pages" msgstr "tekstisivut" -#: contrib/redirects/models.py:7 -msgid "redirect from" -msgstr "ohjaa osoitteesta" +#: contrib/localflavor/sk/sk_regions.py:8 +msgid "Banska Bystrica region" +msgstr "Banská Bystrican aule" -#: contrib/redirects/models.py:8 +#: contrib/localflavor/sk/sk_regions.py:9 +msgid "Bratislava region" +msgstr "Bratislavan alue" + +#: contrib/localflavor/sk/sk_regions.py:10 +msgid "Kosice region" +msgstr "Košicen alue" + +#: contrib/localflavor/sk/sk_regions.py:11 +msgid "Nitra region" +msgstr "Nitran alue" + +#: contrib/localflavor/sk/sk_regions.py:12 +msgid "Presov region" +msgstr "Prešovin alue" + +#: contrib/localflavor/sk/sk_regions.py:13 +msgid "Trencin region" +msgstr "Trenčínin alue" + +#: contrib/localflavor/sk/sk_regions.py:14 +msgid "Trnava region" +msgstr "Trnava region" + +#: contrib/localflavor/sk/sk_regions.py:15 +msgid "Zilina region" +msgstr "Zilina region" + +#: contrib/localflavor/sk/forms.py:32 +msgid "Enter a postal code in the format XXXXX or XXX XX." +msgstr "Syötä postinumero muodossa XXXXX tai XXX XX." + +#: contrib/localflavor/sk/sk_districts.py:8 +msgid "Banska Bystrica" +msgstr "Banska Bystrica" + +#: contrib/localflavor/sk/sk_districts.py:9 +msgid "Banska Stiavnica" +msgstr "Banska Stiavnica" + +#: contrib/localflavor/sk/sk_districts.py:10 +msgid "Bardejov" +msgstr "Bardejov" + +#: contrib/localflavor/sk/sk_districts.py:11 +msgid "Banovce nad Bebravou" +msgstr "Banovce nad Bebravou" + +#: contrib/localflavor/sk/sk_districts.py:12 +msgid "Brezno" +msgstr "Brezno" + +#: contrib/localflavor/sk/sk_districts.py:13 +msgid "Bratislava I" +msgstr "Bratislava I" + +#: contrib/localflavor/sk/sk_districts.py:14 +msgid "Bratislava II" +msgstr "Bratislava II" + +#: contrib/localflavor/sk/sk_districts.py:15 +msgid "Bratislava III" +msgstr "Bratislava III" + +#: contrib/localflavor/sk/sk_districts.py:16 +msgid "Bratislava IV" +msgstr "Bratislava IV" + +#: contrib/localflavor/sk/sk_districts.py:17 +msgid "Bratislava V" +msgstr "Bratislava V" + +#: contrib/localflavor/sk/sk_districts.py:18 +msgid "Bytca" +msgstr "Bytca" + +#: contrib/localflavor/sk/sk_districts.py:19 +msgid "Cadca" +msgstr "Cadca" + +#: contrib/localflavor/sk/sk_districts.py:20 +msgid "Detva" +msgstr "Detva" + +#: contrib/localflavor/sk/sk_districts.py:21 +msgid "Dolny Kubin" +msgstr "Dolny Kubin" + +#: contrib/localflavor/sk/sk_districts.py:22 +msgid "Dunajska Streda" +msgstr "Dunajska Streda" + +#: contrib/localflavor/sk/sk_districts.py:23 +msgid "Galanta" +msgstr "Galanta" + +#: contrib/localflavor/sk/sk_districts.py:24 +msgid "Gelnica" +msgstr "Gelnica" + +#: contrib/localflavor/sk/sk_districts.py:25 +msgid "Hlohovec" +msgstr "Hlohovec" + +#: contrib/localflavor/sk/sk_districts.py:26 +msgid "Humenne" +msgstr "Humenne" + +#: contrib/localflavor/sk/sk_districts.py:27 +msgid "Ilava" +msgstr "Ilava" + +#: contrib/localflavor/sk/sk_districts.py:28 +msgid "Kezmarok" +msgstr "Kezmarok" + +#: contrib/localflavor/sk/sk_districts.py:29 +msgid "Komarno" +msgstr "Komarno" + +#: contrib/localflavor/sk/sk_districts.py:30 +msgid "Kosice I" +msgstr "Kosice I" + +#: contrib/localflavor/sk/sk_districts.py:31 +msgid "Kosice II" +msgstr "Kosice II" + +#: contrib/localflavor/sk/sk_districts.py:32 +msgid "Kosice III" +msgstr "Kosice III" + +#: contrib/localflavor/sk/sk_districts.py:33 +msgid "Kosice IV" +msgstr "Kosice IV" + +#: contrib/localflavor/sk/sk_districts.py:34 +msgid "Kosice - okolie" +msgstr "Kosice - okolie" + +#: contrib/localflavor/sk/sk_districts.py:35 +msgid "Krupina" +msgstr "Krupina" + +#: contrib/localflavor/sk/sk_districts.py:36 +msgid "Kysucke Nove Mesto" +msgstr "Kysucke Nove Mesto" + +#: contrib/localflavor/sk/sk_districts.py:37 +msgid "Levice" +msgstr "Levice" + +#: contrib/localflavor/sk/sk_districts.py:38 +msgid "Levoca" +msgstr "Levoca" + +#: contrib/localflavor/sk/sk_districts.py:39 +msgid "Liptovsky Mikulas" +msgstr "Liptovsky Mikulas" + +#: contrib/localflavor/sk/sk_districts.py:40 +msgid "Lucenec" +msgstr "Lucenec" + +#: contrib/localflavor/sk/sk_districts.py:41 +msgid "Malacky" +msgstr "Malacky" + +#: contrib/localflavor/sk/sk_districts.py:42 +msgid "Martin" +msgstr "Martin" + +#: contrib/localflavor/sk/sk_districts.py:43 +msgid "Medzilaborce" +msgstr "Medzilaborce" + +#: contrib/localflavor/sk/sk_districts.py:44 +msgid "Michalovce" +msgstr "Michalovce" + +#: contrib/localflavor/sk/sk_districts.py:45 +msgid "Myjava" +msgstr "Myjava" + +#: contrib/localflavor/sk/sk_districts.py:46 +msgid "Namestovo" +msgstr "Namestovo" + +#: contrib/localflavor/sk/sk_districts.py:47 +msgid "Nitra" +msgstr "Nitra" + +#: contrib/localflavor/sk/sk_districts.py:48 +msgid "Nove Mesto nad Vahom" +msgstr "Nove Mesto nad Vahom" + +#: contrib/localflavor/sk/sk_districts.py:49 +msgid "Nove Zamky" +msgstr "Nove Zamky" + +#: contrib/localflavor/sk/sk_districts.py:50 +msgid "Partizanske" +msgstr "Partizanske" + +#: contrib/localflavor/sk/sk_districts.py:51 +msgid "Pezinok" +msgstr "Pezinok" + +#: contrib/localflavor/sk/sk_districts.py:52 +msgid "Piestany" +msgstr "Piestany" + +#: contrib/localflavor/sk/sk_districts.py:53 +msgid "Poltar" +msgstr "Poltar" + +#: contrib/localflavor/sk/sk_districts.py:54 +msgid "Poprad" +msgstr "Poprad" + +#: contrib/localflavor/sk/sk_districts.py:55 +msgid "Povazska Bystrica" +msgstr "Povazska Bystrica" + +#: contrib/localflavor/sk/sk_districts.py:56 +msgid "Presov" +msgstr "Presov" + +#: contrib/localflavor/sk/sk_districts.py:57 +msgid "Prievidza" +msgstr "Prievidza" + +#: contrib/localflavor/sk/sk_districts.py:58 +msgid "Puchov" +msgstr "Puchov" + +#: contrib/localflavor/sk/sk_districts.py:59 +msgid "Revuca" +msgstr "Revuca" + +#: contrib/localflavor/sk/sk_districts.py:60 +msgid "Rimavska Sobota" +msgstr "Rimavska Sobota" + +#: contrib/localflavor/sk/sk_districts.py:61 +msgid "Roznava" +msgstr "Roznava" + +#: contrib/localflavor/sk/sk_districts.py:62 +msgid "Ruzomberok" +msgstr "Ruzomberok" + +#: contrib/localflavor/sk/sk_districts.py:63 +msgid "Sabinov" +msgstr "Sabinov" + +#: contrib/localflavor/sk/sk_districts.py:64 +msgid "Senec" +msgstr "Senec" + +#: contrib/localflavor/sk/sk_districts.py:65 +msgid "Senica" +msgstr "Senica" + +#: contrib/localflavor/sk/sk_districts.py:66 +msgid "Skalica" +msgstr "Skalica" + +#: contrib/localflavor/sk/sk_districts.py:67 +msgid "Snina" +msgstr "Snina" + +#: contrib/localflavor/sk/sk_districts.py:68 +msgid "Sobrance" +msgstr "Sobrance" + +#: contrib/localflavor/sk/sk_districts.py:69 +msgid "Spisska Nova Ves" +msgstr "Spisska Nova Ves" + +#: contrib/localflavor/sk/sk_districts.py:70 +msgid "Stara Lubovna" +msgstr "Stara Lubovna" + +#: contrib/localflavor/sk/sk_districts.py:71 +msgid "Stropkov" +msgstr "Stropkov" + +#: contrib/localflavor/sk/sk_districts.py:72 +msgid "Svidnik" +msgstr "Svidnik" + +#: contrib/localflavor/sk/sk_districts.py:73 +msgid "Sala" +msgstr "Sala" + +#: contrib/localflavor/sk/sk_districts.py:74 +msgid "Topolcany" +msgstr "Topolcany" + +#: contrib/localflavor/sk/sk_districts.py:75 +msgid "Trebisov" +msgstr "Trebisov" + +#: contrib/localflavor/sk/sk_districts.py:76 +msgid "Trencin" +msgstr "Trencin" + +#: contrib/localflavor/sk/sk_districts.py:77 +msgid "Trnava" +msgstr "Trnava" + +#: contrib/localflavor/sk/sk_districts.py:78 +msgid "Turcianske Teplice" +msgstr "Turcianske Teplice" + +#: contrib/localflavor/sk/sk_districts.py:79 +msgid "Tvrdosin" +msgstr "Tvrdosin" + +#: contrib/localflavor/sk/sk_districts.py:80 +msgid "Velky Krtis" +msgstr "Velky Krtis" + +#: contrib/localflavor/sk/sk_districts.py:81 +msgid "Vranov nad Toplou" +msgstr "Vranov nad Toplou" + +#: contrib/localflavor/sk/sk_districts.py:82 +msgid "Zlate Moravce" +msgstr "Zlate Moravce" + +#: contrib/localflavor/sk/sk_districts.py:83 +msgid "Zvolen" +msgstr "Zvolen" + +#: contrib/localflavor/sk/sk_districts.py:84 +msgid "Zarnovica" +msgstr "Zarnovica" + +#: contrib/localflavor/sk/sk_districts.py:85 +msgid "Ziar nad Hronom" +msgstr "Ziar nad Hronom" + +#: contrib/localflavor/sk/sk_districts.py:86 +msgid "Zilina" +msgstr "Zilina" + +#: contrib/localflavor/fr/forms.py:17 contrib/localflavor/fi/forms.py:14 +#: contrib/localflavor/de/forms.py:16 +msgid "Enter a zip code in the format XXXXX." +msgstr "Syötä postinumero muodossa XXXXX." + +#: contrib/localflavor/in_/forms.py:16 +msgid "Enter a zip code in the format XXXXXXX." +msgstr "Syötä postinumero muodossa XXXXXXX." + +#: contrib/localflavor/ch/forms.py:18 contrib/localflavor/no/forms.py:14 +msgid "Enter a zip code in the format XXXX." +msgstr "Syötä postinumero muodossa XXXX." + +#: contrib/localflavor/ch/forms.py:90 msgid "" -"This should be an absolute path, excluding the domain name. Example: '/" -"events/search/'." +"Enter a valid Swiss identity or passport card number in X1234567<0 or " +"1234567890 format." +msgstr "Enter a valid Swiss identity or passport card number in X1234567<0 or 1234567890 format." + +#: contrib/localflavor/ch/ch_states.py:5 +msgid "Aargau" +msgstr "Aargau" + +#: contrib/localflavor/ch/ch_states.py:6 +msgid "Appenzell Innerrhoden" +msgstr "Appenzell Innerrhoden" + +#: contrib/localflavor/ch/ch_states.py:7 +msgid "Appenzell Ausserrhoden" +msgstr "Appenzell Ausserrhoden" + +#: contrib/localflavor/ch/ch_states.py:8 +msgid "Basel-Stadt" +msgstr "Basel-Stadt" + +#: contrib/localflavor/ch/ch_states.py:9 +msgid "Basel-Land" +msgstr "Basel-Land" + +#: contrib/localflavor/ch/ch_states.py:10 +msgid "Berne" +msgstr "Berne" + +#: contrib/localflavor/ch/ch_states.py:11 +msgid "Fribourg" +msgstr "Fribourg" + +#: contrib/localflavor/ch/ch_states.py:12 +msgid "Geneva" +msgstr "Geneve" + +#: contrib/localflavor/ch/ch_states.py:13 +msgid "Glarus" +msgstr "Glarus" + +#: contrib/localflavor/ch/ch_states.py:14 +msgid "Graubuenden" +msgstr "Graubuenden" + +#: contrib/localflavor/ch/ch_states.py:15 +msgid "Jura" +msgstr "Jura" + +#: contrib/localflavor/ch/ch_states.py:16 +msgid "Lucerne" +msgstr "Lucerne" + +#: contrib/localflavor/ch/ch_states.py:17 +msgid "Neuchatel" +msgstr "Neuchatel" + +#: contrib/localflavor/ch/ch_states.py:18 +msgid "Nidwalden" +msgstr "Nidwalden" + +#: contrib/localflavor/ch/ch_states.py:19 +msgid "Obwalden" +msgstr "Obwalden" + +#: contrib/localflavor/ch/ch_states.py:20 +msgid "Schaffhausen" +msgstr "Schaffhausen" + +#: contrib/localflavor/ch/ch_states.py:21 +msgid "Schwyz" +msgstr "Schwyz" + +#: contrib/localflavor/ch/ch_states.py:22 +msgid "Solothurn" +msgstr "Solothurn" + +#: contrib/localflavor/ch/ch_states.py:23 +msgid "St. Gallen" +msgstr "St. Gallen" + +#: contrib/localflavor/ch/ch_states.py:24 +msgid "Thurgau" +msgstr "Thurgau" + +#: contrib/localflavor/ch/ch_states.py:25 +msgid "Ticino" +msgstr "Ticino" + +#: contrib/localflavor/ch/ch_states.py:26 +msgid "Uri" +msgstr "Uri" + +#: contrib/localflavor/ch/ch_states.py:27 +msgid "Valais" +msgstr "Valais" + +#: contrib/localflavor/ch/ch_states.py:28 +msgid "Vaud" +msgstr "Vaud" + +#: contrib/localflavor/ch/ch_states.py:29 +msgid "Zug" +msgstr "Zug" + +#: contrib/localflavor/ch/ch_states.py:30 +msgid "Zurich" +msgstr "Zürich" + +#: contrib/localflavor/fi/forms.py:40 contrib/localflavor/fi/forms.py:45 +msgid "Enter a valid Finnish social security number." +msgstr "Syötä oikea suomalainen henkilötunnus." + +#: contrib/localflavor/uk/forms.py:18 +msgid "Enter a postcode. A space is required between the two postcode parts." msgstr "" -"Tässä on käytettävä absoluuttista polkua ilman verkkotunnusta. Esimerkki: " -"'\\\n" -"events/search/'" -#: contrib/redirects/models.py:9 -msgid "redirect to" -msgstr "ohjaa osoitteeseen" +#: contrib/localflavor/au/forms.py:18 +msgid "Enter a 4 digit post code." +msgstr "Syötä nelinumeroinen postinumero." -#: contrib/redirects/models.py:10 +#: contrib/localflavor/br/forms.py:23 +msgid "Enter a zip code in the format XXXXX-XXX." +msgstr "Syötä postinumero muodossa XXXXX-XXX." + +#: contrib/localflavor/br/forms.py:35 +msgid "Phone numbers must be in XX-XXXX-XXXX format." +msgstr "Puhelinnumeron tulee olla muodossa XX-XXXX-XXXX." + +#: contrib/localflavor/br/forms.py:68 msgid "" -"This can be either an absolute path (as above) or a full URL starting with " -"'http://'." +"Select a valid brazilian state. That state is not one of the available " +"states." msgstr "" -"Tässä on käytettävä joko absoluuttista polkua (kuten yllä) tai täydellistä " -"'http://'-alkuista URL-osoitetta." -#: contrib/redirects/models.py:13 -msgid "redirect" -msgstr "edelleenohjaus" +#: contrib/localflavor/br/forms.py:103 contrib/localflavor/ar/forms.py:61 +msgid "This field requires only numbers." +msgstr "Tähän kenttään kelpaavat vain numerot." -#: contrib/redirects/models.py:14 -msgid "redirects" -msgstr "edelleenohjaukset" +#: contrib/localflavor/br/forms.py:105 +msgid "This field requires at most 11 digits or 14 characters." +msgstr "" -#: contrib/comments/models.py:67 contrib/comments/models.py:166 -msgid "object ID" -msgstr "kohteen tunniste" +#: contrib/localflavor/br/forms.py:115 +msgid "Invalid CPF number." +msgstr "" -#: contrib/comments/models.py:68 -msgid "headline" -msgstr "otsikko" +#: contrib/localflavor/br/forms.py:137 +msgid "This field requires at least 14 digits" +msgstr "Tähän kenttään vaaditaan ainakin 14 numeroa." -#: contrib/comments/models.py:69 contrib/comments/models.py:90 -#: contrib/comments/models.py:167 -msgid "comment" -msgstr "kommentti" +#: contrib/localflavor/br/forms.py:147 +msgid "Invalid CNPJ number." +msgstr "" -#: contrib/comments/models.py:70 -msgid "rating #1" -msgstr "1. pisteytys" +#: contrib/localflavor/de/de_states.py:5 +msgid "Baden-Wuerttemberg" +msgstr "" -#: contrib/comments/models.py:71 -msgid "rating #2" -msgstr "2. pisteytys" +#: contrib/localflavor/de/de_states.py:6 +msgid "Bavaria" +msgstr "" -#: contrib/comments/models.py:72 -msgid "rating #3" -msgstr "3. pisteytys" +#: contrib/localflavor/de/de_states.py:7 +msgid "Berlin" +msgstr "Berliini" -#: contrib/comments/models.py:73 -msgid "rating #4" -msgstr "4. pisteytys" +#: contrib/localflavor/de/de_states.py:8 +msgid "Brandenburg" +msgstr "" -#: contrib/comments/models.py:74 -msgid "rating #5" -msgstr "5. pisteytys" +#: contrib/localflavor/de/de_states.py:9 +msgid "Bremen" +msgstr "" -#: contrib/comments/models.py:75 -msgid "rating #6" -msgstr "6. pisteytys" +#: contrib/localflavor/de/de_states.py:10 +msgid "Hamburg" +msgstr "Hampuri" -#: contrib/comments/models.py:76 -msgid "rating #7" -msgstr "7. pisteytys" +#: contrib/localflavor/de/de_states.py:11 +msgid "Hessen" +msgstr "" -#: contrib/comments/models.py:77 -msgid "rating #8" -msgstr "8. pisteytys" +#: contrib/localflavor/de/de_states.py:12 +msgid "Mecklenburg-Western Pomerania" +msgstr "" -#: contrib/comments/models.py:82 -msgid "is valid rating" -msgstr "on sallittu pisteytys" +#: contrib/localflavor/de/de_states.py:13 +msgid "Lower Saxony" +msgstr "" -#: contrib/comments/models.py:83 contrib/comments/models.py:169 -msgid "date/time submitted" -msgstr "lähetyshetki" +#: contrib/localflavor/de/de_states.py:14 +msgid "North Rhine-Westphalia" +msgstr "" -#: contrib/comments/models.py:84 contrib/comments/models.py:170 -msgid "is public" -msgstr "on julkinen" +#: contrib/localflavor/de/de_states.py:15 +msgid "Rhineland-Palatinate" +msgstr "" -#: contrib/comments/models.py:86 -msgid "is removed" -msgstr "on poistettu" +#: contrib/localflavor/de/de_states.py:16 +msgid "Saarland" +msgstr "" -#: contrib/comments/models.py:86 +#: contrib/localflavor/de/de_states.py:17 +msgid "Saxony" +msgstr "" + +#: contrib/localflavor/de/de_states.py:18 +msgid "Saxony-Anhalt" +msgstr "" + +#: contrib/localflavor/de/de_states.py:19 +msgid "Schleswig-Holstein" +msgstr "" + +#: contrib/localflavor/de/de_states.py:20 +msgid "Thuringia" +msgstr "" + +#: contrib/localflavor/de/forms.py:60 msgid "" -"Check this box if the comment is inappropriate. A \"This comment has been " -"removed\" message will be displayed instead." +"Enter a valid German identity card number in XXXXXXXXXXX-XXXXXXX-XXXXXXX-X " +"format." msgstr "" -"Rastita jos kommentti on asiaankuulumaton. Kommentin tilalla näytetään\n" -"viesti \"Tämä kommentti on poistettu\"." -#: contrib/comments/models.py:91 -msgid "comments" -msgstr "kommentit" +#: contrib/localflavor/pl/forms.py:53 +msgid "National Identification Number consists of 11 digits." +msgstr "" -#: contrib/comments/models.py:131 contrib/comments/models.py:207 -msgid "Content object" -msgstr "Kommentoitu kohde" +#: contrib/localflavor/pl/forms.py:59 +msgid "Wrong checksum for the National Identification Number." +msgstr "" -#: contrib/comments/models.py:159 -#, python-format +#: contrib/localflavor/pl/forms.py:71 msgid "" -"Posted by %(user)s at %(date)s\n" -"\n" -"%(comment)s\n" -"\n" -"http://%(domain)s%(url)s" +"Enter a tax number field (NIP) in the format XXX-XXX-XX-XX or XX-XX-XXX-XXX." msgstr "" -" Kirjoittanut %(user)s, pvm %(date)s\\n\n" -" \\n\n" -" %(comment)s\\n\n" -" \\n\n" -" http://%(domain)s%(url)s" -#: contrib/comments/models.py:168 -msgid "person's name" -msgstr "henkilön nimi" +#: contrib/localflavor/pl/forms.py:82 +msgid "Enter a postal code in the format XX-XXX." +msgstr "Syötä postinumero muodossa XX-XXX." -#: contrib/comments/models.py:171 -msgid "ip address" -msgstr "IP-osoite" +#: contrib/localflavor/pl/pl_voivodeships.py:8 +msgid "Lower Silesia" +msgstr "" -#: contrib/comments/models.py:173 -msgid "approved by staff" -msgstr "ylläpidon hyväksymä" +#: contrib/localflavor/pl/pl_voivodeships.py:9 +msgid "Kuyavia-Pomerania" +msgstr "" -#: contrib/comments/models.py:176 -msgid "free comment" -msgstr "vapaa kommentti" +#: contrib/localflavor/pl/pl_voivodeships.py:10 +msgid "Lublin" +msgstr "" -#: contrib/comments/models.py:177 -msgid "free comments" -msgstr "vapaat kommentit" +#: contrib/localflavor/pl/pl_voivodeships.py:11 +msgid "Lubusz" +msgstr "" -#: contrib/comments/models.py:233 -msgid "score" -msgstr "pisteet" +#: contrib/localflavor/pl/pl_voivodeships.py:12 +msgid "Lodz" +msgstr "" -#: contrib/comments/models.py:234 -msgid "score date" -msgstr "pisteytyspäivä" +#: contrib/localflavor/pl/pl_voivodeships.py:13 +msgid "Lesser Poland" +msgstr "" -#: contrib/comments/models.py:237 -msgid "karma score" -msgstr "karma-pisteytys" +#: contrib/localflavor/pl/pl_voivodeships.py:14 +msgid "Masovia" +msgstr "" -#: contrib/comments/models.py:238 -msgid "karma scores" -msgstr "karma-pisteytykset" +#: contrib/localflavor/pl/pl_voivodeships.py:15 +msgid "Opole" +msgstr "" -#: contrib/comments/models.py:242 -#, python-format -msgid "%(score)d rating by %(user)s" -msgstr "%(score)d pistettä käyttäjältä %(user)s" +#: contrib/localflavor/pl/pl_voivodeships.py:16 +msgid "Subcarpatia" +msgstr "" -#: contrib/comments/models.py:258 -#, python-format +#: contrib/localflavor/pl/pl_voivodeships.py:17 +msgid "Podlasie" +msgstr "" + +#: contrib/localflavor/pl/pl_voivodeships.py:18 +msgid "Pomerania" +msgstr "" + +#: contrib/localflavor/pl/pl_voivodeships.py:19 +msgid "Silesia" +msgstr "" + +#: contrib/localflavor/pl/pl_voivodeships.py:20 +msgid "Swietokrzyskie" +msgstr "" + +#: contrib/localflavor/pl/pl_voivodeships.py:21 +msgid "Warmia-Masuria" +msgstr "" + +#: contrib/localflavor/pl/pl_voivodeships.py:22 +msgid "Greater Poland" +msgstr "" + +#: contrib/localflavor/pl/pl_voivodeships.py:23 +msgid "West Pomerania" +msgstr "" + +#: contrib/localflavor/it/forms.py:16 +msgid "Enter a valid zip code." +msgstr "Syötä oikea postinumero." + +#: contrib/localflavor/it/forms.py:41 +msgid "Enter a valid Social Security number." +msgstr "Syötä oikea henkilötunnus." + +#: contrib/localflavor/it/forms.py:68 +msgid "Enter a valid VAT number." +msgstr "Syötä oikea ALV-tunnus." + +#: contrib/localflavor/is_/forms.py:17 msgid "" -"This comment was flagged by %(user)s:\n" -"\n" -"%(text)s" +"Enter a valid Icelandic identification number. The format is XXXXXX-XXXX." msgstr "" -" %(user)s on merkinnyt tämän kommentin:\\n\n" -" \\n\n" -" %(text)s" -#: contrib/comments/models.py:265 -msgid "flag date" -msgstr "merkintäpäivä" +#: contrib/localflavor/is_/forms.py:31 +msgid "The Icelandic identification number is not valid." +msgstr "" -#: contrib/comments/models.py:268 -msgid "user flag" -msgstr "käyttäjän merkki" +#: contrib/localflavor/ar/forms.py:30 contrib/localflavor/ar/forms.py:38 +msgid "Enter a postal code in the format NNNN or ANNNNAAA." +msgstr "" -#: contrib/comments/models.py:269 -msgid "user flags" -msgstr "käyttäjien merkit" +#: contrib/localflavor/ar/forms.py:64 +msgid "This field requires 7 or 8 digits." +msgstr "Tähän kenttään vaaditaan 7 tai 8 numeroa." -#: contrib/comments/models.py:273 -#, python-format -msgid "Flag by %r" -msgstr "Käyttäjän %r merkki" +#: contrib/localflavor/ar/forms.py:75 +msgid "Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format." +msgstr "" -#: contrib/comments/models.py:278 -msgid "deletion date" -msgstr "poistamispäivä" +#: contrib/localflavor/ar/forms.py:88 +msgid "Invalid CUIT." +msgstr "Virheellinen CUIT." -#: contrib/comments/models.py:280 -msgid "moderator deletion" -msgstr "valvojan poisto" +#: contrib/localflavor/ca/forms.py:19 +msgid "Enter a postal code in the format XXX XXX." +msgstr "Syötä postinumero muodossa XXX XXX." -#: contrib/comments/models.py:281 -msgid "moderator deletions" -msgstr "valvojien poistot" +#: contrib/localflavor/ca/forms.py:81 +msgid "Enter a valid Canadian Social Insurance number in XXX-XXX-XXXX format." +msgstr "" -#: contrib/comments/models.py:285 -#, python-format -msgid "Moderator deletion by %r" -msgstr "Valvojan %r poisto" +#: contrib/localflavor/nl/forms.py:25 +msgid "Enter a valid postal code" +msgstr "Syötä oikea postinumero." -#: contrib/comments/views/karma.py:19 -msgid "Anonymous users cannot vote" -msgstr "Anonyymit käyttäjät eivät voi äänestää" +#: contrib/localflavor/nl/forms.py:53 +msgid "Enter a valid phone number" +msgstr "Syötä oikea puhelinnumero." -#: contrib/comments/views/karma.py:23 -msgid "Invalid comment ID" -msgstr "Kommentin tunniste on virheellinen" +#: contrib/localflavor/nl/forms.py:76 +msgid "Enter a valid SoFi number" +msgstr "Syötä ikea SoFi-numero." -#: contrib/comments/views/karma.py:25 -msgid "No voting for yourself" -msgstr "Itseään ei voi äänestää" +#: contrib/localflavor/nl/nl_provinces.py:4 +msgid "Drente" +msgstr "" -#: contrib/comments/views/comments.py:27 -msgid "" -"This rating is required because you've entered at least one other rating." -msgstr "Tämä pisteytys on annettava, koska olet syöttänyt ainakin yhden muunkin pisteytyksen." +#: contrib/localflavor/nl/nl_provinces.py:5 +msgid "Flevoland" +msgstr "" -#: contrib/comments/views/comments.py:111 -#, python-format -msgid "" -"This comment was posted by a user who has posted fewer than %(count)s " -"comment:\n" -"\n" -"%(text)s" -msgid_plural "" -"This comment was posted by a user who has posted fewer than %(count)s " -"comments:\n" -"\n" -"%(text)s" -msgstr[0] "" -"Kommentin kirjoittanut käyttäjä on kirjoittanut vain yhden kommentin:\n" -"\n" -"%(text)s" -msgstr[1] "" -"Kommentin kirjoittanut käyttäjä on kirjoittanut alle %(count)s kommenttia:\n" -"\n" -"%(text)s" +#: contrib/localflavor/nl/nl_provinces.py:6 +msgid "Friesland" +msgstr "" -# Mitä "sketchy user" tarkoittaa? -#: contrib/comments/views/comments.py:116 -#, python-format -msgid "" -"This comment was posted by a sketchy user:\n" -"\n" -"%(text)s" +#: contrib/localflavor/nl/nl_provinces.py:7 +msgid "Gelderland" msgstr "" -"Tämä on \"sketchy\"-käyttäjän kirjoittama kommentti:\n" -"\n" -"%(text)s" -#: contrib/comments/views/comments.py:188 -#: contrib/comments/views/comments.py:280 -msgid "Only POSTs are allowed" -msgstr "Vain POST-kutsut sallittu" +#: contrib/localflavor/nl/nl_provinces.py:8 +msgid "Groningen" +msgstr "" -#: contrib/comments/views/comments.py:192 -#: contrib/comments/views/comments.py:284 -msgid "One or more of the required fields wasn't submitted" -msgstr "Yksi tai useampi vaadittu kenttä on jäänyt täyttämättä" +#: contrib/localflavor/nl/nl_provinces.py:9 +msgid "Limburg" +msgstr "" -#: contrib/comments/views/comments.py:196 -#: contrib/comments/views/comments.py:286 -msgid "Somebody tampered with the comment form (security violation)" -msgstr "Kommenttilomaketta on käpälöity (turvallisuusrike)" +#: contrib/localflavor/nl/nl_provinces.py:10 +msgid "Noord-Brabant" +msgstr "" -#: contrib/comments/views/comments.py:206 -#: contrib/comments/views/comments.py:292 -msgid "" -"The comment form had an invalid 'target' parameter -- the object ID was " -"invalid" -msgstr "Kommenttilomakkeen 'target'-parametri ei kelpaa -- kohteen ID oli virheellinen" +#: contrib/localflavor/nl/nl_provinces.py:11 +msgid "Noord-Holland" +msgstr "" -#: contrib/comments/views/comments.py:257 -#: contrib/comments/views/comments.py:321 -msgid "The comment form didn't provide either 'preview' or 'post'" -msgstr "Kommenttilomake ei pyytänyt esikatselua tai lähettämistä" +#: contrib/localflavor/nl/nl_provinces.py:12 +msgid "Overijssel" +msgstr "" -#: contrib/comments/templates/comments/form.html:8 -msgid "Forgotten your password?" -msgstr "Unohditko salasanasi?" +#: contrib/localflavor/nl/nl_provinces.py:13 +msgid "Utrecht" +msgstr "" -#: contrib/comments/templates/comments/form.html:12 -msgid "Ratings" -msgstr "Pisteytykset" +#: contrib/localflavor/nl/nl_provinces.py:14 +msgid "Zeeland" +msgstr "" -#: contrib/comments/templates/comments/form.html:12 -#: contrib/comments/templates/comments/form.html:23 -msgid "Required" -msgstr "Vaaditaan" +#: contrib/localflavor/nl/nl_provinces.py:15 +msgid "Zuid-Holland" +msgstr "" -#: contrib/comments/templates/comments/form.html:12 -#: contrib/comments/templates/comments/form.html:23 -msgid "Optional" -msgstr "Vapaavalintainen" +#: contrib/localflavor/jp/jp_prefectures.py:4 +msgid "Hokkaido" +msgstr "" -#: contrib/comments/templates/comments/form.html:23 -msgid "Post a photo" -msgstr "Lähetä valokuva" +#: contrib/localflavor/jp/jp_prefectures.py:5 +msgid "Aomori" +msgstr "" -#: contrib/comments/templates/comments/form.html:28 -#: contrib/comments/templates/comments/freeform.html:5 -msgid "Comment:" -msgstr "Kommentti:" +#: contrib/localflavor/jp/jp_prefectures.py:6 +msgid "Iwate" +msgstr "" -#: contrib/comments/templates/comments/form.html:35 -#: contrib/comments/templates/comments/freeform.html:10 -msgid "Preview comment" -msgstr "Esikatsele kommenttia" +#: contrib/localflavor/jp/jp_prefectures.py:7 +msgid "Miyagi" +msgstr "" -#: contrib/comments/templates/comments/freeform.html:4 -msgid "Your name:" -msgstr "Nimesi:" +#: contrib/localflavor/jp/jp_prefectures.py:8 +msgid "Akita" +msgstr "" -#: contrib/sessions/models.py:51 -msgid "session key" -msgstr "istunnon avain" +#: contrib/localflavor/jp/jp_prefectures.py:9 +msgid "Yamagata" +msgstr "" -#: contrib/sessions/models.py:52 -msgid "session data" -msgstr "istunnon tiedot" +#: contrib/localflavor/jp/jp_prefectures.py:10 +msgid "Fukushima" +msgstr "" -#: contrib/sessions/models.py:53 -msgid "expire date" -msgstr "vanhenee" +#: contrib/localflavor/jp/jp_prefectures.py:11 +msgid "Ibaraki" +msgstr "" -#: contrib/sessions/models.py:57 -msgid "session" -msgstr "istunto" +#: contrib/localflavor/jp/jp_prefectures.py:12 +msgid "Tochigi" +msgstr "" -#: contrib/sessions/models.py:58 -msgid "sessions" -msgstr "istunnot" +#: contrib/localflavor/jp/jp_prefectures.py:13 +msgid "Gunma" +msgstr "" -#: contrib/contenttypes/models.py:20 -msgid "python model class name" -msgstr "mallin python-luokan nimi" +#: contrib/localflavor/jp/jp_prefectures.py:14 +msgid "Saitama" +msgstr "" -#: contrib/contenttypes/models.py:23 -msgid "content type" -msgstr "sisältötyyppi" +#: contrib/localflavor/jp/jp_prefectures.py:15 +msgid "Chiba" +msgstr "" -#: contrib/contenttypes/models.py:24 -msgid "content types" -msgstr "sisältötyypit" +#: contrib/localflavor/jp/jp_prefectures.py:16 +msgid "Tokyo" +msgstr "Tokio" -#: forms/__init__.py:381 -#, python-format -msgid "Ensure your text is less than %s character." -msgid_plural "Ensure your text is less than %s characters." -msgstr[0] "Varmista, että tekstin pituus on vähemmän kuin %s merkki." -msgstr[1] "Varmista, että teksti pituus on vähemmän kuin %s merkkiä." +#: contrib/localflavor/jp/jp_prefectures.py:17 +msgid "Kanagawa" +msgstr "" -#: forms/__init__.py:386 -msgid "Line breaks are not allowed here." -msgstr "Rivinvaihtoja ei voi käyttää." +#: contrib/localflavor/jp/jp_prefectures.py:18 +msgid "Yamanashi" +msgstr "" -#: forms/__init__.py:487 forms/__init__.py:560 forms/__init__.py:599 -#, python-format -msgid "Select a valid choice; '%(data)s' is not in %(choices)s." -msgstr "Valinta ei kelpaa; '%(data)s' ei löydy vaihtoehtojen %(choices)s joukosta." +#: contrib/localflavor/jp/jp_prefectures.py:19 +msgid "Nagano" +msgstr "" -#: forms/__init__.py:663 -msgid "The submitted file is empty." -msgstr "Lähetetty tiedosto on tyhjä." +#: contrib/localflavor/jp/jp_prefectures.py:20 +msgid "Niigata" +msgstr "" -#: forms/__init__.py:719 -msgid "Enter a whole number between -32,768 and 32,767." -msgstr "Syötä kokonaisluku väliltä -32768 ja 32767." +#: contrib/localflavor/jp/jp_prefectures.py:21 +msgid "Toyama" +msgstr "" -#: forms/__init__.py:729 -msgid "Enter a positive number." -msgstr "Syötä positiivinen kokonaisluku." +#: contrib/localflavor/jp/jp_prefectures.py:22 +msgid "Ishikawa" +msgstr "" -#: forms/__init__.py:739 -msgid "Enter a whole number between 0 and 32,767." -msgstr "Syötä kokonaisluku väliltä 0 ja 32767." +#: contrib/localflavor/jp/jp_prefectures.py:23 +msgid "Fukui" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:24 +msgid "Gifu" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:25 +msgid "Shizuoka" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:26 +msgid "Aichi" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:27 +msgid "Mie" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:28 +msgid "Shiga" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:29 +msgid "Kyoto" +msgstr "Kioto" + +#: contrib/localflavor/jp/jp_prefectures.py:30 +msgid "Osaka" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:31 +msgid "Hyogo" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:32 +msgid "Nara" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:33 +msgid "Wakayama" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:34 +msgid "Tottori" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:35 +msgid "Shimane" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:36 +msgid "Okayama" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:37 +msgid "Hiroshima" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:38 +msgid "Yamaguchi" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:39 +msgid "Tokushima" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:40 +msgid "Kagawa" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:41 +msgid "Ehime" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:42 +msgid "Kochi" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:43 +msgid "Fukuoka" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:44 +msgid "Saga" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:45 +msgid "Nagasaki" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:46 +msgid "Kumamoto" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:47 +msgid "Oita" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:48 +msgid "Miyazaki" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:49 +msgid "Kagoshima" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:50 +msgid "Okinawa" +msgstr "" + +#: contrib/localflavor/jp/forms.py:21 +msgid "Enter a postal code in the format XXXXXXX or XXX-XXXX." +msgstr "" + +#: contrib/localflavor/cl/forms.py:32 +msgid "Enter valid a Chilean RUT. The format is XX.XXX.XXX-X." +msgstr "" + +#: contrib/localflavor/cl/forms.py:37 +msgid "Enter valid a Chilean RUT" +msgstr "Syötä oikea chileläinen RUT" + +#: contrib/localflavor/us/forms.py:18 +msgid "Enter a zip code in the format XXXXX or XXXXX-XXXX." +msgstr "" + +#: contrib/localflavor/us/forms.py:51 +msgid "Enter a valid U.S. Social Security number in XXX-XX-XXXX format." +msgstr "" + +#: contrib/localflavor/no/forms.py:35 +msgid "Enter a valid Norwegian social security number." +msgstr "Syötä oikea norjalainen henkilötunnus." + +#: utils/dateformat.py:41 +msgid "p.m." +msgstr "ip" + +#: utils/dateformat.py:42 +msgid "a.m." +msgstr "ap" + +#: utils/dateformat.py:47 +msgid "PM" +msgstr "IP" + +#: utils/dateformat.py:48 +msgid "AM" +msgstr "AP" + +#: utils/dateformat.py:97 +msgid "midnight" +msgstr "keskiyö" + +#: utils/dateformat.py:99 +msgid "noon" +msgstr "keskipäivä" + +#: utils/text.py:127 +msgid "or" +msgstr "tai" #: utils/dates.py:6 msgid "Monday" @@ -1851,127 +3155,155 @@ msgstr "lauantai" msgid "Sunday" msgstr "sunnuntai" -#: utils/dates.py:14 +#: utils/dates.py:10 +msgid "Mon" +msgstr "Ma" + +#: utils/dates.py:10 +msgid "Tue" +msgstr "Ti" + +#: utils/dates.py:10 +msgid "Wed" +msgstr "Ke" + +#: utils/dates.py:10 +msgid "Thu" +msgstr "To" + +#: utils/dates.py:10 +msgid "Fri" +msgstr "Pe" + +#: utils/dates.py:11 +msgid "Sat" +msgstr "La" + +#: utils/dates.py:11 +msgid "Sun" +msgstr "Su" + +#: utils/dates.py:18 msgid "January" msgstr "tammikuu" -#: utils/dates.py:14 +#: utils/dates.py:18 msgid "February" msgstr "helmikuu" -#: utils/dates.py:14 utils/dates.py:27 +#: utils/dates.py:18 utils/dates.py:31 msgid "March" msgstr "maaliskuu" -#: utils/dates.py:14 utils/dates.py:27 +#: utils/dates.py:18 utils/dates.py:31 msgid "April" msgstr "huhtikuu" -#: utils/dates.py:14 utils/dates.py:27 +#: utils/dates.py:18 utils/dates.py:31 msgid "May" msgstr "toukokuu" -#: utils/dates.py:14 utils/dates.py:27 +#: utils/dates.py:18 utils/dates.py:31 msgid "June" msgstr "kesäkuu" -#: utils/dates.py:15 utils/dates.py:27 +#: utils/dates.py:19 utils/dates.py:31 msgid "July" msgstr "heinäkuu" -#: utils/dates.py:15 +#: utils/dates.py:19 msgid "August" msgstr "elokuu" -#: utils/dates.py:15 +#: utils/dates.py:19 msgid "September" msgstr "syyskuu" -#: utils/dates.py:15 +#: utils/dates.py:19 msgid "October" msgstr "lokakuu" -#: utils/dates.py:15 +#: utils/dates.py:19 msgid "November" msgstr "marraskuu" -#: utils/dates.py:16 +#: utils/dates.py:20 msgid "December" msgstr "joulukuu" -#: utils/dates.py:19 +#: utils/dates.py:23 msgid "jan" msgstr "tam" -#: utils/dates.py:19 +#: utils/dates.py:23 msgid "feb" msgstr "hel" -#: utils/dates.py:19 +#: utils/dates.py:23 msgid "mar" msgstr "maa" -#: utils/dates.py:19 +#: utils/dates.py:23 msgid "apr" msgstr "huh" -#: utils/dates.py:19 +#: utils/dates.py:23 msgid "may" msgstr "tou" -#: utils/dates.py:19 +#: utils/dates.py:23 msgid "jun" msgstr "kes" -#: utils/dates.py:20 +#: utils/dates.py:24 msgid "jul" msgstr "hei" -#: utils/dates.py:20 +#: utils/dates.py:24 msgid "aug" msgstr "elo" -#: utils/dates.py:20 +#: utils/dates.py:24 msgid "sep" msgstr "syy" -#: utils/dates.py:20 +#: utils/dates.py:24 msgid "oct" msgstr "lok" -#: utils/dates.py:20 +#: utils/dates.py:24 msgid "nov" msgstr "mar" -#: utils/dates.py:20 +#: utils/dates.py:24 msgid "dec" msgstr "jou" -#: utils/dates.py:27 +#: utils/dates.py:31 msgid "Jan." msgstr "tammi" -#: utils/dates.py:27 +#: utils/dates.py:31 msgid "Feb." msgstr "helmi" -#: utils/dates.py:28 +#: utils/dates.py:32 msgid "Aug." msgstr "elo" -#: utils/dates.py:28 +#: utils/dates.py:32 msgid "Sept." msgstr "syys" -#: utils/dates.py:28 +#: utils/dates.py:32 msgid "Oct." msgstr "loka" -#: utils/dates.py:28 +#: utils/dates.py:32 msgid "Nov." msgstr "marras" -#: utils/dates.py:28 +#: utils/dates.py:32 msgid "Dec." msgstr "joulu" @@ -2011,26 +3343,237 @@ msgid_plural "minutes" msgstr[0] "minuutti" msgstr[1] "minuuttia" -#: utils/translation/trans_real.py:362 +#: utils/timesince.py:39 +#, python-format +msgid "%(number)d %(type)s" +msgstr "%(number)d %(type)s" + +#: utils/timesince.py:45 +#, python-format +msgid ", %(number)d %(type)s" +msgstr ", %(number)d %(type)s" + +#: utils/translation/trans_real.py:391 msgid "DATE_FORMAT" msgstr "j.n.Y" -#: utils/translation/trans_real.py:363 +#: utils/translation/trans_real.py:392 msgid "DATETIME_FORMAT" msgstr "j.n.Y G:i" -#: utils/translation/trans_real.py:364 +#: utils/translation/trans_real.py:393 msgid "TIME_FORMAT" msgstr "G:i" -#: utils/translation/trans_real.py:380 +#: utils/translation/trans_real.py:409 msgid "YEAR_MONTH_FORMAT" msgstr "N Y" -#: utils/translation/trans_real.py:381 +#: utils/translation/trans_real.py:410 msgid "MONTH_DAY_FORMAT" msgstr "N j, Y" -#: template/defaultfilters.py:401 -msgid "yes,no,maybe" -msgstr "kyllä,ei,ehkä" +#: conf/global_settings.py:39 +msgid "Arabic" +msgstr "arabia" + +#: conf/global_settings.py:40 +msgid "Bengali" +msgstr "bengali" + +#: conf/global_settings.py:41 +msgid "Bulgarian" +msgstr "bulgaria" + +#: conf/global_settings.py:42 +msgid "Catalan" +msgstr "katalaani" + +#: conf/global_settings.py:43 +msgid "Czech" +msgstr "tšekki" + +#: conf/global_settings.py:44 +msgid "Welsh" +msgstr "wales" + +#: conf/global_settings.py:45 +msgid "Danish" +msgstr "tanska" + +#: conf/global_settings.py:46 +msgid "German" +msgstr "saksa" + +#: conf/global_settings.py:47 +msgid "Greek" +msgstr "kreikka" + +#: conf/global_settings.py:48 +msgid "English" +msgstr "englanti" + +#: conf/global_settings.py:49 +msgid "Spanish" +msgstr "espanja" + +#: conf/global_settings.py:50 +msgid "Argentinean Spanish" +msgstr "Argentiinan espanja" + +#: conf/global_settings.py:51 +msgid "Persian" +msgstr "persia" + +#: conf/global_settings.py:52 +msgid "Finnish" +msgstr "suomi" + +#: conf/global_settings.py:53 +msgid "French" +msgstr "ranska" + +#: conf/global_settings.py:54 +msgid "Galician" +msgstr "galicia" + +#: conf/global_settings.py:55 +msgid "Hungarian" +msgstr "unkari" + +#: conf/global_settings.py:56 +msgid "Hebrew" +msgstr "heprea" + +#: conf/global_settings.py:57 +msgid "Croatian" +msgstr "kroatia" + +#: conf/global_settings.py:58 +msgid "Icelandic" +msgstr "islanti" + +#: conf/global_settings.py:59 +msgid "Italian" +msgstr "italia" + +#: conf/global_settings.py:60 +msgid "Japanese" +msgstr "japani" + +#: conf/global_settings.py:61 +msgid "Korean" +msgstr "korea" + +#: conf/global_settings.py:62 +msgid "Khmer" +msgstr "khmer" + +#: conf/global_settings.py:63 +msgid "Kannada" +msgstr "kannada" + +#: conf/global_settings.py:64 +msgid "Latvian" +msgstr "latvia" + +#: conf/global_settings.py:65 +msgid "Macedonian" +msgstr "makedonia" + +#: conf/global_settings.py:66 +msgid "Dutch" +msgstr "hollanti" + +#: conf/global_settings.py:67 +msgid "Norwegian" +msgstr "norja" + +#: conf/global_settings.py:68 +msgid "Polish" +msgstr "puola" + +#: conf/global_settings.py:69 +msgid "Portugese" +msgstr "portugali" + +#: conf/global_settings.py:70 +msgid "Brazilian" +msgstr "Brasilian portugali" + +#: conf/global_settings.py:71 +msgid "Romanian" +msgstr "romania" + +#: conf/global_settings.py:72 +msgid "Russian" +msgstr "venäjä" + +#: conf/global_settings.py:73 +msgid "Slovak" +msgstr "slovakia" + +#: conf/global_settings.py:74 +msgid "Slovenian" +msgstr "slovenia" + +#: conf/global_settings.py:75 +msgid "Serbian" +msgstr "serbia" + +#: conf/global_settings.py:76 +msgid "Swedish" +msgstr "ruotsi" + +#: conf/global_settings.py:77 +msgid "Tamil" +msgstr "tamili" + +#: conf/global_settings.py:78 +msgid "Telugu" +msgstr "telugu" + +#: conf/global_settings.py:79 +msgid "Turkish" +msgstr "turkki" + +#: conf/global_settings.py:80 +msgid "Ukrainian" +msgstr "ukraina" + +#: conf/global_settings.py:81 +msgid "Simplified Chinese" +msgstr "kiina (yksinkertaistettu)" + +#: conf/global_settings.py:82 +msgid "Traditional Chinese" +msgstr "kiina (perinteinen)" + +#: oldforms/__init__.py:408 +#, python-format +msgid "Ensure your text is less than %s character." +msgid_plural "Ensure your text is less than %s characters." +msgstr[0] "Varmista, että tekstin pituus on vähemmän kuin %s merkki." +msgstr[1] "Varmista, että teksti pituus on vähemmän kuin %s merkkiä." + +#: oldforms/__init__.py:413 +msgid "Line breaks are not allowed here." +msgstr "Rivinvaihtoja ei voi käyttää." + +#: oldforms/__init__.py:511 oldforms/__init__.py:585 oldforms/__init__.py:624 +#, python-format +msgid "Select a valid choice; '%(data)s' is not in %(choices)s." +msgstr "" +"Valinta ei kelpaa; '%(data)s' ei löydy vaihtoehtojen %(choices)s joukosta." + +#: oldforms/__init__.py:744 +msgid "Enter a whole number between -32,768 and 32,767." +msgstr "Syötä kokonaisluku väliltä -32768 ja 32767." + +#: oldforms/__init__.py:754 +msgid "Enter a positive number." +msgstr "Syötä positiivinen kokonaisluku." + +#: oldforms/__init__.py:764 +msgid "Enter a whole number between 0 and 32,767." +msgstr "Syötä kokonaisluku väliltä 0 ja 32767." diff --git a/django/conf/locale/ga/LC_MESSAGES/django.mo b/django/conf/locale/ga/LC_MESSAGES/django.mo Binary files differnew file mode 100644 index 0000000000..1c414c28f5 --- /dev/null +++ b/django/conf/locale/ga/LC_MESSAGES/django.mo diff --git a/django/conf/locale/ga/LC_MESSAGES/django.po b/django/conf/locale/ga/LC_MESSAGES/django.po new file mode 100644 index 0000000000..0adaf0933a --- /dev/null +++ b/django/conf/locale/ga/LC_MESSAGES/django.po @@ -0,0 +1,3443 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-09-14 12:00+0100\n" +"PO-Revision-Date: 2007-09-14 14:00+0100\n" +"Last-Translator: Michael Thornhill <michael.thornhill@gmail.com>\n" +"Language-Team: Gaeilge <ga@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: db/models/manipulators.py:309 +#, python-format +msgid "%(object)s with this %(type)s already exists for the given %(field)s." +msgstr "" + +#: db/models/manipulators.py:310 +#: contrib/admin/views/main.py:342 +#: contrib/admin/views/main.py:344 +#: contrib/admin/views/main.py:346 +#: core/validators.py:283 +msgid "and" +msgstr "" + +#: db/models/fields/related.py:55 +#, python-format +msgid "Please enter a valid %s." +msgstr "" + +#: db/models/fields/related.py:658 +msgid "Separate multiple IDs with commas." +msgstr "" + +#: db/models/fields/related.py:660 +msgid "Hold down \"Control\", or \"Command\" on a Mac, to select more than one." +msgstr "" + +#: db/models/fields/related.py:707 +#, python-format +msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid." +msgid_plural "Please enter valid %(self)s IDs. The values %(value)r are invalid." +msgstr[0] "" +msgstr[1] "" + +#: db/models/fields/__init__.py:52 +#, python-format +msgid "%(optname)s with this %(fieldname)s already exists." +msgstr "" + +#: db/models/fields/__init__.py:159 +#: db/models/fields/__init__.py:316 +#: db/models/fields/__init__.py:724 +#: db/models/fields/__init__.py:735 +#: newforms/fields.py:93 +#: newforms/fields.py:509 +#: newforms/fields.py:585 +#: newforms/fields.py:596 +#: newforms/models.py:193 +#: oldforms/__init__.py:373 +msgid "This field is required." +msgstr "" + +#: db/models/fields/__init__.py:414 +msgid "This value must be an integer." +msgstr "" + +#: db/models/fields/__init__.py:449 +msgid "This value must be either True or False." +msgstr "" + +#: db/models/fields/__init__.py:470 +msgid "This field cannot be null." +msgstr "" + +#: db/models/fields/__init__.py:504 +#: core/validators.py:156 +msgid "Enter a valid date in YYYY-MM-DD format." +msgstr "" + +#: db/models/fields/__init__.py:573 +#: core/validators.py:165 +msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format." +msgstr "" + +#: db/models/fields/__init__.py:634 +msgid "This value must be a decimal number." +msgstr "" + +#: db/models/fields/__init__.py:744 +msgid "Enter a valid filename." +msgstr "" + +#: db/models/fields/__init__.py:887 +msgid "This value must be either None, True or False." +msgstr "" + +#: template/defaultfilters.py:532 +msgid "yes,no,maybe" +msgstr "" + +#: template/defaultfilters.py:561 +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "" +msgstr[1] "" + +#: template/defaultfilters.py:563 +#, python-format +msgid "%.1f KB" +msgstr "" + +#: template/defaultfilters.py:565 +#, python-format +msgid "%.1f MB" +msgstr "" + +#: template/defaultfilters.py:566 +#, python-format +msgid "%.1f GB" +msgstr "" + +#: contrib/flatpages/models.py:7 +#: contrib/admin/views/doc.py:317 +msgid "URL" +msgstr "" + +#: contrib/flatpages/models.py:8 +msgid "Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" + +#: contrib/flatpages/models.py:9 +msgid "title" +msgstr "" + +#: contrib/flatpages/models.py:10 +msgid "content" +msgstr "" + +#: contrib/flatpages/models.py:11 +msgid "enable comments" +msgstr "" + +#: contrib/flatpages/models.py:12 +msgid "template name" +msgstr "" + +#: contrib/flatpages/models.py:13 +msgid "Example: 'flatpages/contact_page.html'. If this isn't provided, the system will use 'flatpages/default.html'." +msgstr "" + +#: contrib/flatpages/models.py:14 +msgid "registration required" +msgstr "" + +#: contrib/flatpages/models.py:14 +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" + +#: contrib/flatpages/models.py:18 +msgid "flat page" +msgstr "" + +#: contrib/flatpages/models.py:19 +msgid "flat pages" +msgstr "" + +#: contrib/redirects/models.py:7 +msgid "redirect from" +msgstr "" + +#: contrib/redirects/models.py:8 +msgid "This should be an absolute path, excluding the domain name. Example: '/events/search/'." +msgstr "" + +#: contrib/redirects/models.py:9 +msgid "redirect to" +msgstr "" + +#: contrib/redirects/models.py:10 +msgid "This can be either an absolute path (as above) or a full URL starting with 'http://'." +msgstr "" + +#: contrib/redirects/models.py:13 +msgid "redirect" +msgstr "" + +#: contrib/redirects/models.py:14 +msgid "redirects" +msgstr "" + +#: contrib/localflavor/uk/forms.py:18 +msgid "Enter a postcode. A space is required between the two postcode parts." +msgstr "" + +#: contrib/localflavor/in_/forms.py:16 +msgid "Enter a zip code in the format XXXXXXX." +msgstr "" + +#: contrib/localflavor/jp/forms.py:21 +msgid "Enter a postal code in the format XXXXXXX or XXX-XXXX." +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:4 +msgid "Hokkaido" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:5 +msgid "Aomori" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:6 +msgid "Iwate" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:7 +msgid "Miyagi" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:8 +msgid "Akita" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:9 +msgid "Yamagata" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:10 +msgid "Fukushima" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:11 +msgid "Ibaraki" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:12 +msgid "Tochigi" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:13 +msgid "Gunma" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:14 +msgid "Saitama" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:15 +msgid "Chiba" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:16 +msgid "Tokyo" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:17 +msgid "Kanagawa" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:18 +msgid "Yamanashi" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:19 +msgid "Nagano" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:20 +msgid "Niigata" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:21 +msgid "Toyama" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:22 +msgid "Ishikawa" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:23 +msgid "Fukui" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:24 +msgid "Gifu" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:25 +msgid "Shizuoka" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:26 +msgid "Aichi" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:27 +msgid "Mie" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:28 +msgid "Shiga" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:29 +msgid "Kyoto" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:30 +msgid "Osaka" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:31 +msgid "Hyogo" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:32 +msgid "Nara" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:33 +msgid "Wakayama" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:34 +msgid "Tottori" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:35 +msgid "Shimane" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:36 +msgid "Okayama" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:37 +msgid "Hiroshima" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:38 +msgid "Yamaguchi" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:39 +msgid "Tokushima" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:40 +msgid "Kagawa" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:41 +msgid "Ehime" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:42 +msgid "Kochi" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:43 +msgid "Fukuoka" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:44 +msgid "Saga" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:45 +msgid "Nagasaki" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:46 +msgid "Kumamoto" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:47 +msgid "Oita" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:48 +msgid "Miyazaki" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:49 +msgid "Kagoshima" +msgstr "" + +#: contrib/localflavor/jp/jp_prefectures.py:50 +msgid "Okinawa" +msgstr "" + +#: contrib/localflavor/sk/sk_regions.py:8 +msgid "Banska Bystrica region" +msgstr "" + +#: contrib/localflavor/sk/sk_regions.py:9 +msgid "Bratislava region" +msgstr "" + +#: contrib/localflavor/sk/sk_regions.py:10 +msgid "Kosice region" +msgstr "" + +#: contrib/localflavor/sk/sk_regions.py:11 +msgid "Nitra region" +msgstr "" + +#: contrib/localflavor/sk/sk_regions.py:12 +msgid "Presov region" +msgstr "" + +#: contrib/localflavor/sk/sk_regions.py:13 +msgid "Trencin region" +msgstr "" + +#: contrib/localflavor/sk/sk_regions.py:14 +msgid "Trnava region" +msgstr "" + +#: contrib/localflavor/sk/sk_regions.py:15 +msgid "Zilina region" +msgstr "" + +#: contrib/localflavor/sk/forms.py:32 +msgid "Enter a postal code in the format XXXXX or XXX XX." +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:8 +msgid "Banska Bystrica" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:9 +msgid "Banska Stiavnica" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:10 +msgid "Bardejov" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:11 +msgid "Banovce nad Bebravou" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:12 +msgid "Brezno" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:13 +msgid "Bratislava I" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:14 +msgid "Bratislava II" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:15 +msgid "Bratislava III" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:16 +msgid "Bratislava IV" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:17 +msgid "Bratislava V" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:18 +msgid "Bytca" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:19 +msgid "Cadca" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:20 +msgid "Detva" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:21 +msgid "Dolny Kubin" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:22 +msgid "Dunajska Streda" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:23 +msgid "Galanta" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:24 +msgid "Gelnica" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:25 +msgid "Hlohovec" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:26 +msgid "Humenne" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:27 +msgid "Ilava" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:28 +msgid "Kezmarok" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:29 +msgid "Komarno" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:30 +msgid "Kosice I" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:31 +msgid "Kosice II" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:32 +msgid "Kosice III" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:33 +msgid "Kosice IV" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:34 +msgid "Kosice - okolie" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:35 +msgid "Krupina" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:36 +msgid "Kysucke Nove Mesto" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:37 +msgid "Levice" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:38 +msgid "Levoca" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:39 +msgid "Liptovsky Mikulas" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:40 +msgid "Lucenec" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:41 +msgid "Malacky" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:42 +msgid "Martin" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:43 +msgid "Medzilaborce" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:44 +msgid "Michalovce" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:45 +msgid "Myjava" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:46 +msgid "Namestovo" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:47 +msgid "Nitra" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:48 +msgid "Nove Mesto nad Vahom" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:49 +msgid "Nove Zamky" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:50 +msgid "Partizanske" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:51 +msgid "Pezinok" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:52 +msgid "Piestany" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:53 +msgid "Poltar" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:54 +msgid "Poprad" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:55 +msgid "Povazska Bystrica" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:56 +msgid "Presov" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:57 +msgid "Prievidza" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:58 +msgid "Puchov" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:59 +msgid "Revuca" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:60 +msgid "Rimavska Sobota" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:61 +msgid "Roznava" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:62 +msgid "Ruzomberok" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:63 +msgid "Sabinov" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:64 +msgid "Senec" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:65 +msgid "Senica" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:66 +msgid "Skalica" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:67 +msgid "Snina" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:68 +msgid "Sobrance" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:69 +msgid "Spisska Nova Ves" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:70 +msgid "Stara Lubovna" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:71 +msgid "Stropkov" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:72 +msgid "Svidnik" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:73 +msgid "Sala" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:74 +msgid "Topolcany" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:75 +msgid "Trebisov" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:76 +msgid "Trencin" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:77 +msgid "Trnava" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:78 +msgid "Turcianske Teplice" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:79 +msgid "Tvrdosin" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:80 +msgid "Velky Krtis" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:81 +msgid "Vranov nad Toplou" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:82 +msgid "Zlate Moravce" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:83 +msgid "Zvolen" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:84 +msgid "Zarnovica" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:85 +msgid "Ziar nad Hronom" +msgstr "" + +#: contrib/localflavor/sk/sk_districts.py:86 +msgid "Zilina" +msgstr "" + +#: contrib/localflavor/is_/forms.py:17 +msgid "Enter a valid Icelandic identification number. The format is XXXXXX-XXXX." +msgstr "" + +#: contrib/localflavor/is_/forms.py:31 +msgid "The Icelandic identification number is not valid." +msgstr "" + +#: contrib/localflavor/au/forms.py:18 +msgid "Enter a 4 digit post code." +msgstr "" + +#: contrib/localflavor/fi/forms.py:14 +#: contrib/localflavor/fr/forms.py:17 +#: contrib/localflavor/de/forms.py:16 +msgid "Enter a zip code in the format XXXXX." +msgstr "" + +#: contrib/localflavor/fi/forms.py:40 +#: contrib/localflavor/fi/forms.py:45 +msgid "Enter a valid Finnish social security number." +msgstr "" + +#: contrib/localflavor/ch/forms.py:18 +#: contrib/localflavor/no/forms.py:14 +msgid "Enter a zip code in the format XXXX." +msgstr "" + +#: contrib/localflavor/ch/forms.py:90 +msgid "Enter a valid Swiss identity or passport card number in X1234567<0 or 1234567890 format." +msgstr "" + +#: contrib/localflavor/ch/ch_states.py:5 +msgid "Aargau" +msgstr "" + +#: contrib/localflavor/ch/ch_states.py:6 +msgid "Appenzell Innerrhoden" +msgstr "" + +#: contrib/localflavor/ch/ch_states.py:7 +msgid "Appenzell Ausserrhoden" +msgstr "" + +#: contrib/localflavor/ch/ch_states.py:8 +msgid "Basel-Stadt" +msgstr "" + +#: contrib/localflavor/ch/ch_states.py:9 +msgid "Basel-Land" +msgstr "" + +#: contrib/localflavor/ch/ch_states.py:10 +msgid "Berne" +msgstr "" + +#: contrib/localflavor/ch/ch_states.py:11 +msgid "Fribourg" +msgstr "" + +#: contrib/localflavor/ch/ch_states.py:12 +msgid "Geneva" +msgstr "" + +#: contrib/localflavor/ch/ch_states.py:13 +msgid "Glarus" +msgstr "" + +#: contrib/localflavor/ch/ch_states.py:14 +msgid "Graubuenden" +msgstr "" + +#: contrib/localflavor/ch/ch_states.py:15 +msgid "Jura" +msgstr "" + +#: contrib/localflavor/ch/ch_states.py:16 +msgid "Lucerne" +msgstr "" + +#: contrib/localflavor/ch/ch_states.py:17 +msgid "Neuchatel" +msgstr "" + +#: contrib/localflavor/ch/ch_states.py:18 +msgid "Nidwalden" +msgstr "" + +#: contrib/localflavor/ch/ch_states.py:19 +msgid "Obwalden" +msgstr "" + +#: contrib/localflavor/ch/ch_states.py:20 +msgid "Schaffhausen" +msgstr "" + +#: contrib/localflavor/ch/ch_states.py:21 +msgid "Schwyz" +msgstr "" + +#: contrib/localflavor/ch/ch_states.py:22 +msgid "Solothurn" +msgstr "" + +#: contrib/localflavor/ch/ch_states.py:23 +msgid "St. Gallen" +msgstr "" + +#: contrib/localflavor/ch/ch_states.py:24 +msgid "Thurgau" +msgstr "" + +#: contrib/localflavor/ch/ch_states.py:25 +msgid "Ticino" +msgstr "" + +#: contrib/localflavor/ch/ch_states.py:26 +msgid "Uri" +msgstr "" + +#: contrib/localflavor/ch/ch_states.py:27 +msgid "Valais" +msgstr "" + +#: contrib/localflavor/ch/ch_states.py:28 +msgid "Vaud" +msgstr "" + +#: contrib/localflavor/ch/ch_states.py:29 +msgid "Zug" +msgstr "" + +#: contrib/localflavor/ch/ch_states.py:30 +msgid "Zurich" +msgstr "" + +#: contrib/localflavor/cl/forms.py:32 +msgid "Enter valid a Chilean RUT. The format is XX.XXX.XXX-X." +msgstr "" + +#: contrib/localflavor/cl/forms.py:37 +msgid "Enter valid a Chilean RUT" +msgstr "" + +#: contrib/localflavor/ar/forms.py:30 +#: contrib/localflavor/ar/forms.py:38 +msgid "Enter a postal code in the format NNNN or ANNNNAAA." +msgstr "" + +#: contrib/localflavor/ar/forms.py:61 +#: contrib/localflavor/br/forms.py:103 +msgid "This field requires only numbers." +msgstr "" + +#: contrib/localflavor/ar/forms.py:64 +msgid "This field requires 7 or 8 digits." +msgstr "" + +#: contrib/localflavor/ar/forms.py:75 +msgid "Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format." +msgstr "" + +#: contrib/localflavor/ar/forms.py:88 +msgid "Invalid CUIT." +msgstr "" + +#: contrib/localflavor/us/forms.py:18 +msgid "Enter a zip code in the format XXXXX or XXXXX-XXXX." +msgstr "" + +#: contrib/localflavor/us/forms.py:51 +msgid "Enter a valid U.S. Social Security number in XXX-XX-XXXX format." +msgstr "" + +#: contrib/localflavor/no/forms.py:35 +msgid "Enter a valid Norwegian social security number." +msgstr "" + +#: contrib/localflavor/pl/forms.py:53 +msgid "National Identification Number consists of 11 digits." +msgstr "" + +#: contrib/localflavor/pl/forms.py:59 +msgid "Wrong checksum for the National Identification Number." +msgstr "" + +#: contrib/localflavor/pl/forms.py:71 +msgid "Enter a tax number field (NIP) in the format XXX-XXX-XX-XX or XX-XX-XXX-XXX." +msgstr "" + +#: contrib/localflavor/pl/forms.py:82 +msgid "Enter a postal code in the format XX-XXX." +msgstr "" + +#: contrib/localflavor/pl/pl_voivodeships.py:8 +msgid "Lower Silesia" +msgstr "" + +#: contrib/localflavor/pl/pl_voivodeships.py:9 +msgid "Kuyavia-Pomerania" +msgstr "" + +#: contrib/localflavor/pl/pl_voivodeships.py:10 +msgid "Lublin" +msgstr "" + +#: contrib/localflavor/pl/pl_voivodeships.py:11 +msgid "Lubusz" +msgstr "" + +#: contrib/localflavor/pl/pl_voivodeships.py:12 +msgid "Lodz" +msgstr "" + +#: contrib/localflavor/pl/pl_voivodeships.py:13 +msgid "Lesser Poland" +msgstr "" + +#: contrib/localflavor/pl/pl_voivodeships.py:14 +msgid "Masovia" +msgstr "" + +#: contrib/localflavor/pl/pl_voivodeships.py:15 +msgid "Opole" +msgstr "" + +#: contrib/localflavor/pl/pl_voivodeships.py:16 +msgid "Subcarpatia" +msgstr "" + +#: contrib/localflavor/pl/pl_voivodeships.py:17 +msgid "Podlasie" +msgstr "" + +#: contrib/localflavor/pl/pl_voivodeships.py:18 +msgid "Pomerania" +msgstr "" + +#: contrib/localflavor/pl/pl_voivodeships.py:19 +msgid "Silesia" +msgstr "" + +#: contrib/localflavor/pl/pl_voivodeships.py:20 +msgid "Swietokrzyskie" +msgstr "" + +#: contrib/localflavor/pl/pl_voivodeships.py:21 +msgid "Warmia-Masuria" +msgstr "" + +#: contrib/localflavor/pl/pl_voivodeships.py:22 +msgid "Greater Poland" +msgstr "" + +#: contrib/localflavor/pl/pl_voivodeships.py:23 +msgid "West Pomerania" +msgstr "" + +#: contrib/localflavor/de/forms.py:60 +msgid "Enter a valid German identity card number in XXXXXXXXXXX-XXXXXXX-XXXXXXX-X format." +msgstr "" + +#: contrib/localflavor/de/de_states.py:5 +msgid "Baden-Wuerttemberg" +msgstr "" + +#: contrib/localflavor/de/de_states.py:6 +msgid "Bavaria" +msgstr "" + +#: contrib/localflavor/de/de_states.py:7 +msgid "Berlin" +msgstr "" + +#: contrib/localflavor/de/de_states.py:8 +msgid "Brandenburg" +msgstr "" + +#: contrib/localflavor/de/de_states.py:9 +msgid "Bremen" +msgstr "" + +#: contrib/localflavor/de/de_states.py:10 +msgid "Hamburg" +msgstr "" + +#: contrib/localflavor/de/de_states.py:11 +msgid "Hessen" +msgstr "" + +#: contrib/localflavor/de/de_states.py:12 +msgid "Mecklenburg-Western Pomerania" +msgstr "" + +#: contrib/localflavor/de/de_states.py:13 +msgid "Lower Saxony" +msgstr "" + +#: contrib/localflavor/de/de_states.py:14 +msgid "North Rhine-Westphalia" +msgstr "" + +#: contrib/localflavor/de/de_states.py:15 +msgid "Rhineland-Palatinate" +msgstr "" + +#: contrib/localflavor/de/de_states.py:16 +msgid "Saarland" +msgstr "" + +#: contrib/localflavor/de/de_states.py:17 +msgid "Saxony" +msgstr "" + +#: contrib/localflavor/de/de_states.py:18 +msgid "Saxony-Anhalt" +msgstr "" + +#: contrib/localflavor/de/de_states.py:19 +msgid "Schleswig-Holstein" +msgstr "" + +#: contrib/localflavor/de/de_states.py:20 +msgid "Thuringia" +msgstr "" + +#: contrib/localflavor/nl/forms.py:25 +msgid "Enter a valid postal code" +msgstr "" + +#: contrib/localflavor/nl/forms.py:53 +msgid "Enter a valid phone number" +msgstr "" + +#: contrib/localflavor/nl/forms.py:76 +msgid "Enter a valid SoFi number" +msgstr "" + +#: contrib/localflavor/nl/nl_provinces.py:4 +msgid "Drente" +msgstr "" + +#: contrib/localflavor/nl/nl_provinces.py:5 +msgid "Flevoland" +msgstr "" + +#: contrib/localflavor/nl/nl_provinces.py:6 +msgid "Friesland" +msgstr "" + +#: contrib/localflavor/nl/nl_provinces.py:7 +msgid "Gelderland" +msgstr "" + +#: contrib/localflavor/nl/nl_provinces.py:8 +msgid "Groningen" +msgstr "" + +#: contrib/localflavor/nl/nl_provinces.py:9 +msgid "Limburg" +msgstr "" + +#: contrib/localflavor/nl/nl_provinces.py:10 +msgid "Noord-Brabant" +msgstr "" + +#: contrib/localflavor/nl/nl_provinces.py:11 +msgid "Noord-Holland" +msgstr "" + +#: contrib/localflavor/nl/nl_provinces.py:12 +msgid "Overijssel" +msgstr "" + +#: contrib/localflavor/nl/nl_provinces.py:13 +msgid "Utrecht" +msgstr "" + +#: contrib/localflavor/nl/nl_provinces.py:14 +msgid "Zeeland" +msgstr "" + +#: contrib/localflavor/nl/nl_provinces.py:15 +msgid "Zuid-Holland" +msgstr "" + +#: contrib/localflavor/it/forms.py:16 +msgid "Enter a valid zip code." +msgstr "" + +#: contrib/localflavor/it/forms.py:41 +msgid "Enter a valid Social Security number." +msgstr "" + +#: contrib/localflavor/it/forms.py:68 +msgid "Enter a valid VAT number." +msgstr "" + +#: contrib/localflavor/br/forms.py:23 +msgid "Enter a zip code in the format XXXXX-XXX." +msgstr "" + +#: contrib/localflavor/br/forms.py:35 +msgid "Phone numbers must be in XX-XXXX-XXXX format." +msgstr "" + +#: contrib/localflavor/br/forms.py:68 +msgid "Select a valid brazilian state. That state is not one of the available states." +msgstr "" + +#: contrib/localflavor/br/forms.py:105 +msgid "This field requires at most 11 digits or 14 characters." +msgstr "" + +#: contrib/localflavor/br/forms.py:115 +msgid "Invalid CPF number." +msgstr "" + +#: contrib/localflavor/br/forms.py:137 +msgid "This field requires at least 14 digits" +msgstr "" + +#: contrib/localflavor/br/forms.py:147 +msgid "Invalid CNPJ number." +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:20 +msgid "th" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:20 +msgid "st" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:20 +msgid "nd" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:20 +msgid "rd" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:50 +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "" +msgstr[1] "" + +#: contrib/humanize/templatetags/humanize.py:53 +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "" +msgstr[1] "" + +#: contrib/humanize/templatetags/humanize.py:56 +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "" +msgstr[1] "" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "one" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "two" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "three" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "four" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "five" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "six" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "seven" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "eight" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "nine" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:90 +msgid "today" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:92 +msgid "tomorrow" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:94 +msgid "yesterday" +msgstr "" + +#: contrib/admin/filterspecs.py:42 +#, python-format +msgid "" +"<h3>By %s:</h3>\n" +"<ul>\n" +msgstr "" + +#: contrib/admin/filterspecs.py:72 +#: contrib/admin/filterspecs.py:90 +#: contrib/admin/filterspecs.py:145 +#: contrib/admin/filterspecs.py:171 +msgid "All" +msgstr "" + +#: contrib/admin/filterspecs.py:111 +msgid "Any date" +msgstr "" + +#: contrib/admin/filterspecs.py:112 +msgid "Today" +msgstr "" + +#: contrib/admin/filterspecs.py:115 +msgid "Past 7 days" +msgstr "" + +#: contrib/admin/filterspecs.py:117 +msgid "This month" +msgstr "" + +#: contrib/admin/filterspecs.py:119 +msgid "This year" +msgstr "" + +#: contrib/admin/filterspecs.py:145 +#: newforms/widgets.py:188 +#: oldforms/__init__.py:591 +msgid "Yes" +msgstr "" + +#: contrib/admin/filterspecs.py:145 +#: newforms/widgets.py:188 +#: oldforms/__init__.py:591 +msgid "No" +msgstr "" + +#: contrib/admin/filterspecs.py:152 +#: newforms/widgets.py:188 +#: oldforms/__init__.py:591 +msgid "Unknown" +msgstr "" + +#: contrib/admin/models.py:17 +msgid "action time" +msgstr "" + +#: contrib/admin/models.py:20 +msgid "object id" +msgstr "" + +#: contrib/admin/models.py:21 +msgid "object repr" +msgstr "" + +#: contrib/admin/models.py:22 +msgid "action flag" +msgstr "" + +#: contrib/admin/models.py:23 +msgid "change message" +msgstr "" + +#: contrib/admin/models.py:26 +msgid "log entry" +msgstr "" + +#: contrib/admin/models.py:27 +msgid "log entries" +msgstr "" + +#: contrib/admin/templates/widget/file.html:2 +msgid "Currently:" +msgstr "" + +#: contrib/admin/templates/widget/file.html:3 +msgid "Change:" +msgstr "" + +#: contrib/admin/templates/widget/date_time.html:3 +msgid "Date:" +msgstr "" + +#: contrib/admin/templates/widget/date_time.html:4 +msgid "Time:" +msgstr "" + +#: contrib/admin/templates/admin/delete_confirmation.html:3 +#: contrib/admin/templates/admin/object_history.html:3 +#: contrib/admin/templates/admin/change_form.html:10 +#: contrib/admin/templates/admin/change_list.html:5 +#: contrib/admin/templates/admin/base.html:25 +#: contrib/admin/templates/admin/auth/user/change_password.html:9 +#: contrib/admin/templates/admin_doc/bookmarklets.html:3 +#: contrib/admin/templates/registration/password_change_form.html:3 +#: contrib/admin/templates/registration/password_change_done.html:3 +msgid "Documentation" +msgstr "" + +#: contrib/admin/templates/admin/delete_confirmation.html:3 +#: contrib/admin/templates/admin/object_history.html:3 +#: contrib/admin/templates/admin/change_form.html:10 +#: contrib/admin/templates/admin/change_list.html:5 +#: contrib/admin/templates/admin/base.html:25 +#: contrib/admin/templates/admin/auth/user/change_password.html:9 +#: contrib/admin/templates/admin/auth/user/change_password.html:15 +#: contrib/admin/templates/admin/auth/user/change_password.html:46 +#: contrib/admin/templates/admin_doc/view_detail.html:4 +#: contrib/admin/templates/admin_doc/template_tag_index.html:5 +#: contrib/admin/templates/admin_doc/view_index.html:5 +#: contrib/admin/templates/admin_doc/model_index.html:5 +#: contrib/admin/templates/admin_doc/template_detail.html:4 +#: contrib/admin/templates/admin_doc/index.html:4 +#: contrib/admin/templates/admin_doc/missing_docutils.html:4 +#: contrib/admin/templates/admin_doc/model_detail.html:3 +#: contrib/admin/templates/admin_doc/template_filter_index.html:5 +#: contrib/admin/templates/admin_doc/bookmarklets.html:4 +#: contrib/admin/templates/registration/password_change_form.html:3 +#: contrib/admin/templates/registration/password_change_done.html:3 +msgid "Change password" +msgstr "" + +#: contrib/admin/templates/admin/delete_confirmation.html:3 +#: contrib/admin/templates/admin/object_history.html:3 +#: contrib/admin/templates/admin/change_form.html:10 +#: contrib/admin/templates/admin/change_list.html:5 +#: contrib/admin/templates/admin/base.html:25 +#: contrib/admin/templates/admin/auth/user/change_password.html:9 +#: contrib/admin/templates/admin_doc/view_detail.html:4 +#: contrib/admin/templates/admin_doc/template_tag_index.html:5 +#: contrib/admin/templates/admin_doc/view_index.html:5 +#: contrib/admin/templates/admin_doc/model_index.html:5 +#: contrib/admin/templates/admin_doc/template_detail.html:4 +#: contrib/admin/templates/admin_doc/index.html:4 +#: contrib/admin/templates/admin_doc/missing_docutils.html:4 +#: contrib/admin/templates/admin_doc/model_detail.html:3 +#: contrib/admin/templates/admin_doc/template_filter_index.html:5 +#: contrib/admin/templates/admin_doc/bookmarklets.html:4 +#: contrib/admin/templates/registration/password_change_form.html:3 +#: contrib/admin/templates/registration/password_change_done.html:3 +#: contrib/comments/templates/comments/form.html:6 +msgid "Log out" +msgstr "" + +#: contrib/admin/templates/admin/delete_confirmation.html:6 +#: contrib/admin/templates/admin/object_history.html:5 +#: contrib/admin/templates/admin/500.html:4 +#: contrib/admin/templates/admin/change_form.html:13 +#: contrib/admin/templates/admin/invalid_setup.html:4 +#: contrib/admin/templates/admin/change_list.html:6 +#: contrib/admin/templates/admin/base.html:30 +#: contrib/admin/templates/admin/auth/user/change_password.html:12 +#: contrib/admin/templates/admin_doc/bookmarklets.html:3 +#: contrib/admin/templates/registration/password_change_form.html:4 +#: contrib/admin/templates/registration/password_change_done.html:4 +#: contrib/admin/templates/registration/logged_out.html:4 +#: contrib/admin/templates/registration/password_reset_form.html:4 +#: contrib/admin/templates/registration/password_reset_done.html:4 +msgid "Home" +msgstr "" + +#: contrib/admin/templates/admin/delete_confirmation.html:9 +#: contrib/admin/templates/admin/submit_line.html:3 +msgid "Delete" +msgstr "" + +#: contrib/admin/templates/admin/delete_confirmation.html:14 +#, python-format +msgid "Deleting the %(object_name)s '%(escaped_object)s' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" +msgstr "" + +#: contrib/admin/templates/admin/delete_confirmation.html:21 +#, python-format +msgid "Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? All of the following related items will be deleted:" +msgstr "" + +#: contrib/admin/templates/admin/delete_confirmation.html:26 +msgid "Yes, I'm sure" +msgstr "" + +#: contrib/admin/templates/admin/object_history.html:5 +#: contrib/admin/templates/admin/change_form.html:21 +msgid "History" +msgstr "" + +#: contrib/admin/templates/admin/object_history.html:18 +msgid "Date/time" +msgstr "" + +#: contrib/admin/templates/admin/object_history.html:19 +msgid "User" +msgstr "" + +#: contrib/admin/templates/admin/object_history.html:20 +msgid "Action" +msgstr "" + +#: contrib/admin/templates/admin/object_history.html:26 +msgid "DATE_WITH_TIME_FULL" +msgstr "" + +#: contrib/admin/templates/admin/object_history.html:36 +msgid "This object doesn't have a change history. It probably wasn't added via this admin site." +msgstr "" + +#: contrib/admin/templates/admin/login.html:17 +#: contrib/comments/templates/comments/form.html:6 +#: contrib/comments/templates/comments/form.html:8 +msgid "Username:" +msgstr "" + +#: contrib/admin/templates/admin/login.html:20 +#: contrib/comments/templates/comments/form.html:8 +msgid "Password:" +msgstr "" + +#: contrib/admin/templates/admin/login.html:25 +#: contrib/admin/views/decorators.py:24 +msgid "Log in" +msgstr "" + +#: contrib/admin/templates/admin/pagination.html:10 +msgid "Show all" +msgstr "" + +#: contrib/admin/templates/admin/500.html:4 +msgid "Server error" +msgstr "" + +#: contrib/admin/templates/admin/500.html:6 +msgid "Server error (500)" +msgstr "" + +#: contrib/admin/templates/admin/500.html:9 +msgid "Server Error <em>(500)</em>" +msgstr "" + +#: contrib/admin/templates/admin/500.html:10 +msgid "There's been an error. It's been reported to the site administrators via e-mail and should be fixed shortly. Thanks for your patience." +msgstr "" + +#: contrib/admin/templates/admin/change_form.html:15 +#: contrib/admin/templates/admin/index.html:28 +msgid "Add" +msgstr "" + +#: contrib/admin/templates/admin/change_form.html:22 +msgid "View on site" +msgstr "" + +#: contrib/admin/templates/admin/change_form.html:32 +#: contrib/admin/templates/admin/auth/user/change_password.html:24 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "" +msgstr[1] "" + +#: contrib/admin/templates/admin/change_form.html:50 +msgid "Ordering" +msgstr "" + +#: contrib/admin/templates/admin/change_form.html:53 +msgid "Order:" +msgstr "" + +#: contrib/admin/templates/admin/filter.html:2 +#, python-format +msgid " By %(filter_title)s " +msgstr "" + +#: contrib/admin/templates/admin/invalid_setup.html:8 +msgid "Something's wrong with your database installation. Make sure the appropriate database tables have been created, and make sure the database is readable by the appropriate user." +msgstr "" + +#: contrib/admin/templates/admin/index.html:17 +#, python-format +msgid "Models available in the %(name)s application." +msgstr "" + +#: contrib/admin/templates/admin/index.html:18 +#, python-format +msgid "%(name)s" +msgstr "" + +#: contrib/admin/templates/admin/index.html:34 +msgid "Change" +msgstr "" + +#: contrib/admin/templates/admin/index.html:44 +msgid "You don't have permission to edit anything." +msgstr "" + +#: contrib/admin/templates/admin/index.html:52 +msgid "Recent Actions" +msgstr "" + +#: contrib/admin/templates/admin/index.html:53 +msgid "My Actions" +msgstr "" + +#: contrib/admin/templates/admin/index.html:57 +msgid "None available" +msgstr "" + +#: contrib/admin/templates/admin/404.html:4 +#: contrib/admin/templates/admin/404.html:8 +msgid "Page not found" +msgstr "" + +#: contrib/admin/templates/admin/404.html:10 +msgid "We're sorry, but the requested page could not be found." +msgstr "" + +#: contrib/admin/templates/admin/filters.html:4 +msgid "Filter" +msgstr "" + +#: contrib/admin/templates/admin/search_form.html:8 +msgid "Go" +msgstr "" + +#: contrib/admin/templates/admin/search_form.html:10 +#, python-format +msgid "1 result" +msgid_plural "%(counter)s results" +msgstr[0] "" +msgstr[1] "" + +#: contrib/admin/templates/admin/search_form.html:10 +#, python-format +msgid "%(full_result_count)s total" +msgstr "" + +#: contrib/admin/templates/admin/submit_line.html:4 +msgid "Save as new" +msgstr "" + +#: contrib/admin/templates/admin/submit_line.html:5 +msgid "Save and add another" +msgstr "" + +#: contrib/admin/templates/admin/submit_line.html:6 +msgid "Save and continue editing" +msgstr "" + +#: contrib/admin/templates/admin/submit_line.html:7 +msgid "Save" +msgstr "" + +#: contrib/admin/templates/admin/base_site.html:4 +msgid "Django site admin" +msgstr "" + +#: contrib/admin/templates/admin/base_site.html:7 +msgid "Django administration" +msgstr "" + +#: contrib/admin/templates/admin/change_list.html:12 +#, python-format +msgid "Add %(name)s" +msgstr "" + +#: contrib/admin/templates/admin/base.html:25 +msgid "Welcome," +msgstr "" + +#: contrib/admin/templates/admin/auth/user/change_password.html:28 +#, python-format +msgid "Enter a new password for the user <strong>%(username)s</strong>." +msgstr "" + +#: contrib/admin/templates/admin/auth/user/change_password.html:34 +#: contrib/admin/templates/admin/auth/user/add_form.html:18 +msgid "Password" +msgstr "" + +#: contrib/admin/templates/admin/auth/user/change_password.html:39 +#: contrib/admin/templates/admin/auth/user/add_form.html:23 +msgid "Password (again)" +msgstr "" + +#: contrib/admin/templates/admin/auth/user/change_password.html:40 +#: contrib/admin/templates/admin/auth/user/add_form.html:24 +msgid "Enter the same password as above, for verification." +msgstr "" + +#: contrib/admin/templates/admin/auth/user/add_form.html:6 +msgid "First, enter a username and password. Then, you'll be able to edit more user options." +msgstr "" + +#: contrib/admin/templates/admin/auth/user/add_form.html:12 +msgid "Username" +msgstr "" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:3 +msgid "Bookmarklets" +msgstr "" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:5 +msgid "Documentation bookmarklets" +msgstr "" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:9 +msgid "" +"\n" +"<p class=\"help\">To install bookmarklets, drag the link to your bookmarks\n" +"toolbar, or right-click the link and add it to your bookmarks. Now you can\n" +"select the bookmarklet from any page in the site. Note that some of these\n" +"bookmarklets require you to be viewing the site from a computer designated\n" +"as \"internal\" (talk to your system administrator if you aren't sure if\n" +"your computer is \"internal\").</p>\n" +msgstr "" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:19 +msgid "Documentation for this page" +msgstr "" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:20 +msgid "Jumps you from any page to the documentation for the view that generates that page." +msgstr "" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:22 +msgid "Show object ID" +msgstr "" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:23 +msgid "Shows the content-type and unique ID for pages that represent a single object." +msgstr "" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:25 +msgid "Edit this object (current window)" +msgstr "" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:26 +msgid "Jumps to the admin page for pages that represent a single object." +msgstr "" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:28 +msgid "Edit this object (new window)" +msgstr "" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:29 +msgid "As above, but opens the admin page in a new window." +msgstr "" + +#: contrib/admin/templates/registration/password_change_form.html:4 +#: contrib/admin/templates/registration/password_change_form.html:6 +#: contrib/admin/templates/registration/password_change_form.html:10 +#: contrib/admin/templates/registration/password_change_done.html:4 +msgid "Password change" +msgstr "" + +#: contrib/admin/templates/registration/password_change_form.html:12 +msgid "Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly." +msgstr "" + +#: contrib/admin/templates/registration/password_change_form.html:17 +msgid "Old password:" +msgstr "" + +#: contrib/admin/templates/registration/password_change_form.html:19 +msgid "New password:" +msgstr "" + +#: contrib/admin/templates/registration/password_change_form.html:21 +msgid "Confirm password:" +msgstr "" + +#: contrib/admin/templates/registration/password_change_form.html:23 +msgid "Change my password" +msgstr "" + +#: contrib/admin/templates/registration/password_change_done.html:6 +#: contrib/admin/templates/registration/password_change_done.html:10 +msgid "Password change successful" +msgstr "" + +#: contrib/admin/templates/registration/password_change_done.html:12 +msgid "Your password was changed." +msgstr "" + +#: contrib/admin/templates/registration/logged_out.html:8 +msgid "Thanks for spending some quality time with the Web site today." +msgstr "" + +#: contrib/admin/templates/registration/logged_out.html:10 +msgid "Log in again" +msgstr "" + +#: contrib/admin/templates/registration/password_reset_email.html:2 +msgid "You're receiving this e-mail because you requested a password reset" +msgstr "" + +#: contrib/admin/templates/registration/password_reset_email.html:3 +#, python-format +msgid "for your user account at %(site_name)s" +msgstr "" + +#: contrib/admin/templates/registration/password_reset_email.html:5 +#, python-format +msgid "Your new password is: %(new_password)s" +msgstr "" + +#: contrib/admin/templates/registration/password_reset_email.html:7 +msgid "Feel free to change this password by going to this page:" +msgstr "" + +#: contrib/admin/templates/registration/password_reset_email.html:11 +msgid "Your username, in case you've forgotten:" +msgstr "" + +#: contrib/admin/templates/registration/password_reset_email.html:13 +msgid "Thanks for using our site!" +msgstr "" + +#: contrib/admin/templates/registration/password_reset_email.html:15 +#, python-format +msgid "The %(site_name)s team" +msgstr "" + +#: contrib/admin/templates/registration/password_reset_form.html:4 +#: contrib/admin/templates/registration/password_reset_form.html:6 +#: contrib/admin/templates/registration/password_reset_form.html:10 +#: contrib/admin/templates/registration/password_reset_done.html:4 +msgid "Password reset" +msgstr "" + +#: contrib/admin/templates/registration/password_reset_form.html:12 +msgid "Forgotten your password? Enter your e-mail address below, and we'll reset your password and e-mail the new one to you." +msgstr "" + +#: contrib/admin/templates/registration/password_reset_form.html:16 +msgid "E-mail address:" +msgstr "" + +#: contrib/admin/templates/registration/password_reset_form.html:16 +msgid "Reset my password" +msgstr "" + +#: contrib/admin/templates/registration/password_reset_done.html:6 +#: contrib/admin/templates/registration/password_reset_done.html:10 +msgid "Password reset successful" +msgstr "" + +#: contrib/admin/templates/registration/password_reset_done.html:12 +msgid "We've e-mailed a new password to the e-mail address you submitted. You should be receiving it shortly." +msgstr "" + +#: contrib/admin/views/decorators.py:10 +#: contrib/auth/forms.py:60 +msgid "Please enter a correct username and password. Note that both fields are case-sensitive." +msgstr "" + +#: contrib/admin/views/decorators.py:62 +msgid "Please log in again, because your session has expired. Don't worry: Your submission has been saved." +msgstr "" + +#: contrib/admin/views/decorators.py:69 +msgid "Looks like your browser isn't configured to accept cookies. Please enable cookies, reload this page, and try again." +msgstr "" + +#: contrib/admin/views/decorators.py:83 +msgid "Usernames cannot contain the '@' character." +msgstr "" + +#: contrib/admin/views/decorators.py:85 +#, python-format +msgid "Your e-mail address is not your username. Try '%s' instead." +msgstr "" + +#: contrib/admin/views/doc.py:47 +#: contrib/admin/views/doc.py:49 +#: contrib/admin/views/doc.py:51 +msgid "tag:" +msgstr "" + +#: contrib/admin/views/doc.py:78 +#: contrib/admin/views/doc.py:80 +#: contrib/admin/views/doc.py:82 +msgid "filter:" +msgstr "" + +#: contrib/admin/views/doc.py:136 +#: contrib/admin/views/doc.py:138 +#: contrib/admin/views/doc.py:140 +msgid "view:" +msgstr "" + +#: contrib/admin/views/doc.py:165 +#, python-format +msgid "App %r not found" +msgstr "" + +#: contrib/admin/views/doc.py:172 +#, python-format +msgid "Model %(name)r not found in app %(label)r" +msgstr "" + +#: contrib/admin/views/doc.py:184 +#, python-format +msgid "the related `%(label)s.%(type)s` object" +msgstr "" + +#: contrib/admin/views/doc.py:184 +#: contrib/admin/views/doc.py:206 +#: contrib/admin/views/doc.py:220 +#: contrib/admin/views/doc.py:225 +msgid "model:" +msgstr "" + +#: contrib/admin/views/doc.py:215 +#, python-format +msgid "related `%(label)s.%(name)s` objects" +msgstr "" + +#: contrib/admin/views/doc.py:220 +#, python-format +msgid "all %s" +msgstr "" + +#: contrib/admin/views/doc.py:225 +#, python-format +msgid "number of %s" +msgstr "" + +#: contrib/admin/views/doc.py:230 +#, python-format +msgid "Fields on %s objects" +msgstr "" + +#: contrib/admin/views/doc.py:292 +#: contrib/admin/views/doc.py:303 +#: contrib/admin/views/doc.py:305 +#: contrib/admin/views/doc.py:311 +#: contrib/admin/views/doc.py:312 +#: contrib/admin/views/doc.py:314 +msgid "Integer" +msgstr "" + +#: contrib/admin/views/doc.py:293 +msgid "Boolean (Either True or False)" +msgstr "" + +#: contrib/admin/views/doc.py:294 +#: contrib/admin/views/doc.py:313 +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "" + +#: contrib/admin/views/doc.py:295 +msgid "Comma-separated integers" +msgstr "" + +#: contrib/admin/views/doc.py:296 +msgid "Date (without time)" +msgstr "" + +#: contrib/admin/views/doc.py:297 +msgid "Date (with time)" +msgstr "" + +#: contrib/admin/views/doc.py:298 +msgid "Decimal number" +msgstr "" + +#: contrib/admin/views/doc.py:299 +msgid "E-mail address" +msgstr "" + +#: contrib/admin/views/doc.py:300 +#: contrib/admin/views/doc.py:301 +#: contrib/admin/views/doc.py:304 +msgid "File path" +msgstr "" + +#: contrib/admin/views/doc.py:302 +msgid "Floating point number" +msgstr "" + +#: contrib/admin/views/doc.py:306 +#: contrib/comments/models.py:85 +msgid "IP address" +msgstr "" + +#: contrib/admin/views/doc.py:308 +msgid "Boolean (Either True, False or None)" +msgstr "" + +#: contrib/admin/views/doc.py:309 +msgid "Relation to parent model" +msgstr "" + +#: contrib/admin/views/doc.py:310 +msgid "Phone number" +msgstr "" + +#: contrib/admin/views/doc.py:315 +msgid "Text" +msgstr "" + +#: contrib/admin/views/doc.py:316 +msgid "Time" +msgstr "" + +#: contrib/admin/views/doc.py:318 +msgid "U.S. state (two uppercase letters)" +msgstr "" + +#: contrib/admin/views/doc.py:319 +msgid "XML text" +msgstr "" + +#: contrib/admin/views/doc.py:345 +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "" + +#: contrib/admin/views/auth.py:20 +#: contrib/admin/views/main.py:264 +#, python-format +msgid "The %(name)s \"%(obj)s\" was added successfully." +msgstr "" + +#: contrib/admin/views/auth.py:25 +#: contrib/admin/views/main.py:268 +#: contrib/admin/views/main.py:354 +msgid "You may edit it again below." +msgstr "" + +#: contrib/admin/views/auth.py:31 +msgid "Add user" +msgstr "" + +#: contrib/admin/views/auth.py:58 +msgid "Password changed successfully." +msgstr "" + +#: contrib/admin/views/auth.py:65 +#, python-format +msgid "Change password: %s" +msgstr "" + +#: contrib/admin/views/main.py:230 +msgid "Site administration" +msgstr "" + +#: contrib/admin/views/main.py:278 +#: contrib/admin/views/main.py:363 +#, python-format +msgid "You may add another %s below." +msgstr "" + +#: contrib/admin/views/main.py:296 +#, python-format +msgid "Add %s" +msgstr "" + +#: contrib/admin/views/main.py:342 +#, python-format +msgid "Added %s." +msgstr "" + +#: contrib/admin/views/main.py:344 +#, python-format +msgid "Changed %s." +msgstr "" + +#: contrib/admin/views/main.py:346 +#, python-format +msgid "Deleted %s." +msgstr "" + +#: contrib/admin/views/main.py:349 +msgid "No fields changed." +msgstr "" + +#: contrib/admin/views/main.py:352 +#, python-format +msgid "The %(name)s \"%(obj)s\" was changed successfully." +msgstr "" + +#: contrib/admin/views/main.py:360 +#, python-format +msgid "The %(name)s \"%(obj)s\" was added successfully. You may edit it again below." +msgstr "" + +#: contrib/admin/views/main.py:398 +#, python-format +msgid "Change %s" +msgstr "" + +#: contrib/admin/views/main.py:483 +#, python-format +msgid "One or more %(fieldname)s in %(name)s: %(obj)s" +msgstr "" + +#: contrib/admin/views/main.py:488 +#, python-format +msgid "One or more %(fieldname)s in %(name)s:" +msgstr "" + +#: contrib/admin/views/main.py:520 +#, python-format +msgid "The %(name)s \"%(obj)s\" was deleted successfully." +msgstr "" + +#: contrib/admin/views/main.py:523 +msgid "Are you sure?" +msgstr "" + +#: contrib/admin/views/main.py:545 +#, python-format +msgid "Change history: %s" +msgstr "" + +#: contrib/admin/views/main.py:579 +#, python-format +msgid "Select %s" +msgstr "" + +#: contrib/admin/views/main.py:579 +#, python-format +msgid "Select %s to change" +msgstr "" + +#: contrib/admin/views/main.py:780 +msgid "Database error" +msgstr "" + +#: contrib/admin/templatetags/admin_list.py:254 +msgid "All dates" +msgstr "" + +#: contrib/auth/forms.py:17 +#: contrib/auth/forms.py:138 +msgid "The two password fields didn't match." +msgstr "" + +#: contrib/auth/forms.py:25 +msgid "A user with that username already exists." +msgstr "" + +#: contrib/auth/forms.py:53 +msgid "Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in." +msgstr "" + +#: contrib/auth/forms.py:62 +msgid "This account is inactive." +msgstr "" + +#: contrib/auth/forms.py:84 +msgid "That e-mail address doesn't have an associated user account. Are you sure you've registered?" +msgstr "" + +#: contrib/auth/forms.py:117 +msgid "The two 'new password' fields didn't match." +msgstr "" + +#: contrib/auth/forms.py:124 +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" + +#: contrib/auth/views.py:47 +msgid "Logged out" +msgstr "" + +#: contrib/auth/models.py:53 +#: contrib/auth/models.py:73 +msgid "name" +msgstr "" + +#: contrib/auth/models.py:55 +msgid "codename" +msgstr "" + +#: contrib/auth/models.py:58 +msgid "permission" +msgstr "" + +#: contrib/auth/models.py:59 +#: contrib/auth/models.py:74 +msgid "permissions" +msgstr "" + +#: contrib/auth/models.py:77 +msgid "group" +msgstr "" + +#: contrib/auth/models.py:78 +#: contrib/auth/models.py:121 +msgid "groups" +msgstr "" + +#: contrib/auth/models.py:111 +msgid "username" +msgstr "" + +#: contrib/auth/models.py:111 +msgid "Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores)." +msgstr "" + +#: contrib/auth/models.py:112 +msgid "first name" +msgstr "" + +#: contrib/auth/models.py:113 +msgid "last name" +msgstr "" + +#: contrib/auth/models.py:114 +msgid "e-mail address" +msgstr "" + +#: contrib/auth/models.py:115 +msgid "password" +msgstr "" + +#: contrib/auth/models.py:115 +msgid "Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change password form</a>." +msgstr "" + +#: contrib/auth/models.py:116 +msgid "staff status" +msgstr "" + +#: contrib/auth/models.py:116 +msgid "Designates whether the user can log into this admin site." +msgstr "" + +#: contrib/auth/models.py:117 +msgid "active" +msgstr "" + +#: contrib/auth/models.py:117 +msgid "Designates whether this user can log into the Django admin. Unselect this instead of deleting accounts." +msgstr "" + +#: contrib/auth/models.py:118 +msgid "superuser status" +msgstr "" + +#: contrib/auth/models.py:118 +msgid "Designates that this user has all permissions without explicitly assigning them." +msgstr "" + +#: contrib/auth/models.py:119 +msgid "last login" +msgstr "" + +#: contrib/auth/models.py:120 +msgid "date joined" +msgstr "" + +#: contrib/auth/models.py:122 +msgid "In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in." +msgstr "" + +#: contrib/auth/models.py:123 +msgid "user permissions" +msgstr "" + +#: contrib/auth/models.py:127 +msgid "user" +msgstr "" + +#: contrib/auth/models.py:128 +msgid "users" +msgstr "" + +#: contrib/auth/models.py:134 +msgid "Personal info" +msgstr "" + +#: contrib/auth/models.py:135 +msgid "Permissions" +msgstr "" + +#: contrib/auth/models.py:136 +msgid "Important dates" +msgstr "" + +#: contrib/auth/models.py:137 +msgid "Groups" +msgstr "" + +#: contrib/auth/models.py:288 +msgid "message" +msgstr "" + +#: contrib/sessions/models.py:68 +msgid "session key" +msgstr "" + +#: contrib/sessions/models.py:69 +msgid "session data" +msgstr "" + +#: contrib/sessions/models.py:70 +msgid "expire date" +msgstr "" + +#: contrib/sessions/models.py:74 +msgid "session" +msgstr "" + +#: contrib/sessions/models.py:75 +msgid "sessions" +msgstr "" + +#: contrib/contenttypes/models.py:37 +msgid "python model class name" +msgstr "" + +#: contrib/contenttypes/models.py:40 +msgid "content type" +msgstr "" + +#: contrib/contenttypes/models.py:41 +msgid "content types" +msgstr "" + +#: contrib/sites/models.py:33 +msgid "domain name" +msgstr "" + +#: contrib/sites/models.py:34 +msgid "display name" +msgstr "" + +#: contrib/sites/models.py:38 +msgid "site" +msgstr "" + +#: contrib/sites/models.py:39 +msgid "sites" +msgstr "" + +#: contrib/comments/models.py:67 +#: contrib/comments/models.py:169 +msgid "object ID" +msgstr "" + +#: contrib/comments/models.py:68 +msgid "headline" +msgstr "" + +#: contrib/comments/models.py:69 +#: contrib/comments/models.py:90 +#: contrib/comments/models.py:170 +msgid "comment" +msgstr "" + +#: contrib/comments/models.py:70 +msgid "rating #1" +msgstr "" + +#: contrib/comments/models.py:71 +msgid "rating #2" +msgstr "" + +#: contrib/comments/models.py:72 +msgid "rating #3" +msgstr "" + +#: contrib/comments/models.py:73 +msgid "rating #4" +msgstr "" + +#: contrib/comments/models.py:74 +msgid "rating #5" +msgstr "" + +#: contrib/comments/models.py:75 +msgid "rating #6" +msgstr "" + +#: contrib/comments/models.py:76 +msgid "rating #7" +msgstr "" + +#: contrib/comments/models.py:77 +msgid "rating #8" +msgstr "" + +#: contrib/comments/models.py:82 +msgid "is valid rating" +msgstr "" + +#: contrib/comments/models.py:83 +#: contrib/comments/models.py:172 +msgid "date/time submitted" +msgstr "" + +#: contrib/comments/models.py:84 +#: contrib/comments/models.py:173 +msgid "is public" +msgstr "" + +#: contrib/comments/models.py:86 +msgid "is removed" +msgstr "" + +#: contrib/comments/models.py:86 +msgid "Check this box if the comment is inappropriate. A \"This comment has been removed\" message will be displayed instead." +msgstr "" + +#: contrib/comments/models.py:91 +msgid "comments" +msgstr "" + +#: contrib/comments/models.py:134 +#: contrib/comments/models.py:213 +msgid "Content object" +msgstr "" + +#: contrib/comments/models.py:162 +#, python-format +msgid "" +"Posted by %(user)s at %(date)s\n" +"\n" +"%(comment)s\n" +"\n" +"http://%(domain)s%(url)s" +msgstr "" + +#: contrib/comments/models.py:171 +msgid "person's name" +msgstr "" + +#: contrib/comments/models.py:174 +msgid "ip address" +msgstr "" + +#: contrib/comments/models.py:176 +msgid "approved by staff" +msgstr "" + +#: contrib/comments/models.py:179 +msgid "free comment" +msgstr "" + +#: contrib/comments/models.py:180 +msgid "free comments" +msgstr "" + +#: contrib/comments/models.py:239 +msgid "score" +msgstr "" + +#: contrib/comments/models.py:240 +msgid "score date" +msgstr "" + +#: contrib/comments/models.py:243 +msgid "karma score" +msgstr "" + +#: contrib/comments/models.py:244 +msgid "karma scores" +msgstr "" + +#: contrib/comments/models.py:248 +#, python-format +msgid "%(score)d rating by %(user)s" +msgstr "" + +#: contrib/comments/models.py:264 +#, python-format +msgid "" +"This comment was flagged by %(user)s:\n" +"\n" +"%(text)s" +msgstr "" + +#: contrib/comments/models.py:271 +msgid "flag date" +msgstr "" + +#: contrib/comments/models.py:274 +msgid "user flag" +msgstr "" + +#: contrib/comments/models.py:275 +msgid "user flags" +msgstr "" + +#: contrib/comments/models.py:279 +#, python-format +msgid "Flag by %r" +msgstr "" + +#: contrib/comments/models.py:284 +msgid "deletion date" +msgstr "" + +#: contrib/comments/models.py:286 +msgid "moderator deletion" +msgstr "" + +#: contrib/comments/models.py:287 +msgid "moderator deletions" +msgstr "" + +#: contrib/comments/models.py:291 +#, python-format +msgid "Moderator deletion by %r" +msgstr "" + +#: contrib/comments/templates/comments/form.html:8 +msgid "Forgotten your password?" +msgstr "" + +#: contrib/comments/templates/comments/form.html:12 +msgid "Ratings" +msgstr "" + +#: contrib/comments/templates/comments/form.html:12 +#: contrib/comments/templates/comments/form.html:23 +msgid "Required" +msgstr "" + +#: contrib/comments/templates/comments/form.html:12 +#: contrib/comments/templates/comments/form.html:23 +msgid "Optional" +msgstr "" + +#: contrib/comments/templates/comments/form.html:23 +msgid "Post a photo" +msgstr "" + +#: contrib/comments/templates/comments/form.html:28 +#: contrib/comments/templates/comments/freeform.html:5 +msgid "Comment:" +msgstr "" + +#: contrib/comments/templates/comments/form.html:35 +#: contrib/comments/templates/comments/freeform.html:10 +msgid "Preview comment" +msgstr "" + +#: contrib/comments/templates/comments/freeform.html:4 +msgid "Your name:" +msgstr "" + +#: contrib/comments/views/karma.py:20 +msgid "Anonymous users cannot vote" +msgstr "" + +#: contrib/comments/views/karma.py:24 +msgid "Invalid comment ID" +msgstr "" + +#: contrib/comments/views/karma.py:26 +msgid "No voting for yourself" +msgstr "" + +#: contrib/comments/views/comments.py:28 +msgid "This rating is required because you've entered at least one other rating." +msgstr "" + +#: contrib/comments/views/comments.py:112 +#, python-format +msgid "" +"This comment was posted by a user who has posted fewer than %(count)s comment:\n" +"\n" +"%(text)s" +msgid_plural "" +"This comment was posted by a user who has posted fewer than %(count)s comments:\n" +"\n" +"%(text)s" +msgstr[0] "" +msgstr[1] "" + +#: contrib/comments/views/comments.py:117 +#, python-format +msgid "" +"This comment was posted by a sketchy user:\n" +"\n" +"%(text)s" +msgstr "" + +#: contrib/comments/views/comments.py:189 +#: contrib/comments/views/comments.py:281 +msgid "Only POSTs are allowed" +msgstr "" + +#: contrib/comments/views/comments.py:193 +#: contrib/comments/views/comments.py:285 +msgid "One or more of the required fields wasn't submitted" +msgstr "" + +#: contrib/comments/views/comments.py:197 +#: contrib/comments/views/comments.py:287 +msgid "Somebody tampered with the comment form (security violation)" +msgstr "" + +#: contrib/comments/views/comments.py:207 +#: contrib/comments/views/comments.py:293 +msgid "The comment form had an invalid 'target' parameter -- the object ID was invalid" +msgstr "" + +#: contrib/comments/views/comments.py:258 +#: contrib/comments/views/comments.py:322 +msgid "The comment form didn't provide either 'preview' or 'post'" +msgstr "" + +#: newforms/fields.py:123 +#, python-format +msgid "Ensure this value has at most %(max)d characters (it has %(length)d)." +msgstr "" + +#: newforms/fields.py:125 +#, python-format +msgid "Ensure this value has at least %(min)d characters (it has %(length)d)." +msgstr "" + +#: newforms/fields.py:149 +#: core/validators.py:128 +msgid "Enter a whole number." +msgstr "" + +#: newforms/fields.py:151 +#: newforms/fields.py:174 +#: newforms/fields.py:204 +#, python-format +msgid "Ensure this value is less than or equal to %s." +msgstr "" + +#: newforms/fields.py:153 +#: newforms/fields.py:176 +#: newforms/fields.py:206 +#, python-format +msgid "Ensure this value is greater than or equal to %s." +msgstr "" + +#: newforms/fields.py:172 +#: newforms/fields.py:199 +msgid "Enter a number." +msgstr "" + +#: newforms/fields.py:208 +#, python-format +msgid "Ensure that there are no more than %s digits in total." +msgstr "" + +#: newforms/fields.py:210 +#, python-format +msgid "Ensure that there are no more than %s decimal places." +msgstr "" + +#: newforms/fields.py:212 +#, python-format +msgid "Ensure that there are no more than %s digits before the decimal point." +msgstr "" + +#: newforms/fields.py:245 +#: newforms/fields.py:629 +msgid "Enter a valid date." +msgstr "" + +#: newforms/fields.py:272 +#: newforms/fields.py:631 +msgid "Enter a valid time." +msgstr "" + +#: newforms/fields.py:308 +msgid "Enter a valid date/time." +msgstr "" + +#: newforms/fields.py:321 +msgid "Enter a valid value." +msgstr "" + +#: newforms/fields.py:343 +#: core/validators.py:170 +msgid "Enter a valid e-mail address." +msgstr "" + +#: newforms/fields.py:377 +#: oldforms/__init__.py:686 +#: core/validators.py:182 +#: core/validators.py:469 +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" + +#: newforms/fields.py:379 +msgid "No file was submitted." +msgstr "" + +#: newforms/fields.py:381 +#: oldforms/__init__.py:688 +msgid "The submitted file is empty." +msgstr "" + +#: newforms/fields.py:405 +#: core/validators.py:193 +msgid "Upload a valid image. The file you uploaded was either not an image or a corrupted image." +msgstr "" + +#: newforms/fields.py:419 +#: newforms/fields.py:444 +msgid "Enter a valid URL." +msgstr "" + +#: newforms/fields.py:446 +msgid "This URL appears to be a broken link." +msgstr "" + +#: newforms/fields.py:497 +#: newforms/models.py:180 +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" + +#: newforms/fields.py:513 +#: newforms/fields.py:589 +#: newforms/models.py:197 +msgid "Enter a list of values." +msgstr "" + +#: newforms/fields.py:519 +#: newforms/models.py:203 +#, python-format +msgid "Select a valid choice. %s is not one of the available choices." +msgstr "" + +#: views/generic/create_update.py:43 +#, python-format +msgid "The %(verbose_name)s was created successfully." +msgstr "" + +#: views/generic/create_update.py:117 +#, python-format +msgid "The %(verbose_name)s was updated successfully." +msgstr "" + +#: views/generic/create_update.py:184 +#, python-format +msgid "The %(verbose_name)s was deleted." +msgstr "" + +#: oldforms/__init__.py:408 +#, python-format +msgid "Ensure your text is less than %s character." +msgid_plural "Ensure your text is less than %s characters." +msgstr[0] "" +msgstr[1] "" + +#: oldforms/__init__.py:413 +msgid "Line breaks are not allowed here." +msgstr "" + +#: oldforms/__init__.py:511 +#: oldforms/__init__.py:585 +#: oldforms/__init__.py:624 +#, python-format +msgid "Select a valid choice; '%(data)s' is not in %(choices)s." +msgstr "" + +#: oldforms/__init__.py:744 +msgid "Enter a whole number between -32,768 and 32,767." +msgstr "" + +#: oldforms/__init__.py:754 +msgid "Enter a positive number." +msgstr "" + +#: oldforms/__init__.py:764 +msgid "Enter a whole number between 0 and 32,767." +msgstr "" + +#: core/validators.py:72 +msgid "This value must contain only letters, numbers and underscores." +msgstr "" + +#: core/validators.py:76 +msgid "This value must contain only letters, numbers, underscores, dashes or slashes." +msgstr "" + +#: core/validators.py:80 +msgid "This value must contain only letters, numbers, underscores or hyphens." +msgstr "" + +#: core/validators.py:84 +msgid "Uppercase letters are not allowed here." +msgstr "" + +#: core/validators.py:88 +msgid "Lowercase letters are not allowed here." +msgstr "" + +#: core/validators.py:95 +msgid "Enter only digits separated by commas." +msgstr "" + +#: core/validators.py:107 +msgid "Enter valid e-mail addresses separated by commas." +msgstr "" + +#: core/validators.py:111 +msgid "Please enter a valid IP address." +msgstr "" + +#: core/validators.py:115 +msgid "Empty values are not allowed here." +msgstr "" + +#: core/validators.py:119 +msgid "Non-numeric characters aren't allowed here." +msgstr "" + +#: core/validators.py:123 +msgid "This value can't be comprised solely of digits." +msgstr "" + +#: core/validators.py:132 +msgid "Only alphabetical characters are allowed here." +msgstr "" + +#: core/validators.py:147 +msgid "Year must be 1900 or later." +msgstr "" + +#: core/validators.py:151 +#, python-format +msgid "Invalid date: %s" +msgstr "" + +#: core/validators.py:161 +msgid "Enter a valid time in HH:MM format." +msgstr "" + +#: core/validators.py:200 +#, python-format +msgid "The URL %s does not point to a valid image." +msgstr "" + +#: core/validators.py:204 +#, python-format +msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid." +msgstr "" + +#: core/validators.py:212 +#, python-format +msgid "The URL %s does not point to a valid QuickTime video." +msgstr "" + +#: core/validators.py:216 +msgid "A valid URL is required." +msgstr "" + +#: core/validators.py:230 +#, python-format +msgid "" +"Valid HTML is required. Specific errors are:\n" +"%s" +msgstr "" + +#: core/validators.py:237 +#, python-format +msgid "Badly formed XML: %s" +msgstr "" + +#: core/validators.py:254 +#, python-format +msgid "Invalid URL: %s" +msgstr "" + +#: core/validators.py:259 +#: core/validators.py:261 +#, python-format +msgid "The URL %s is a broken link." +msgstr "" + +#: core/validators.py:267 +msgid "Enter a valid U.S. state abbreviation." +msgstr "" + +#: core/validators.py:281 +#, python-format +msgid "Watch your mouth! The word %s is not allowed here." +msgid_plural "Watch your mouth! The words %s are not allowed here." +msgstr[0] "" +msgstr[1] "" + +#: core/validators.py:288 +#, python-format +msgid "This field must match the '%s' field." +msgstr "" + +#: core/validators.py:307 +msgid "Please enter something for at least one field." +msgstr "" + +#: core/validators.py:316 +#: core/validators.py:327 +msgid "Please enter both fields or leave them both empty." +msgstr "" + +#: core/validators.py:335 +#, python-format +msgid "This field must be given if %(field)s is %(value)s" +msgstr "" + +#: core/validators.py:348 +#, python-format +msgid "This field must be given if %(field)s is not %(value)s" +msgstr "" + +#: core/validators.py:367 +msgid "Duplicate values are not allowed." +msgstr "" + +#: core/validators.py:382 +#, python-format +msgid "This value must be between %(lower)s and %(upper)s." +msgstr "" + +#: core/validators.py:384 +#, python-format +msgid "This value must be at least %s." +msgstr "" + +#: core/validators.py:386 +#, python-format +msgid "This value must be no more than %s." +msgstr "" + +#: core/validators.py:422 +#, python-format +msgid "This value must be a power of %s." +msgstr "" + +#: core/validators.py:432 +msgid "Please enter a valid decimal number." +msgstr "" + +#: core/validators.py:439 +#, python-format +msgid "Please enter a valid decimal number with at most %s total digit." +msgid_plural "Please enter a valid decimal number with at most %s total digits." +msgstr[0] "" +msgstr[1] "" + +#: core/validators.py:442 +#, python-format +msgid "Please enter a valid decimal number with a whole part of at most %s digit." +msgid_plural "Please enter a valid decimal number with a whole part of at most %s digits." +msgstr[0] "" +msgstr[1] "" + +#: core/validators.py:445 +#, python-format +msgid "Please enter a valid decimal number with at most %s decimal place." +msgid_plural "Please enter a valid decimal number with at most %s decimal places." +msgstr[0] "" +msgstr[1] "" + +#: core/validators.py:453 +msgid "Please enter a valid floating point number." +msgstr "" + +#: core/validators.py:462 +#, python-format +msgid "Make sure your uploaded file is at least %s bytes big." +msgstr "" + +#: core/validators.py:463 +#, python-format +msgid "Make sure your uploaded file is at most %s bytes big." +msgstr "" + +#: core/validators.py:480 +msgid "The format for this field is wrong." +msgstr "" + +#: core/validators.py:495 +msgid "This field is invalid." +msgstr "" + +#: core/validators.py:531 +#, python-format +msgid "Could not retrieve anything from %s." +msgstr "" + +#: core/validators.py:534 +#, python-format +msgid "The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'." +msgstr "" + +#: core/validators.py:567 +#, python-format +msgid "Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with \"%(start)s\".)" +msgstr "" + +#: core/validators.py:571 +#, python-format +msgid "Some text starting on line %(line)s is not allowed in that context. (Line starts with \"%(start)s\".)" +msgstr "" + +#: core/validators.py:576 +#, python-format +msgid "\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%(start)s\".)" +msgstr "" + +#: core/validators.py:581 +#, python-format +msgid "\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%(start)s\".)" +msgstr "" + +#: core/validators.py:585 +#, python-format +msgid "A tag on line %(line)s is missing one or more required attributes. (Line starts with \"%(start)s\".)" +msgstr "" + +#: core/validators.py:590 +#, python-format +msgid "The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line starts with \"%(start)s\".)" +msgstr "" + +#: utils/timesince.py:12 +msgid "year" +msgid_plural "years" +msgstr[0] "" +msgstr[1] "" + +#: utils/timesince.py:13 +msgid "month" +msgid_plural "months" +msgstr[0] "" +msgstr[1] "" + +#: utils/timesince.py:14 +msgid "week" +msgid_plural "weeks" +msgstr[0] "" +msgstr[1] "" + +#: utils/timesince.py:15 +msgid "day" +msgid_plural "days" +msgstr[0] "" +msgstr[1] "" + +#: utils/timesince.py:16 +msgid "hour" +msgid_plural "hours" +msgstr[0] "" +msgstr[1] "" + +#: utils/timesince.py:17 +msgid "minute" +msgid_plural "minutes" +msgstr[0] "" +msgstr[1] "" + +#: utils/timesince.py:39 +#, python-format +msgid "%(number)d %(type)s" +msgstr "" + +#: utils/timesince.py:45 +#, python-format +msgid ", %(number)d %(type)s" +msgstr "" + +#: utils/dateformat.py:41 +msgid "p.m." +msgstr "" + +#: utils/dateformat.py:42 +msgid "a.m." +msgstr "" + +#: utils/dateformat.py:47 +msgid "PM" +msgstr "" + +#: utils/dateformat.py:48 +msgid "AM" +msgstr "" + +#: utils/dateformat.py:97 +msgid "midnight" +msgstr "" + +#: utils/dateformat.py:99 +msgid "noon" +msgstr "" + +#: utils/text.py:127 +msgid "or" +msgstr "" + +#: utils/dates.py:6 +msgid "Monday" +msgstr "" + +#: utils/dates.py:6 +msgid "Tuesday" +msgstr "" + +#: utils/dates.py:6 +msgid "Wednesday" +msgstr "" + +#: utils/dates.py:6 +msgid "Thursday" +msgstr "" + +#: utils/dates.py:6 +msgid "Friday" +msgstr "" + +#: utils/dates.py:7 +msgid "Saturday" +msgstr "" + +#: utils/dates.py:7 +msgid "Sunday" +msgstr "" + +#: utils/dates.py:10 +msgid "Mon" +msgstr "" + +#: utils/dates.py:10 +msgid "Tue" +msgstr "" + +#: utils/dates.py:10 +msgid "Wed" +msgstr "" + +#: utils/dates.py:10 +msgid "Thu" +msgstr "" + +#: utils/dates.py:10 +msgid "Fri" +msgstr "" + +#: utils/dates.py:11 +msgid "Sat" +msgstr "" + +#: utils/dates.py:11 +msgid "Sun" +msgstr "" + +#: utils/dates.py:18 +msgid "January" +msgstr "" + +#: utils/dates.py:18 +msgid "February" +msgstr "" + +#: utils/dates.py:18 +#: utils/dates.py:31 +msgid "March" +msgstr "" + +#: utils/dates.py:18 +#: utils/dates.py:31 +msgid "April" +msgstr "" + +#: utils/dates.py:18 +#: utils/dates.py:31 +msgid "May" +msgstr "" + +#: utils/dates.py:18 +#: utils/dates.py:31 +msgid "June" +msgstr "" + +#: utils/dates.py:19 +#: utils/dates.py:31 +msgid "July" +msgstr "" + +#: utils/dates.py:19 +msgid "August" +msgstr "" + +#: utils/dates.py:19 +msgid "September" +msgstr "" + +#: utils/dates.py:19 +msgid "October" +msgstr "" + +#: utils/dates.py:19 +msgid "November" +msgstr "" + +#: utils/dates.py:20 +msgid "December" +msgstr "" + +#: utils/dates.py:23 +msgid "jan" +msgstr "" + +#: utils/dates.py:23 +msgid "feb" +msgstr "" + +#: utils/dates.py:23 +msgid "mar" +msgstr "" + +#: utils/dates.py:23 +msgid "apr" +msgstr "" + +#: utils/dates.py:23 +msgid "may" +msgstr "" + +#: utils/dates.py:23 +msgid "jun" +msgstr "" + +#: utils/dates.py:24 +msgid "jul" +msgstr "" + +#: utils/dates.py:24 +msgid "aug" +msgstr "" + +#: utils/dates.py:24 +msgid "sep" +msgstr "" + +#: utils/dates.py:24 +msgid "oct" +msgstr "" + +#: utils/dates.py:24 +msgid "nov" +msgstr "" + +#: utils/dates.py:24 +msgid "dec" +msgstr "" + +#: utils/dates.py:31 +msgid "Jan." +msgstr "" + +#: utils/dates.py:31 +msgid "Feb." +msgstr "" + +#: utils/dates.py:32 +msgid "Aug." +msgstr "" + +#: utils/dates.py:32 +msgid "Sept." +msgstr "" + +#: utils/dates.py:32 +msgid "Oct." +msgstr "" + +#: utils/dates.py:32 +msgid "Nov." +msgstr "" + +#: utils/dates.py:32 +msgid "Dec." +msgstr "" + +#: utils/translation/trans_real.py:391 +msgid "DATE_FORMAT" +msgstr "" + +#: utils/translation/trans_real.py:392 +msgid "DATETIME_FORMAT" +msgstr "" + +#: utils/translation/trans_real.py:393 +msgid "TIME_FORMAT" +msgstr "" + +#: utils/translation/trans_real.py:409 +msgid "YEAR_MONTH_FORMAT" +msgstr "" + +#: utils/translation/trans_real.py:410 +msgid "MONTH_DAY_FORMAT" +msgstr "" + +#: conf/global_settings.py:39 +msgid "Arabic" +msgstr "" + +#: conf/global_settings.py:40 +msgid "Bengali" +msgstr "" + +#: conf/global_settings.py:41 +msgid "Bulgarian" +msgstr "" + +#: conf/global_settings.py:42 +msgid "Catalan" +msgstr "" + +#: conf/global_settings.py:43 +msgid "Czech" +msgstr "" + +#: conf/global_settings.py:44 +msgid "Welsh" +msgstr "" + +#: conf/global_settings.py:45 +msgid "Danish" +msgstr "" + +#: conf/global_settings.py:46 +msgid "German" +msgstr "" + +#: conf/global_settings.py:47 +msgid "Greek" +msgstr "" + +#: conf/global_settings.py:48 +msgid "English" +msgstr "" + +#: conf/global_settings.py:49 +msgid "Spanish" +msgstr "" + +#: conf/global_settings.py:50 +msgid "Argentinean Spanish" +msgstr "" + +#: conf/global_settings.py:51 +msgid "Persian" +msgstr "" + +#: conf/global_settings.py:52 +msgid "Finnish" +msgstr "" + +#: conf/global_settings.py:53 +msgid "French" +msgstr "" + +#: conf/global_settings.py:54 +msgid "Galician" +msgstr "" + +#: conf/global_settings.py:55 +msgid "Hungarian" +msgstr "" + +#: conf/global_settings.py:56 +msgid "Hebrew" +msgstr "" + +#: conf/global_settings.py:57 +msgid "Croatian" +msgstr "" + +#: conf/global_settings.py:58 +msgid "Icelandic" +msgstr "" + +#: conf/global_settings.py:59 +msgid "Italian" +msgstr "" + +#: conf/global_settings.py:60 +msgid "Japanese" +msgstr "" + +#: conf/global_settings.py:61 +msgid "Korean" +msgstr "" + +#: conf/global_settings.py:62 +msgid "Khmer" +msgstr "" + +#: conf/global_settings.py:63 +msgid "Kannada" +msgstr "" + +#: conf/global_settings.py:64 +msgid "Latvian" +msgstr "" + +#: conf/global_settings.py:65 +msgid "Macedonian" +msgstr "" + +#: conf/global_settings.py:66 +msgid "Dutch" +msgstr "" + +#: conf/global_settings.py:67 +msgid "Norwegian" +msgstr "" + +#: conf/global_settings.py:68 +msgid "Polish" +msgstr "" + +#: conf/global_settings.py:69 +msgid "Portugese" +msgstr "" + +#: conf/global_settings.py:70 +msgid "Brazilian" +msgstr "" + +#: conf/global_settings.py:71 +msgid "Romanian" +msgstr "" + +#: conf/global_settings.py:72 +msgid "Russian" +msgstr "" + +#: conf/global_settings.py:73 +msgid "Slovak" +msgstr "" + +#: conf/global_settings.py:74 +msgid "Slovenian" +msgstr "" + +#: conf/global_settings.py:75 +msgid "Serbian" +msgstr "" + +#: conf/global_settings.py:76 +msgid "Swedish" +msgstr "" + +#: conf/global_settings.py:77 +msgid "Tamil" +msgstr "" + +#: conf/global_settings.py:78 +msgid "Telugu" +msgstr "" + +#: conf/global_settings.py:79 +msgid "Turkish" +msgstr "" + +#: conf/global_settings.py:80 +msgid "Ukrainian" +msgstr "" + +#: conf/global_settings.py:81 +msgid "Simplified Chinese" +msgstr "" + +#: conf/global_settings.py:82 +msgid "Traditional Chinese" +msgstr "" + diff --git a/django/conf/locale/ga/LC_MESSAGES/djangojs.mo b/django/conf/locale/ga/LC_MESSAGES/djangojs.mo Binary files differnew file mode 100644 index 0000000000..06f96baee4 --- /dev/null +++ b/django/conf/locale/ga/LC_MESSAGES/djangojs.mo diff --git a/django/conf/locale/ga/LC_MESSAGES/djangojs.po b/django/conf/locale/ga/LC_MESSAGES/djangojs.po new file mode 100644 index 0000000000..41b93dab53 --- /dev/null +++ b/django/conf/locale/ga/LC_MESSAGES/djangojs.po @@ -0,0 +1,116 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: django 1.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-09-14 12:33+0100\n" +"PO-Revision-Date: 2007-09-14 14:19+0100\n" +"Last-Translator: Michael Thornhill <michael.thornhill@gmail.com>\n" +"Language-Team: Gaeilge <ga@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: contrib/admin/media/js/calendar.js:24 +#: contrib/admin/media/js/dateparse.js:32 +msgid "January February March April May June July August September October November December" +msgstr "" + +#: contrib/admin/media/js/calendar.js:25 +msgid "S M T W T F S" +msgstr "" + +#: contrib/admin/media/js/dateparse.js:33 +msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday" +msgstr "" + +#: contrib/admin/media/js/SelectFilter2.js:33 +#, perl-format +msgid "Available %s" +msgstr "" + +#: 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 "" + +#: 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/admin/DateTimeShortcuts.js:47 +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81 +msgid "Now" +msgstr "" + +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51 +msgid "Clock" +msgstr "" + +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78 +msgid "Choose a time" +msgstr "" + +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82 +msgid "Midnight" +msgstr "" + +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83 +msgid "6 a.m." +msgstr "" + +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84 +msgid "Noon" +msgstr "" + +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88 +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183 +msgid "Cancel" +msgstr "" + +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128 +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177 +msgid "Today" +msgstr "" + +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132 +msgid "Calendar" +msgstr "" + +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175 +msgid "Yesterday" +msgstr "" + +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179 +msgid "Tomorrow" +msgstr "" + +#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34 +#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72 +msgid "Show" +msgstr "" + +#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63 +msgid "Hide" +msgstr "" + diff --git a/django/conf/locale/he/LC_MESSAGES/django.mo b/django/conf/locale/he/LC_MESSAGES/django.mo Binary files differindex 50021ed86d..a0cb5fa62a 100644 --- a/django/conf/locale/he/LC_MESSAGES/django.mo +++ b/django/conf/locale/he/LC_MESSAGES/django.mo diff --git a/django/conf/locale/he/LC_MESSAGES/django.po b/django/conf/locale/he/LC_MESSAGES/django.po index 9fc5d7ee80..3ea69510c8 100644 --- a/django/conf/locale/he/LC_MESSAGES/django.po +++ b/django/conf/locale/he/LC_MESSAGES/django.po @@ -205,7 +205,7 @@ msgstr "פברואר" #: utils/dates.py:14 utils/dates.py:27 msgid "March" -msgstr "מרץ" +msgstr "מרס" #: utils/dates.py:14 utils/dates.py:27 msgid "April" @@ -241,11 +241,11 @@ msgstr "נובמבר" #: utils/dates.py:16 msgid "December" -msgstr "תצבר" +msgstr "דצמבר" #: utils/dates.py:19 msgid "jan" -msgstr "יאנ" +msgstr "ינו" #: utils/dates.py:19 msgid "feb" @@ -253,7 +253,7 @@ msgstr "פבר" #: utils/dates.py:19 msgid "mar" -msgstr "מרץ" +msgstr "מרס" #: utils/dates.py:19 msgid "apr" @@ -293,7 +293,7 @@ msgstr "דצמ" #: utils/dates.py:27 msgid "Jan." -msgstr "יאנ'" +msgstr "ינו'" #: utils/dates.py:27 msgid "Feb." diff --git a/django/conf/locale/hu/LC_MESSAGES/django.mo b/django/conf/locale/hu/LC_MESSAGES/django.mo Binary files differindex 797b87b332..a46cb69ad5 100644 --- a/django/conf/locale/hu/LC_MESSAGES/django.mo +++ b/django/conf/locale/hu/LC_MESSAGES/django.mo diff --git a/django/conf/locale/hu/LC_MESSAGES/django.po b/django/conf/locale/hu/LC_MESSAGES/django.po index 6bdfd5cb8b..a00ed9c6cf 100644 --- a/django/conf/locale/hu/LC_MESSAGES/django.po +++ b/django/conf/locale/hu/LC_MESSAGES/django.po @@ -1,24 +1,845 @@ -# translation of django.po to -# translation of django.po to -# translation of django.po to +# translation of django.po to Hungarian # This file is distributed under the same license as the PACKAGE package. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER. -# Nagy Károly <charlie@rendszergazda.com>, 2006. # msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2006-05-16 10:14+0200\n" -"PO-Revision-Date: 2006-05-10 12:13+0200\n" -"Last-Translator: Nagy Károly <charlie@rendszergazda.com>\n" -"Language-Team: <hu@li.org>\n" +"POT-Creation-Date: 2007-08-21 02:23+0200\n" +"PO-Revision-Date: 2007-08-21 02:28+0200\n" +"Last-Translator: Szilveszter Farkas <szilveszter.farkas@gmail.com>\n" +"Language-Team: Hungarian <hu@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: KBabel 1.9.1\n" +"X-Generator: KBabel 1.11.4\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: contrib/comments/models.py:67 contrib/comments/models.py:166 +#: oldforms/__init__.py:373 db/models/fields/__init__.py:156 +#: db/models/fields/__init__.py:313 db/models/fields/__init__.py:721 +#: db/models/fields/__init__.py:732 newforms/models.py:193 +#: newforms/fields.py:92 newforms/fields.py:490 newforms/fields.py:566 +#: newforms/fields.py:577 +msgid "This field is required." +msgstr "Ennek a mezőnek a megadása kötelező." + +#: oldforms/__init__.py:408 +#, python-format +msgid "Ensure your text is less than %s character." +msgid_plural "Ensure your text is less than %s characters." +msgstr[0] "A szövegnek rövidebbnek kell lennie %s karakternél." +msgstr[1] "A szövegnek rövidebbnek kell lennie %s karakternél." + +#: oldforms/__init__.py:413 +msgid "Line breaks are not allowed here." +msgstr "Sortörések itt nem megengedettek." + +#: oldforms/__init__.py:511 oldforms/__init__.py:585 oldforms/__init__.py:624 +#, python-format +msgid "Select a valid choice; '%(data)s' is not in %(choices)s." +msgstr "Válasszon egy érvényes elemet, '%(data)s' nincs ezek között: %(choices)s." + +#: oldforms/__init__.py:591 newforms/widgets.py:188 +#: contrib/admin/filterspecs.py:152 +msgid "Unknown" +msgstr "Ismeretlen" + +#: oldforms/__init__.py:591 newforms/widgets.py:188 +#: contrib/admin/filterspecs.py:145 +msgid "Yes" +msgstr "Igen" + +#: oldforms/__init__.py:591 newforms/widgets.py:188 +#: contrib/admin/filterspecs.py:145 +msgid "No" +msgstr "Nem" + +#: oldforms/__init__.py:686 core/validators.py:181 core/validators.py:461 +#: newforms/fields.py:376 +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Nem küldött el fájlt. Ellenőrizze a kódolás típusát az űrlapon." + +#: oldforms/__init__.py:688 newforms/fields.py:380 +msgid "The submitted file is empty." +msgstr "A küldött fájl üres." + +#: oldforms/__init__.py:744 +msgid "Enter a whole number between -32,768 and 32,767." +msgstr "Írjon be egy egész számot -32 768 és 32 767 között." + +#: oldforms/__init__.py:754 +msgid "Enter a positive number." +msgstr "Írjon be egy pozitív számot." + +#: oldforms/__init__.py:764 +msgid "Enter a whole number between 0 and 32,767." +msgstr "Írjon be egy egész számot 0 és 32 767 között." + +#: db/models/manipulators.py:309 +#, python-format +msgid "%(object)s with this %(type)s already exists for the given %(field)s." +msgstr "A megadott %(field)s mezőhöz már létezik %(type)s típusú %(object)s elem." + +#: db/models/manipulators.py:310 core/validators.py:275 +#: contrib/admin/views/main.py:342 contrib/admin/views/main.py:344 +#: contrib/admin/views/main.py:346 +msgid "and" +msgstr "és" + +# TODO +#: db/models/fields/__init__.py:49 +#, python-format +msgid "%(optname)s with this %(fieldname)s already exists." +msgstr "%(optname)s ezzel a(z) %(fieldname)s már létezik." + +#: db/models/fields/__init__.py:411 +msgid "This value must be an integer." +msgstr "Az értéknek egész számnak kell lennie." + +#: db/models/fields/__init__.py:446 +msgid "This value must be either True or False." +msgstr "Az értéknek igaznak (True) vagy hamisnak (False) kell lennie." + +#: db/models/fields/__init__.py:467 +msgid "This field cannot be null." +msgstr "Ez a mező nem lehet nulla." + +#: db/models/fields/__init__.py:501 core/validators.py:155 +msgid "Enter a valid date in YYYY-MM-DD format." +msgstr "Írjon be egy érvényes dátumot 'ÉÉÉÉ-HH-NN' alakban." + +#: db/models/fields/__init__.py:570 core/validators.py:164 +msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format." +msgstr "Írjon be egy érvényes dátumot/időt 'ÉÉÉÉ-HH-NN ÓÓ-PP' alakban." + +#: db/models/fields/__init__.py:631 +msgid "This value must be a decimal number." +msgstr "Az értéknek decimálisnak kell lennie." + +#: db/models/fields/__init__.py:741 +msgid "Enter a valid filename." +msgstr "Adjon meg egy érvényes fájlnevet." + +#: db/models/fields/__init__.py:883 +msgid "This value must be either None, True or False." +msgstr "" +"Az értéknek semminek (None), igaznak (True), vagy hamisnak (False) kell " +"lennie." + +#: db/models/fields/related.py:55 +#, python-format +msgid "Please enter a valid %s." +msgstr "Adjon meg egy érvényes %s értéket." + +#: db/models/fields/related.py:658 +msgid "Separate multiple IDs with commas." +msgstr "Az ID-ket vesszővel válassza el." + +#: db/models/fields/related.py:660 +msgid "Hold down \"Control\", or \"Command\" on a Mac, to select more than one." +msgstr "" +"Tartsa lenyomva a \"Control\"-t (vagy Mac-en a \"Command\"-ot) több elem " +"kiválasztásához." + +#: db/models/fields/related.py:707 +#, python-format +msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid." +msgid_plural "Please enter valid %(self)s IDs. The values %(value)r are invalid." +msgstr[0] "Írjon be érvényes %(self)s ID-t. A mostani érték érvénytelen: %(value)r." +msgstr[1] "" +"Írjon be érvényes %(self)s ID-ket. A mostani értékek érvénytelenek: %(value)" +"r." + +#: conf/global_settings.py:39 +msgid "Arabic" +msgstr "Arab" + +#: conf/global_settings.py:40 +msgid "Bengali" +msgstr "Bengáli" + +#: conf/global_settings.py:41 +msgid "Bulgarian" +msgstr "Bolgár" + +#: conf/global_settings.py:42 +msgid "Catalan" +msgstr "Katalán" + +#: conf/global_settings.py:43 +msgid "Czech" +msgstr "Cseh" + +#: conf/global_settings.py:44 +msgid "Welsh" +msgstr "Walesi" + +#: conf/global_settings.py:45 +msgid "Danish" +msgstr "Dán" + +#: conf/global_settings.py:46 +msgid "German" +msgstr "Német" + +#: conf/global_settings.py:47 +msgid "Greek" +msgstr "Görög" + +#: conf/global_settings.py:48 +msgid "English" +msgstr "Angol" + +#: conf/global_settings.py:49 +msgid "Spanish" +msgstr "Spanyol" + +#: conf/global_settings.py:50 +msgid "Argentinean Spanish" +msgstr "Argentín spanyol" + +#: conf/global_settings.py:51 +msgid "Persian" +msgstr "Perzsa" + +#: conf/global_settings.py:52 +msgid "Finnish" +msgstr "Finn" + +#: conf/global_settings.py:53 +msgid "French" +msgstr "Francia" + +#: conf/global_settings.py:54 +msgid "Galician" +msgstr "Gall" + +#: conf/global_settings.py:55 +msgid "Hungarian" +msgstr "Magyar" + +#: conf/global_settings.py:56 +msgid "Hebrew" +msgstr "Héber" + +#: conf/global_settings.py:57 +msgid "Croatian" +msgstr "Horvát" + +#: conf/global_settings.py:58 +msgid "Icelandic" +msgstr "Izlandi" + +#: conf/global_settings.py:59 +msgid "Italian" +msgstr "Olasz" + +#: conf/global_settings.py:60 +msgid "Japanese" +msgstr "Japán" + +#: conf/global_settings.py:61 +msgid "Korean" +msgstr "Koreai" + +#: conf/global_settings.py:62 +msgid "Kannada" +msgstr "Kannada" + +#: conf/global_settings.py:63 +msgid "Latvian" +msgstr "Litván" + +#: conf/global_settings.py:64 +msgid "Macedonian" +msgstr "Macedón" + +#: conf/global_settings.py:65 +msgid "Dutch" +msgstr "Holland" + +#: conf/global_settings.py:66 +msgid "Norwegian" +msgstr "Norvég" + +#: conf/global_settings.py:67 +msgid "Polish" +msgstr "Lengyel" + +#: conf/global_settings.py:68 +msgid "Portugese" +msgstr "Portugál" + +#: conf/global_settings.py:69 +msgid "Brazilian" +msgstr "Brazil" + +#: conf/global_settings.py:70 +msgid "Romanian" +msgstr "Román" + +#: conf/global_settings.py:71 +msgid "Russian" +msgstr "Orosz" + +#: conf/global_settings.py:72 +msgid "Slovak" +msgstr "Szlovák" + +#: conf/global_settings.py:73 +msgid "Slovenian" +msgstr "Szlovén" + +#: conf/global_settings.py:74 +msgid "Serbian" +msgstr "Szerb" + +#: conf/global_settings.py:75 +msgid "Swedish" +msgstr "Svéd" + +#: conf/global_settings.py:76 +msgid "Tamil" +msgstr "Tamil" + +#: conf/global_settings.py:77 +msgid "Telugu" +msgstr "Telugu" + +#: conf/global_settings.py:78 +msgid "Turkish" +msgstr "Török" + +#: conf/global_settings.py:79 +msgid "Ukrainian" +msgstr "Ukrán" + +#: conf/global_settings.py:80 +msgid "Simplified Chinese" +msgstr "Egyszerű kínai" + +#: conf/global_settings.py:81 +msgid "Traditional Chinese" +msgstr "Hagyományos kínai" + +#: core/validators.py:71 +msgid "This value must contain only letters, numbers and underscores." +msgstr "Az érték csak betűket, számokat és aláhúzást tartalmazhat." + +#: core/validators.py:75 +msgid "" +"This value must contain only letters, numbers, underscores, dashes or " +"slashes." +msgstr "Az érték csak betűket, számokat, aláhúzást és perjelet tartalmazhat." + +#: core/validators.py:79 +msgid "This value must contain only letters, numbers, underscores or hyphens." +msgstr "Az érték csak betűket, számokat, aláhúzást és kötőjelet tartalmazhat." + +#: core/validators.py:83 +msgid "Uppercase letters are not allowed here." +msgstr "Nagybetűk itt nem megengedettek." + +#: core/validators.py:87 +msgid "Lowercase letters are not allowed here." +msgstr "Kisbetűk itt nem megengedettek." + +#: core/validators.py:94 +msgid "Enter only digits separated by commas." +msgstr "Csak számokat adjon meg, vesszővel elválasztva." + +#: core/validators.py:106 +msgid "Enter valid e-mail addresses separated by commas." +msgstr "Érvényes e-mail címeket adjon meg, vesszővel elválasztva." + +#: core/validators.py:110 +msgid "Please enter a valid IP address." +msgstr "Írjon be egy érvényes IP címet." + +#: core/validators.py:114 +msgid "Empty values are not allowed here." +msgstr "Üres érték itt nem megengedett." + +#: core/validators.py:118 +msgid "Non-numeric characters aren't allowed here." +msgstr "Nem szám karakterek itt nem megengedettek." + +#: core/validators.py:122 +msgid "This value can't be comprised solely of digits." +msgstr "Ez az érték nem tartalmazhat kizárólag számokat." + +#: core/validators.py:127 newforms/fields.py:142 +msgid "Enter a whole number." +msgstr "Adjon meg egy egész számot." + +#: core/validators.py:131 +msgid "Only alphabetical characters are allowed here." +msgstr "Itt csak betűk megengedettek." + +#: core/validators.py:146 +msgid "Year must be 1900 or later." +msgstr "Az évnek 1900-nak vagy későbbinek kell lennie." + +#: core/validators.py:150 +#, python-format +msgid "Invalid date: %s" +msgstr "Érvénytelen dátum: %s" + +#: core/validators.py:160 +msgid "Enter a valid time in HH:MM format." +msgstr "Írjon be egy érvényes időt 'ÓÓ:PP' alakban." + +#: core/validators.py:169 newforms/fields.py:336 +msgid "Enter a valid e-mail address." +msgstr "Írjon be egy érvényes e-mail címet." + +#: core/validators.py:185 newforms/fields.py:397 +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Töltsön fel egy érvényes képfájlt. A feltöltött fájl nem kép volt, vagy " +"megsérült." + +#: core/validators.py:192 +#, python-format +msgid "The URL %s does not point to a valid image." +msgstr "A hivatkozás (%s) érvénytelen képfájlra mutat." + +#: core/validators.py:196 +#, python-format +msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid." +msgstr "" +"A telefonszámoknak 'XXX-XXX-XXXX' formátumúnak kell lenniük. \"%s\" " +"érvénytelen." + +#: core/validators.py:204 +#, python-format +msgid "The URL %s does not point to a valid QuickTime video." +msgstr "A hivatkozás (%s) érvénytelen QuickTime videóra mutat." + +#: core/validators.py:208 +msgid "A valid URL is required." +msgstr "Érvényes URL szükséges." + +#: core/validators.py:222 +#, python-format +msgid "" +"Valid HTML is required. Specific errors are:\n" +"%s" +msgstr "" +"Érvényes HTML kell. A hiba:\n" +"%s" + +#: core/validators.py:229 +#, python-format +msgid "Badly formed XML: %s" +msgstr "Rosszul formázott XML: %s" + +#: core/validators.py:246 +#, python-format +msgid "Invalid URL: %s" +msgstr "Érvénytelen URL: %s" + +#: core/validators.py:251 core/validators.py:253 +#, python-format +msgid "The URL %s is a broken link." +msgstr "A hivatkozás (%s) egy törött link." + +#: core/validators.py:259 +msgid "Enter a valid U.S. state abbreviation." +msgstr "Írja be egy érvényes USA állam rövidítését." + +#: core/validators.py:273 +#, python-format +msgid "Watch your mouth! The word %s is not allowed here." +msgid_plural "Watch your mouth! The words %s are not allowed here." +msgstr[0] "Vigyázzon a szájára! Az ilyen szó (%s) itt nem megengedett." +msgstr[1] "Vigyázzon a szájára! Az ilyen szavak (%s) itt nem megengedettek." + +# TODO +#: core/validators.py:280 +#, python-format +msgid "This field must match the '%s' field." +msgstr "Ennek a mezőnek egyeznie kell a(z) %s mezővel." + +#: core/validators.py:299 +msgid "Please enter something for at least one field." +msgstr "Írjon be valamit legalább egy mezőbe." + +#: core/validators.py:308 core/validators.py:319 +msgid "Please enter both fields or leave them both empty." +msgstr "Töltse ki mindkét mezőt, vagy hagyja üresen mindkettőt." + +#: core/validators.py:327 +#, python-format +msgid "This field must be given if %(field)s is %(value)s" +msgstr "Ezt a mezőt meg kell adni, ha %(field)s értéke %(value)s" + +#: core/validators.py:340 +#, python-format +msgid "This field must be given if %(field)s is not %(value)s" +msgstr "Ezt a mezőt meg kell adni, ha %(field)s értéke nem %(value)s" + +#: core/validators.py:359 +msgid "Duplicate values are not allowed." +msgstr "Ugyanazok az értékek nem megengedettek." + +#: core/validators.py:374 +#, python-format +msgid "This value must be between %(lower)s and %(upper)s." +msgstr "Az értéknek %(lower)s és %(upper)s között kell lennie." + +#: core/validators.py:376 +#, python-format +msgid "This value must be at least %s." +msgstr "Az értéknek legalább ennyinek kell lennie: %s." + +#: core/validators.py:378 +#, python-format +msgid "This value must be no more than %s." +msgstr "Az érték nem lehet több ennyinél: %s." + +#: core/validators.py:414 +#, python-format +msgid "This value must be a power of %s." +msgstr "Az értéknek %s hatványának kell lennie." + +#: core/validators.py:424 +msgid "Please enter a valid decimal number." +msgstr "Írjon be egy érvényes decimális számot." + +#: core/validators.py:431 +#, python-format +msgid "Please enter a valid decimal number with at most %s total digit." +msgid_plural "Please enter a valid decimal number with at most %s total digits." +msgstr[0] "Írjon be egy legalább %s jegyű érvényes decimális számot." +msgstr[1] "Írjon be egy legalább %s jegyű érvényes decimális számot." + +#: core/validators.py:434 +#, python-format +msgid "Please enter a valid decimal number with a whole part of at most %s digit." +msgid_plural "Please enter a valid decimal number with a whole part of at most %s digits." +msgstr[0] "Írjon be egy érvényes decimális számot, legfeljebb %s egész számjeggyel." +msgstr[1] "Írjon be egy érvényes decimális számot, legfeljebb %s egész számjeggyel." + +#: core/validators.py:437 +#, python-format +msgid "Please enter a valid decimal number with at most %s decimal place." +msgid_plural "Please enter a valid decimal number with at most %s decimal places." +msgstr[0] "Írjon be egy érvényes decimális számot, legfeljebb %s tizedessel." +msgstr[1] "Írj be egy érvényes decimális számot, legfeljebb %s tizedessel." + +#: core/validators.py:445 +msgid "Please enter a valid floating point number." +msgstr "Írj be egy érvényes lebegőpontos számot." + +#: core/validators.py:454 +#, python-format +msgid "Make sure your uploaded file is at least %s bytes big." +msgstr "A feltöltött fájl legalább %s bájt méretű legyen." + +#: core/validators.py:455 +#, python-format +msgid "Make sure your uploaded file is at most %s bytes big." +msgstr "A feltöltött fájl legfeljebb %s bájt méretű lehet." + +#: core/validators.py:472 +msgid "The format for this field is wrong." +msgstr "Ennek a mezőnek rossz a formátuma." + +#: core/validators.py:487 +msgid "This field is invalid." +msgstr "A mező érvénytelen." + +#: core/validators.py:523 +#, python-format +msgid "Could not retrieve anything from %s." +msgstr "Nem lehet semmit kinyerni innen: %s." + +#: core/validators.py:526 +#, python-format +msgid "The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'." +msgstr "" +"A hivatkozás (%(url)s) érvénytelen '%(contenttype)s' Content-Type fejlécet " +"adott vissza." + +#: core/validators.py:559 +#, python-format +msgid "" +"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with " +"\"%(start)s\".)" +msgstr "" +"Zárja le a nyitott %(tag)s címkét a következő sorban: %(line)s. (A sor " +"kezdete: \"%(start)s\".)" + +#: core/validators.py:563 +#, python-format +msgid "" +"Some text starting on line %(line)s is not allowed in that context. (Line " +"starts with \"%(start)s\".)" +msgstr "" +"Valamely szöveg nem megengedett ebben a környezetben a következő sorban: %" +"(line)s. (A sor kezdete: \"%(start)s\".)" + +#: core/validators.py:568 +#, python-format +msgid "" +"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%" +"(start)s\".)" +msgstr "" +"\"%(attr)s\" érvénytelen tulajdonság a következő sorban: %(line)s. (A sor " +"kezdete: \"%(start)s\".)" + +#: core/validators.py:573 +#, python-format +msgid "" +"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%" +"(start)s\".)" +msgstr "" +"\"<%(tag)s>\" érvénytelen címke a következő sorban: %(line)s. (A sor " +"kezdete: \"%(start)s\".)" + +#: core/validators.py:577 +#, python-format +msgid "" +"A tag on line %(line)s is missing one or more required attributes. (Line " +"starts with \"%(start)s\".)" +msgstr "" +"A következő sorban lévő címkéről hiányzik egy vagy több kötelező " +"tulajdonság: %(line)s. (A sor kezdete: \"%(start)s\".)" + +#: core/validators.py:582 +#, python-format +msgid "" +"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line " +"starts with \"%(start)s\".)" +msgstr "" +"A tulajdonság (\"%(attr)s\") érvénytelen a következő sorban: %(line)s. (A " +"sor kezdete: \"%(start)s\".)" + +#: views/generic/create_update.py:43 +#, python-format +msgid "The %(verbose_name)s was created successfully." +msgstr "%(verbose_name)s sikeresen létrehozva." + +#: views/generic/create_update.py:117 +#, python-format +msgid "The %(verbose_name)s was updated successfully." +msgstr "%(verbose_name)s sikeresen frissítve." + +#: views/generic/create_update.py:184 +#, python-format +msgid "The %(verbose_name)s was deleted." +msgstr "%(verbose_name)s törölve." + +#: newforms/models.py:180 newforms/fields.py:478 +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Válasszon érvényes elemet. Az Ön választása nincs az elérhető lehetőségek " +"között." + +#: newforms/models.py:197 newforms/fields.py:494 newforms/fields.py:570 +msgid "Enter a list of values." +msgstr "Adja meg értékek egy listáját." + +#: newforms/models.py:203 newforms/fields.py:500 +#, python-format +msgid "Select a valid choice. %s is not one of the available choices." +msgstr "Válasszon érvényes elemet. %s nincs az elérhető lehetőségek között." + +#: newforms/fields.py:116 +#, python-format +msgid "Ensure this value has at most %(max)d characters (it has %(length)d)." +msgstr "" +"Bizonyosodjon meg arról, hogy ez az érték legfeljebb %(max)d karaktert " +"tartalmaz (jelenlegi hossza: %(length)d)." + +#: newforms/fields.py:118 +#, python-format +msgid "Ensure this value has at least %(min)d characters (it has %(length)d)." +msgstr "" +"Bizonyosodjon meg arról, hogy ez az érték legalább %(min)d karaktert " +"tartalmaz (jelenlegi hossza: %(length)d)." + +#: newforms/fields.py:144 newforms/fields.py:167 newforms/fields.py:197 +#, python-format +msgid "Ensure this value is less than or equal to %s." +msgstr "Bizonyosodjon meg arról, hogy az érték %s vagy kisebb." + +#: newforms/fields.py:146 newforms/fields.py:169 newforms/fields.py:199 +#, python-format +msgid "Ensure this value is greater than or equal to %s." +msgstr "Bizonyosodjon meg arról, hogy az érték %s vagy nagyobb." + +#: newforms/fields.py:165 newforms/fields.py:192 +msgid "Enter a number." +msgstr "Adj meg egy számot." + +#: newforms/fields.py:201 +#, python-format +msgid "Ensure that there are no more than %s digits in total." +msgstr "Bizonyosodjon meg arról, hogy nincs ennél több számjegy: %s." + +#: newforms/fields.py:203 +#, python-format +msgid "Ensure that there are no more than %s decimal places." +msgstr "Bizonyosodjon meg arról, hogy nincs ennél több tizedesjegy: %s." + +#: newforms/fields.py:205 +#, python-format +msgid "Ensure that there are no more than %s digits before the decimal point." +msgstr "" +"Bizonyosodjon meg arról, hogy nincs ennél több számjegy a tizedesvessző " +"előtt: %s." + +#: newforms/fields.py:238 newforms/fields.py:610 +msgid "Enter a valid date." +msgstr "Adjon meg egy érvényes dátumot." + +#: newforms/fields.py:265 newforms/fields.py:612 +msgid "Enter a valid time." +msgstr "Adjon meg egy érvényes időt." + +#: newforms/fields.py:301 +msgid "Enter a valid date/time." +msgstr "Adjon meg egy érvényes dátumot/időt." + +#: newforms/fields.py:314 +msgid "Enter a valid value." +msgstr "Adjon meg egy érvényes értéket." + +#: newforms/fields.py:378 +msgid "No file was submitted." +msgstr "Semmilyen fájl sem került feltöltésre." + +#: newforms/fields.py:403 newforms/fields.py:425 +msgid "Enter a valid URL." +msgstr "Adjon meg egy érvényes URL-t." + +#: newforms/fields.py:427 +msgid "This URL appears to be a broken link." +msgstr "Ez a hivatkozás törött linknek tűnik." + +#: contrib/humanize/templatetags/humanize.py:20 +msgid "th" +msgstr "." + +#: contrib/humanize/templatetags/humanize.py:20 +msgid "st" +msgstr "." + +#: contrib/humanize/templatetags/humanize.py:20 +msgid "nd" +msgstr "." + +#: contrib/humanize/templatetags/humanize.py:20 +msgid "rd" +msgstr "." + +#: contrib/humanize/templatetags/humanize.py:50 +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value)1f millió" +msgstr[1] "%(value)1f millió" + +#: contrib/humanize/templatetags/humanize.py:53 +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value)1f milliárd" +msgstr[1] "%(value)1f milliárd" + +#: contrib/humanize/templatetags/humanize.py:56 +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value)1f trilliárd" +msgstr[1] "%(value)1f trilliárd" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "one" +msgstr "egy" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "two" +msgstr "kettő" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "three" +msgstr "három" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "four" +msgstr "négy" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "five" +msgstr "öt" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "six" +msgstr "hat" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "seven" +msgstr "hét" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "eight" +msgstr "nyolc" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "nine" +msgstr "kilenc" + +#: contrib/humanize/templatetags/humanize.py:90 +msgid "today" +msgstr "ma" + +#: contrib/humanize/templatetags/humanize.py:92 +msgid "tomorrow" +msgstr "holnap" + +#: contrib/humanize/templatetags/humanize.py:94 +msgid "yesterday" +msgstr "tegnap" + +#: contrib/redirects/models.py:7 +msgid "redirect from" +msgstr "átirányítva innen" + +#: contrib/redirects/models.py:8 +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" +"Ennek abszolút elérési útnak kell lennie, a tartománynév nélkül. Példa: '/" +"events/search/'" + +#: contrib/redirects/models.py:9 +msgid "redirect to" +msgstr "átirányítva ide" + +#: contrib/redirects/models.py:10 +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"Ennek vagy abszolút elérési útnak kell lennie (mint fentebb), vagy teljes " +"URL-nek 'http://'-vel kezdve." + +#: contrib/redirects/models.py:13 +msgid "redirect" +msgstr "átirányítás" + +#: contrib/redirects/models.py:14 +msgid "redirects" +msgstr "átirányít" + +#: contrib/comments/models.py:67 contrib/comments/models.py:169 msgid "object ID" msgstr "objektum ID" @@ -27,7 +848,7 @@ msgid "headline" msgstr "címsor" #: contrib/comments/models.py:69 contrib/comments/models.py:90 -#: contrib/comments/models.py:167 +#: contrib/comments/models.py:170 msgid "comment" msgstr "megjegyzés" @@ -67,17 +888,17 @@ msgstr "besorolás #8" msgid "is valid rating" msgstr "érvényes besorolás" -#: contrib/comments/models.py:83 contrib/comments/models.py:169 +#: contrib/comments/models.py:83 contrib/comments/models.py:172 msgid "date/time submitted" msgstr "dátum/idő beállítva" -#: contrib/comments/models.py:84 contrib/comments/models.py:170 +#: contrib/comments/models.py:84 contrib/comments/models.py:173 msgid "is public" msgstr "publikus" -#: contrib/comments/models.py:85 contrib/admin/views/doc.py:289 +#: contrib/comments/models.py:85 contrib/admin/views/doc.py:306 msgid "IP address" -msgstr "IP szám" +msgstr "IP cím" #: contrib/comments/models.py:86 msgid "is removed" @@ -92,15 +913,14 @@ msgstr "" "törölték\" üzenet fog megjelenni helyette." #: contrib/comments/models.py:91 -#, fuzzy msgid "comments" msgstr "megjegyzés" -#: contrib/comments/models.py:131 contrib/comments/models.py:207 +#: contrib/comments/models.py:134 contrib/comments/models.py:213 msgid "Content object" msgstr "Tartalom objektum" -#: contrib/comments/models.py:159 +#: contrib/comments/models.py:162 #, python-format msgid "" "Posted by %(user)s at %(date)s\n" @@ -109,58 +929,54 @@ msgid "" "\n" "http://%(domain)s%(url)s" msgstr "" -"Beküldte %(user)s %(date)s -kor\n" +"Beküldte %(user)s ekkor: %(date)s\n" "\n" "%(comment)s\n" "\n" "http://%(domain)s%(url)s" -#: contrib/comments/models.py:168 +#: contrib/comments/models.py:171 msgid "person's name" msgstr "személy neve" -#: contrib/comments/models.py:171 +#: contrib/comments/models.py:174 msgid "ip address" msgstr "IP cím" -#: contrib/comments/models.py:173 +#: contrib/comments/models.py:176 msgid "approved by staff" msgstr "személyzet által elfogadva" -#: contrib/comments/models.py:176 -#, fuzzy +#: contrib/comments/models.py:179 msgid "free comment" -msgstr "Szabad megjegyzés" +msgstr "szabad megjegyzés" -#: contrib/comments/models.py:177 -#, fuzzy +#: contrib/comments/models.py:180 msgid "free comments" -msgstr "Szabad megjegyzések" +msgstr "szabad megjegyzések" -#: contrib/comments/models.py:233 +#: contrib/comments/models.py:239 msgid "score" msgstr "értékelés" -#: contrib/comments/models.py:234 +#: contrib/comments/models.py:240 msgid "score date" msgstr "értékelés dátuma" -#: contrib/comments/models.py:237 -#, fuzzy +#: contrib/comments/models.py:243 msgid "karma score" -msgstr "Karma értékelés" +msgstr "karma értékelés" -#: contrib/comments/models.py:238 -#, fuzzy +#: contrib/comments/models.py:244 msgid "karma scores" -msgstr "Karma értékelése" +msgstr "karma értékelések" -#: contrib/comments/models.py:242 +#: contrib/comments/models.py:248 #, python-format msgid "%(score)d rating by %(user)s" -msgstr "%(score)d értékelés %(user)s -tól" +msgstr "%(score)d értékelés %(user)s felhasználótól" -#: contrib/comments/models.py:258 +#: contrib/comments/models.py:264 #, python-format msgid "" "This comment was flagged by %(user)s:\n" @@ -171,60 +987,55 @@ msgstr "" "\n" "%(text)s" -#: contrib/comments/models.py:265 +#: contrib/comments/models.py:271 msgid "flag date" msgstr "jelölés dátuma" -#: contrib/comments/models.py:268 -#, fuzzy +#: contrib/comments/models.py:274 msgid "user flag" -msgstr "Felhasználó jelölése" +msgstr "felhasználó jelölése" -#: contrib/comments/models.py:269 -#, fuzzy +#: contrib/comments/models.py:275 msgid "user flags" -msgstr "Felhasználó jelölései" +msgstr "felhasználó jelölései" -#: contrib/comments/models.py:273 +#: contrib/comments/models.py:279 #, python-format msgid "Flag by %r" msgstr "Megjelölte %r" -#: contrib/comments/models.py:278 +#: contrib/comments/models.py:284 msgid "deletion date" msgstr "törlés dátuma" -#: contrib/comments/models.py:280 -#, fuzzy +#: contrib/comments/models.py:286 msgid "moderator deletion" -msgstr "Moderátor törlése" +msgstr "moderátor törlése" -#: contrib/comments/models.py:281 -#, fuzzy +#: contrib/comments/models.py:287 msgid "moderator deletions" -msgstr "Moderátor törlései" +msgstr "moderátor törlései" -#: contrib/comments/models.py:285 +#: contrib/comments/models.py:291 #, python-format msgid "Moderator deletion by %r" msgstr "Moderátor törlés %r által" -#: contrib/comments/views/karma.py:19 +#: contrib/comments/views/karma.py:20 msgid "Anonymous users cannot vote" -msgstr "Ismeretlen felhasználó nem szavazhat" +msgstr "Névtelen felhasználó nem szavazhat" -#: contrib/comments/views/karma.py:23 +#: contrib/comments/views/karma.py:24 msgid "Invalid comment ID" msgstr "Érvénytelen megjegyzés ID" -#: contrib/comments/views/karma.py:25 +#: contrib/comments/views/karma.py:26 msgid "No voting for yourself" -msgstr "Nem szavazhatsz magadra" +msgstr "Nem szavazhat önmagára" #: contrib/comments/views/comments.py:28 -msgid "" -"This rating is required because you've entered at least one other rating." -msgstr "Ez az értékelés szükséges, mert legalább még egy értékelés kell." +msgid "This rating is required because you've entered at least one other rating." +msgstr "Ez az értékelés szükséges, mert legalább még egy értékelést megadott." #: contrib/comments/views/comments.py:112 #, python-format @@ -244,8 +1055,8 @@ msgstr[0] "" "\n" "%(text)s" msgstr[1] "" -"Ezeket a megjegyzéseket olyan felhasználó küldte akinek kevesebb mint %" -"(count)s megjegyzése van:\n" +"Ezt a megjegyzést olyan felhasználó küldte akinek kevesebb mint %(count)s " +"megjegyzése van:\n" "\n" "%(text)s" @@ -261,22 +1072,22 @@ msgstr "" "%(text)s" #: contrib/comments/views/comments.py:189 -#: contrib/comments/views/comments.py:280 +#: contrib/comments/views/comments.py:281 msgid "Only POSTs are allowed" msgstr "Csak POST engedélyezett" #: contrib/comments/views/comments.py:193 -#: contrib/comments/views/comments.py:284 +#: contrib/comments/views/comments.py:285 msgid "One or more of the required fields wasn't submitted" msgstr "Egy vagy több kötelező mező nincs kitöltve" #: contrib/comments/views/comments.py:197 -#: contrib/comments/views/comments.py:286 +#: contrib/comments/views/comments.py:287 msgid "Somebody tampered with the comment form (security violation)" msgstr "Valaki megváltoztatta a megjegyzés űrlapot (biztonság megsértése)" #: contrib/comments/views/comments.py:207 -#: contrib/comments/views/comments.py:292 +#: contrib/comments/views/comments.py:293 msgid "" "The comment form had an invalid 'target' parameter -- the object ID was " "invalid" @@ -284,8 +1095,8 @@ msgstr "" "A megjegyzés űrlap érvénytelen 'target' paramétert tartalmaz -- az objektum " "ID-je érvénytelen volt" -#: contrib/comments/views/comments.py:257 -#: contrib/comments/views/comments.py:321 +#: contrib/comments/views/comments.py:258 +#: contrib/comments/views/comments.py:322 msgid "The comment form didn't provide either 'preview' or 'post'" msgstr "A megjegyzés űrlap nem biztosít sem 'preview' -t sem 'post' -ot." @@ -296,35 +1107,36 @@ msgid "Username:" msgstr "Felhasználó:" #: contrib/comments/templates/comments/form.html:6 -#: contrib/admin/templates/admin/login.html:20 -msgid "Password:" -msgstr "Jelszó:" - -#: contrib/comments/templates/comments/form.html:6 -msgid "Forgotten your password?" -msgstr "Elfelejtetted a jelszavad?" - -#: contrib/comments/templates/comments/form.html:8 -#: contrib/admin/templates/admin/object_history.html:3 #: contrib/admin/templates/admin/change_list.html:5 -#: contrib/admin/templates/admin/base.html:23 -#: contrib/admin/templates/admin/delete_confirmation.html:3 +#: contrib/admin/templates/admin/object_history.html:3 #: contrib/admin/templates/admin/change_form.html:10 +#: contrib/admin/templates/admin/delete_confirmation.html:3 +#: contrib/admin/templates/admin/base.html:25 +#: contrib/admin/templates/admin/auth/user/change_password.html:9 #: contrib/admin/templates/registration/password_change_done.html:3 #: contrib/admin/templates/registration/password_change_form.html:3 -#: contrib/admin/templates/admin_doc/bookmarklets.html:4 #: contrib/admin/templates/admin_doc/view_detail.html:4 -#: contrib/admin/templates/admin_doc/template_tag_index.html:5 +#: contrib/admin/templates/admin_doc/bookmarklets.html:4 #: contrib/admin/templates/admin_doc/template_detail.html:4 -#: contrib/admin/templates/admin_doc/template_filter_index.html:5 +#: contrib/admin/templates/admin_doc/template_tag_index.html:5 #: contrib/admin/templates/admin_doc/missing_docutils.html:4 #: contrib/admin/templates/admin_doc/view_index.html:5 #: contrib/admin/templates/admin_doc/model_detail.html:3 #: contrib/admin/templates/admin_doc/index.html:4 #: contrib/admin/templates/admin_doc/model_index.html:5 +#: contrib/admin/templates/admin_doc/template_filter_index.html:5 msgid "Log out" msgstr "Kijelentkezés" +#: contrib/comments/templates/comments/form.html:8 +#: contrib/admin/templates/admin/login.html:20 +msgid "Password:" +msgstr "Jelszó:" + +#: contrib/comments/templates/comments/form.html:8 +msgid "Forgotten your password?" +msgstr "Elfelejtette a jelszavát?" + #: contrib/comments/templates/comments/form.html:12 msgid "Ratings" msgstr "Értékelések" @@ -343,343 +1155,447 @@ msgstr "Opcionális" msgid "Post a photo" msgstr "Fénykép beküldése" -#: contrib/comments/templates/comments/form.html:27 +#: contrib/comments/templates/comments/form.html:28 #: contrib/comments/templates/comments/freeform.html:5 msgid "Comment:" msgstr "Megjegyzés:" -#: contrib/comments/templates/comments/form.html:32 -#: contrib/comments/templates/comments/freeform.html:9 +#: contrib/comments/templates/comments/form.html:35 +#: contrib/comments/templates/comments/freeform.html:10 msgid "Preview comment" msgstr "Megjegyzés előnézete" #: contrib/comments/templates/comments/freeform.html:4 msgid "Your name:" -msgstr "Neved:" +msgstr "Név:" + +#: contrib/sites/models.py:15 +msgid "domain name" +msgstr "tartománynév" + +#: contrib/sites/models.py:16 +msgid "display name" +msgstr "megjelenítendő név" + +#: contrib/sites/models.py:20 +msgid "site" +msgstr "honlap" -#: contrib/admin/filterspecs.py:40 +#: contrib/sites/models.py:21 +msgid "sites" +msgstr "honlapok" + +#: contrib/admin/filterspecs.py:42 #, python-format msgid "" "<h3>By %s:</h3>\n" "<ul>\n" msgstr "" -"<h3>Szerző %s:</h3>\n" +"<h3>Szerző: %s:</h3>\n" "<ul>\n" -#: contrib/admin/filterspecs.py:70 contrib/admin/filterspecs.py:88 -#: contrib/admin/filterspecs.py:143 +#: contrib/admin/filterspecs.py:72 contrib/admin/filterspecs.py:90 +#: contrib/admin/filterspecs.py:145 contrib/admin/filterspecs.py:171 msgid "All" msgstr "Mind" -#: contrib/admin/filterspecs.py:109 +#: contrib/admin/filterspecs.py:111 msgid "Any date" msgstr "Bármely dátum" -#: contrib/admin/filterspecs.py:110 +#: contrib/admin/filterspecs.py:112 msgid "Today" msgstr "Ma" -#: contrib/admin/filterspecs.py:113 +#: contrib/admin/filterspecs.py:115 msgid "Past 7 days" msgstr "Utolsó 7 nap" -#: contrib/admin/filterspecs.py:115 +#: contrib/admin/filterspecs.py:117 msgid "This month" msgstr "Ez a hónap" -#: contrib/admin/filterspecs.py:117 +#: contrib/admin/filterspecs.py:119 msgid "This year" msgstr "Ez az év" -#: contrib/admin/filterspecs.py:143 -msgid "Yes" -msgstr "Igen" - -#: contrib/admin/filterspecs.py:143 -msgid "No" -msgstr "Nem" - -#: contrib/admin/filterspecs.py:150 -msgid "Unknown" -msgstr "Ismeretlen" - -#: contrib/admin/models.py:16 +#: contrib/admin/models.py:17 msgid "action time" msgstr "művelet időpontja" -#: contrib/admin/models.py:19 +#: contrib/admin/models.py:20 msgid "object id" msgstr "objektum id" -#: contrib/admin/models.py:20 +#: contrib/admin/models.py:21 msgid "object repr" msgstr "objektum repr" -#: contrib/admin/models.py:21 +#: contrib/admin/models.py:22 msgid "action flag" msgstr "művelet jelölés" -#: contrib/admin/models.py:22 +#: contrib/admin/models.py:23 msgid "change message" -msgstr "üzenet megváltoztatása" +msgstr "üzenet módosítása" -#: contrib/admin/models.py:25 +#: contrib/admin/models.py:26 msgid "log entry" msgstr "naplóbejegyzés" -#: contrib/admin/models.py:26 +#: contrib/admin/models.py:27 msgid "log entries" msgstr "naplóbejegyzések" -#: contrib/admin/templatetags/admin_list.py:228 +#: contrib/admin/templatetags/admin_list.py:254 msgid "All dates" msgstr "Minden dátum" -#: contrib/admin/views/decorators.py:9 contrib/auth/forms.py:36 -#: contrib/auth/forms.py:41 -msgid "" -"Please enter a correct username and password. Note that both fields are case-" -"sensitive." -msgstr "" -"Kérlek írd be a helyes felhasználónevet és jelszót. Mindkét mező kisbetű-" -"nagybetű érzékeny." - -#: contrib/admin/views/decorators.py:23 -#: contrib/admin/templates/admin/login.html:25 -msgid "Log in" -msgstr "Bejelentkezés" +# TODO +#: contrib/admin/views/auth.py:20 contrib/admin/views/main.py:264 +#, python-format +msgid "The %(name)s \"%(obj)s\" was added successfully." +msgstr "\"%(obj)s\" %(name)s sikeresen létrehozva." -#: contrib/admin/views/decorators.py:61 -msgid "" -"Please log in again, because your session has expired. Don't worry: Your " -"submission has been saved." -msgstr "" -"Kérlek jelentkezz be újra, mert a munkameneted végetért. Ne aggódj, minden " -"beküldött adatod el van mentve." +#: contrib/admin/views/auth.py:25 contrib/admin/views/main.py:268 +#: contrib/admin/views/main.py:354 +msgid "You may edit it again below." +msgstr "Alább ismét szerkesztheti." -#: contrib/admin/views/decorators.py:68 -msgid "" -"Looks like your browser isn't configured to accept cookies. Please enable " -"cookies, reload this page, and try again." -msgstr "" -"Úgy tűnik a böngésződön nincs engedélyezve a cookie-k fogadása. Kérlek " -"engedélyezd és töltsd újra az oldalt!" +#: contrib/admin/views/auth.py:31 +msgid "Add user" +msgstr "Felhasználó hozzáadása" -#: contrib/admin/views/decorators.py:82 -msgid "Usernames cannot contain the '@' character." -msgstr "A felhasználónév nem tartalmazhat '@' karaktert." +#: contrib/admin/views/auth.py:58 +msgid "Password changed successfully." +msgstr "Sikeres jelszóváltoztatás." -#: contrib/admin/views/decorators.py:84 +#: contrib/admin/views/auth.py:65 #, python-format -msgid "Your e-mail address is not your username. Try '%s' instead." -msgstr "Az email címed nem a felhasználóneved. Próbáld a(z) '%s' inkább." +msgid "Change password: %s" +msgstr "Jelszó megváltoztatása: %s" -#: contrib/admin/views/main.py:226 +#: contrib/admin/views/main.py:230 msgid "Site administration" msgstr "Honlap karbantartás" -#: contrib/admin/views/main.py:260 -#, python-format -msgid "The %(name)s \"%(obj)s\" was added successfully." -msgstr "A(z) %(name)s \"%(obj)s\" sikeresen hozzáadva." - -#: contrib/admin/views/main.py:264 contrib/admin/views/main.py:348 -msgid "You may edit it again below." -msgstr "Alább ismét szerkesztheted." - -#: contrib/admin/views/main.py:272 contrib/admin/views/main.py:357 +#: contrib/admin/views/main.py:278 contrib/admin/views/main.py:363 #, python-format msgid "You may add another %s below." -msgstr "Alább hozzáadhatsz egy másik %s -t." +msgstr "Alább hozzáadhat egy másikat ebből: %s." -#: contrib/admin/views/main.py:290 +#: contrib/admin/views/main.py:296 #, python-format msgid "Add %s" -msgstr "%s hozzáadása" +msgstr "Új %s" -#: contrib/admin/views/main.py:336 +#: contrib/admin/views/main.py:342 #, python-format msgid "Added %s." -msgstr "%s hozzáadva." +msgstr "%s létrehozva." -#: contrib/admin/views/main.py:336 contrib/admin/views/main.py:338 -#: contrib/admin/views/main.py:340 -msgid "and" -msgstr "és" - -#: contrib/admin/views/main.py:338 +#: contrib/admin/views/main.py:344 #, python-format msgid "Changed %s." -msgstr "%s megváltoztatva." +msgstr "%s módosítva." -#: contrib/admin/views/main.py:340 +#: contrib/admin/views/main.py:346 #, python-format msgid "Deleted %s." msgstr "%s törölve." -#: contrib/admin/views/main.py:343 +#: contrib/admin/views/main.py:349 msgid "No fields changed." msgstr "Egy mező sem változott." -#: contrib/admin/views/main.py:346 +#: contrib/admin/views/main.py:352 #, python-format msgid "The %(name)s \"%(obj)s\" was changed successfully." -msgstr "A(z) %(name)s \"%(obj)s\" sikeresen megváltoztatva." +msgstr "\"%(obj)s\" %(name)s sikeresen módosítva." -#: contrib/admin/views/main.py:354 +#: contrib/admin/views/main.py:360 #, python-format -msgid "" -"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below." -msgstr "" -"A(z) %(name)s \"%(obj)s\" sikeresen hozzáadva. Alább ismét szerkesztheted." +msgid "The %(name)s \"%(obj)s\" was added successfully. You may edit it again below." +msgstr "\"%(obj)s\" %(name)s sikeresen létrehozva. Alább ismét szerkesztheted." -#: contrib/admin/views/main.py:392 +#: contrib/admin/views/main.py:398 #, python-format msgid "Change %s" -msgstr "%s megváltoztatása" +msgstr "%s módosítása" -#: contrib/admin/views/main.py:470 +# TODO +#: contrib/admin/views/main.py:483 #, python-format msgid "One or more %(fieldname)s in %(name)s: %(obj)s" msgstr "Egy vagy több %(fieldname)s a(z) %(name)s -ban: %(obj)s" -#: contrib/admin/views/main.py:475 +# TODO +#: contrib/admin/views/main.py:488 #, python-format msgid "One or more %(fieldname)s in %(name)s:" msgstr "Egy vagy több %(fieldname)s a(z) %(name)s:" -#: contrib/admin/views/main.py:508 +#: contrib/admin/views/main.py:520 #, python-format msgid "The %(name)s \"%(obj)s\" was deleted successfully." -msgstr "A(z) %(name)s \"%(obj)s\" sikeresen törölve." +msgstr "\"%(obj)s\" %(name)s sikeresen törölve." -#: contrib/admin/views/main.py:511 +#: contrib/admin/views/main.py:523 msgid "Are you sure?" -msgstr "Biztos vagy benne?" +msgstr "Biztos benne?" -#: contrib/admin/views/main.py:533 +#: contrib/admin/views/main.py:545 #, python-format msgid "Change history: %s" msgstr "Változások története: %s" -#: contrib/admin/views/main.py:565 +#: contrib/admin/views/main.py:579 #, python-format msgid "Select %s" msgstr "Kiválasztás %s" -#: contrib/admin/views/main.py:565 +#: contrib/admin/views/main.py:579 #, python-format msgid "Select %s to change" -msgstr "Válaszd a(z) %s a változtatáshoz" +msgstr "Válasszon ki egyet a módosításhoz (%s)" + +#: contrib/admin/views/main.py:780 +msgid "Database error" +msgstr "Adatbázis hiba" + +#: contrib/admin/views/decorators.py:10 contrib/auth/forms.py:60 +msgid "" +"Please enter a correct username and password. Note that both fields are case-" +"sensitive." +msgstr "" +"Írjon be egy helyes felhasználónevet és jelszót. Mindkét mező kisbetű-" +"nagybetű érzékeny." + +#: contrib/admin/views/decorators.py:24 +#: contrib/admin/templates/admin/login.html:25 +msgid "Log in" +msgstr "Bejelentkezés" + +#: contrib/admin/views/decorators.py:62 +msgid "" +"Please log in again, because your session has expired. Don't worry: Your " +"submission has been saved." +msgstr "" +"Jelentkezzen be újra, mert a munkamenete végetért. Ne aggódjon, minden " +"beküldött adata el van mentve." + +#: contrib/admin/views/decorators.py:69 +msgid "" +"Looks like your browser isn't configured to accept cookies. Please enable " +"cookies, reload this page, and try again." +msgstr "" +"Úgy tűnik a böngészőjében nincs engedélyezve a cookie-k fogadása. Kérem " +"engedélyezze és töltse újra az oldalt!" + +#: contrib/admin/views/decorators.py:83 +msgid "Usernames cannot contain the '@' character." +msgstr "A felhasználónév nem tartalmazhat '@' karaktert." + +#: contrib/admin/views/decorators.py:85 +#, python-format +msgid "Your e-mail address is not your username. Try '%s' instead." +msgstr "Az email címe nem a felhasználóneve. Próbálja inkább ezt: %s." + +#: contrib/admin/views/doc.py:47 contrib/admin/views/doc.py:49 +#: contrib/admin/views/doc.py:51 +msgid "tag:" +msgstr "címke:" + +#: contrib/admin/views/doc.py:78 contrib/admin/views/doc.py:80 +#: contrib/admin/views/doc.py:82 +msgid "filter:" +msgstr "szűrő:" + +#: contrib/admin/views/doc.py:136 contrib/admin/views/doc.py:138 +#: contrib/admin/views/doc.py:140 +msgid "view:" +msgstr "nézet:" + +#: contrib/admin/views/doc.py:165 +#, python-format +msgid "App %r not found" +msgstr "%r alkalmazás nem található" + +#: contrib/admin/views/doc.py:172 +#, python-format +msgid "Model %(name)r not found in app %(label)r" +msgstr "%(name)r modell nem található a következő alkalmazásban: %(label)r" + +#: contrib/admin/views/doc.py:184 +#, python-format +msgid "the related `%(label)s.%(type)s` object" +msgstr "a kapcsolódó '%(label)s.%(type)s' objektum" + +#: contrib/admin/views/doc.py:184 contrib/admin/views/doc.py:206 +#: contrib/admin/views/doc.py:220 contrib/admin/views/doc.py:225 +msgid "model:" +msgstr "modell:" + +#: contrib/admin/views/doc.py:215 +#, python-format +msgid "related `%(label)s.%(name)s` objects" +msgstr "kapcsolódó '%(label)s.%(name)sí' objektumok" + +#: contrib/admin/views/doc.py:220 +#, python-format +msgid "all %s" +msgstr "minden %s" + +#: contrib/admin/views/doc.py:225 +#, python-format +msgid "number of %s" +msgstr "%s mennyisége" -#: contrib/admin/views/doc.py:277 contrib/admin/views/doc.py:286 -#: contrib/admin/views/doc.py:288 contrib/admin/views/doc.py:294 -#: contrib/admin/views/doc.py:295 contrib/admin/views/doc.py:297 +#: contrib/admin/views/doc.py:230 +#, python-format +msgid "Fields on %s objects" +msgstr "Mezők %s objektumokban" + +#: contrib/admin/views/doc.py:292 contrib/admin/views/doc.py:303 +#: contrib/admin/views/doc.py:305 contrib/admin/views/doc.py:311 +#: contrib/admin/views/doc.py:312 contrib/admin/views/doc.py:314 msgid "Integer" msgstr "Egész" -#: contrib/admin/views/doc.py:278 +#: contrib/admin/views/doc.py:293 msgid "Boolean (Either True or False)" msgstr "Logikai (True vagy False)" -#: contrib/admin/views/doc.py:279 contrib/admin/views/doc.py:296 +#: contrib/admin/views/doc.py:294 contrib/admin/views/doc.py:313 #, python-format -msgid "String (up to %(maxlength)s)" -msgstr "Karakterlánc (%(maxlength)s hosszig)" +msgid "String (up to %(max_length)s)" +msgstr "Karakterlánc (%(max_length)s hosszig)" -#: contrib/admin/views/doc.py:280 +#: contrib/admin/views/doc.py:295 msgid "Comma-separated integers" msgstr "Vesszővel elválasztott egészek" -#: contrib/admin/views/doc.py:281 +#: contrib/admin/views/doc.py:296 msgid "Date (without time)" msgstr "Dátum (idő nélkül)" -#: contrib/admin/views/doc.py:282 +#: contrib/admin/views/doc.py:297 msgid "Date (with time)" msgstr "Dátum (idővel)" -#: contrib/admin/views/doc.py:283 +#: contrib/admin/views/doc.py:298 +msgid "Decimal number" +msgstr "Tizes számrendszerű (decimális) szám" + +#: contrib/admin/views/doc.py:299 msgid "E-mail address" msgstr "E-mail cím" -#: contrib/admin/views/doc.py:284 contrib/admin/views/doc.py:287 +#: contrib/admin/views/doc.py:300 contrib/admin/views/doc.py:301 +#: contrib/admin/views/doc.py:304 msgid "File path" msgstr "Elérési út" -#: contrib/admin/views/doc.py:285 -msgid "Decimal number" -msgstr "Tizes számrendszerű szám" +#: contrib/admin/views/doc.py:302 +msgid "Floating point number" +msgstr "Lebegőpontos szám" -#: contrib/admin/views/doc.py:291 +#: contrib/admin/views/doc.py:308 msgid "Boolean (Either True, False or None)" msgstr "Logikai (True, False vagy None)" -#: contrib/admin/views/doc.py:292 +#: contrib/admin/views/doc.py:309 msgid "Relation to parent model" msgstr "Szülőkapcsolat" -#: contrib/admin/views/doc.py:293 +#: contrib/admin/views/doc.py:310 msgid "Phone number" msgstr "Telefonszám" -#: contrib/admin/views/doc.py:298 +#: contrib/admin/views/doc.py:315 msgid "Text" msgstr "Szöveg" -#: contrib/admin/views/doc.py:299 +#: contrib/admin/views/doc.py:316 msgid "Time" msgstr "Idő" -#: contrib/admin/views/doc.py:300 contrib/flatpages/models.py:7 +#: contrib/admin/views/doc.py:317 contrib/flatpages/models.py:7 msgid "URL" msgstr "URL" -#: contrib/admin/views/doc.py:301 +#: contrib/admin/views/doc.py:318 msgid "U.S. state (two uppercase letters)" msgstr "USA állam (két nagybetű)" -#: contrib/admin/views/doc.py:302 +#: contrib/admin/views/doc.py:319 msgid "XML text" msgstr "XML szöveg" -#: contrib/admin/templates/admin/object_history.html:3 +#: contrib/admin/views/doc.py:345 +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s nem tűnik egy urlpattern objektumnak." + +#: contrib/admin/templates/widget/file.html:2 +msgid "Currently:" +msgstr "Éppen:" + +#: contrib/admin/templates/widget/file.html:3 +msgid "Change:" +msgstr "Változás:" + +#: contrib/admin/templates/widget/date_time.html:3 +msgid "Date:" +msgstr "Dátum:" + +#: contrib/admin/templates/widget/date_time.html:4 +msgid "Time:" +msgstr "Idő:" + #: contrib/admin/templates/admin/change_list.html:5 -#: contrib/admin/templates/admin/base.html:23 -#: contrib/admin/templates/admin/delete_confirmation.html:3 +#: contrib/admin/templates/admin/object_history.html:3 #: contrib/admin/templates/admin/change_form.html:10 +#: contrib/admin/templates/admin/delete_confirmation.html:3 +#: contrib/admin/templates/admin/base.html:25 +#: contrib/admin/templates/admin/auth/user/change_password.html:9 #: contrib/admin/templates/registration/password_change_done.html:3 #: contrib/admin/templates/registration/password_change_form.html:3 #: contrib/admin/templates/admin_doc/bookmarklets.html:3 msgid "Documentation" msgstr "Dokumentáció" -#: contrib/admin/templates/admin/object_history.html:3 #: contrib/admin/templates/admin/change_list.html:5 -#: contrib/admin/templates/admin/base.html:23 -#: contrib/admin/templates/admin/delete_confirmation.html:3 +#: contrib/admin/templates/admin/object_history.html:3 #: contrib/admin/templates/admin/change_form.html:10 +#: contrib/admin/templates/admin/delete_confirmation.html:3 +#: contrib/admin/templates/admin/base.html:25 +#: contrib/admin/templates/admin/auth/user/change_password.html:9 +#: contrib/admin/templates/admin/auth/user/change_password.html:15 +#: contrib/admin/templates/admin/auth/user/change_password.html:46 #: contrib/admin/templates/registration/password_change_done.html:3 #: contrib/admin/templates/registration/password_change_form.html:3 -#: contrib/admin/templates/admin_doc/bookmarklets.html:4 #: contrib/admin/templates/admin_doc/view_detail.html:4 -#: contrib/admin/templates/admin_doc/template_tag_index.html:5 +#: contrib/admin/templates/admin_doc/bookmarklets.html:4 #: contrib/admin/templates/admin_doc/template_detail.html:4 -#: contrib/admin/templates/admin_doc/template_filter_index.html:5 +#: contrib/admin/templates/admin_doc/template_tag_index.html:5 #: contrib/admin/templates/admin_doc/missing_docutils.html:4 #: contrib/admin/templates/admin_doc/view_index.html:5 #: contrib/admin/templates/admin_doc/model_detail.html:3 #: contrib/admin/templates/admin_doc/index.html:4 #: contrib/admin/templates/admin_doc/model_index.html:5 +#: contrib/admin/templates/admin_doc/template_filter_index.html:5 msgid "Change password" msgstr "Jelszó megváltoztatása" +#: contrib/admin/templates/admin/change_list.html:6 #: contrib/admin/templates/admin/object_history.html:5 #: contrib/admin/templates/admin/500.html:4 -#: contrib/admin/templates/admin/change_list.html:6 -#: contrib/admin/templates/admin/base.html:28 -#: contrib/admin/templates/admin/delete_confirmation.html:6 +#: contrib/admin/templates/admin/invalid_setup.html:4 #: contrib/admin/templates/admin/change_form.html:13 +#: contrib/admin/templates/admin/delete_confirmation.html:6 +#: contrib/admin/templates/admin/base.html:30 +#: contrib/admin/templates/admin/auth/user/change_password.html:12 #: contrib/admin/templates/registration/password_change_done.html:4 #: contrib/admin/templates/registration/password_reset_form.html:4 #: contrib/admin/templates/registration/logged_out.html:4 @@ -689,8 +1605,18 @@ msgstr "Jelszó megváltoztatása" msgid "Home" msgstr "Kezdőlap" +#: contrib/admin/templates/admin/change_list.html:12 +#, python-format +msgid "Add %(name)s" +msgstr "Új %(name)s" + +#: contrib/admin/templates/admin/filter.html:2 +#, python-format +msgid " By %(filter_title)s " +msgstr " %(filter_title)s szerint " + #: contrib/admin/templates/admin/object_history.html:5 -#: contrib/admin/templates/admin/change_form.html:20 +#: contrib/admin/templates/admin/change_form.html:21 msgid "History" msgstr "Történet" @@ -706,6 +1632,7 @@ msgstr "Felhasználó" msgid "Action" msgstr "Művelet" +# TODO #: contrib/admin/templates/admin/object_history.html:26 msgid "DATE_WITH_TIME_FULL" msgstr "N j, Y, P" @@ -718,6 +1645,26 @@ msgstr "" "Az objektumnak nincs változási története. Valószínűleg nem ezen a " "karbantartó oldalon lett rögzítve." +#: contrib/admin/templates/admin/search_form.html:8 +msgid "Go" +msgstr "Mehet" + +#: contrib/admin/templates/admin/search_form.html:10 +#, python-format +msgid "1 result" +msgid_plural "%(counter)s results" +msgstr[0] "Egy találat." +msgstr[1] "%(counter)s találat." + +#: contrib/admin/templates/admin/search_form.html:10 +#, python-format +msgid "%(full_result_count)s total" +msgstr "%(full_result_count)s összesen" + +#: contrib/admin/templates/admin/pagination.html:10 +msgid "Show all" +msgstr "Mutassa mindet" + #: contrib/admin/templates/admin/base_site.html:4 msgid "Django site admin" msgstr "Django honlap adminisztráció" @@ -728,15 +1675,15 @@ msgstr "Django adminisztráció" #: contrib/admin/templates/admin/500.html:4 msgid "Server error" -msgstr "Szerver hiba" +msgstr "Szerverhiba" #: contrib/admin/templates/admin/500.html:6 msgid "Server error (500)" -msgstr "Szerver hiba (500)" +msgstr "Szerverhiba (500)" #: contrib/admin/templates/admin/500.html:9 msgid "Server Error <em>(500)</em>" -msgstr "Szerver hiba <em>(500)</em>" +msgstr "Szerverhiba <em>(500)</em>" #: contrib/admin/templates/admin/500.html:10 msgid "" @@ -744,38 +1691,44 @@ msgid "" "mail and should be fixed shortly. Thanks for your patience." msgstr "" "Hiba történt, melyet e-mailben jelentettünk az oldal karbantartójának. A " -"rendszer remélhetően hamar megjavul, köszönjük a türelmedet." - -#: contrib/admin/templates/admin/404.html:4 -#: contrib/admin/templates/admin/404.html:8 -msgid "Page not found" -msgstr "Nincs ilyen oldal" +"rendszer remélhetően hamar megjavul. Köszönjük a türelmét." -#: contrib/admin/templates/admin/404.html:10 -msgid "We're sorry, but the requested page could not be found." -msgstr "Sajnáljuk, a kért oldalt nem találjuk." +#: contrib/admin/templates/admin/invalid_setup.html:8 +msgid "" +"Something's wrong with your database installation. Make sure the appropriate " +"database tables have been created, and make sure the database is readable by " +"the appropriate user." +msgstr "" +"Valami nem stimmel a telepített adatbázissal. Bizonyosodjon meg arról, hogy " +"a megfelelő táblák létre lettek-e hozva, és hogy a megfelelő felhasználó " +"tudja-e őket olvasni." #: contrib/admin/templates/admin/index.html:17 #, python-format msgid "Models available in the %(name)s application." -msgstr "" +msgstr "%(name)s alkalmazásban elérhető modellek." + +#: contrib/admin/templates/admin/index.html:18 +#, python-format +msgid "%(name)s" +msgstr "%(name)s" #: contrib/admin/templates/admin/index.html:28 #: contrib/admin/templates/admin/change_form.html:15 msgid "Add" -msgstr "Hozzáadás" +msgstr "Új" #: contrib/admin/templates/admin/index.html:34 msgid "Change" -msgstr "Változtatás" +msgstr "Módosítás" #: contrib/admin/templates/admin/index.html:44 msgid "You don't have permission to edit anything." -msgstr "Nincs jogod szerkeszteni." +msgstr "Nincs joga szerkeszteni." #: contrib/admin/templates/admin/index.html:52 msgid "Recent Actions" -msgstr "Utóbbi műveletek" +msgstr "Utolsó műveletek" #: contrib/admin/templates/admin/index.html:53 msgid "My Actions" @@ -785,18 +1738,37 @@ msgstr "Az én műveleteim" msgid "None available" msgstr "Nincs elérhető" -#: contrib/admin/templates/admin/change_list.html:11 -#, python-format -msgid "Add %(name)s" -msgstr "%(name)s hozzáadása" +#: contrib/admin/templates/admin/404.html:4 +#: contrib/admin/templates/admin/404.html:8 +msgid "Page not found" +msgstr "Nincs ilyen oldal" + +#: contrib/admin/templates/admin/404.html:10 +msgid "We're sorry, but the requested page could not be found." +msgstr "Sajnáljuk, de a kért oldal nem található." -#: contrib/admin/templates/admin/login.html:22 -msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?" -msgstr "Csak nem <a href=\"/password_reset/\">elfelejtetted a jelszavadat</a>?" +#: contrib/admin/templates/admin/filters.html:4 +msgid "Filter" +msgstr "Szűrő" -#: contrib/admin/templates/admin/base.html:23 -msgid "Welcome," -msgstr "Üdvözöllek," +#: contrib/admin/templates/admin/change_form.html:22 +msgid "View on site" +msgstr "Megtekintés a honlapon" + +#: contrib/admin/templates/admin/change_form.html:32 +#: contrib/admin/templates/admin/auth/user/change_password.html:24 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "Kérem javítsa az alábbi hibát." +msgstr[1] "Kérlem javítsa az alábbi hibákat." + +#: contrib/admin/templates/admin/change_form.html:50 +msgid "Ordering" +msgstr "Rendezés" + +#: contrib/admin/templates/admin/change_form.html:53 +msgid "Order:" +msgstr "Rendezés:" #: contrib/admin/templates/admin/delete_confirmation.html:9 #: contrib/admin/templates/admin/submit_line.html:3 @@ -806,53 +1778,30 @@ msgstr "Törlés" #: contrib/admin/templates/admin/delete_confirmation.html:14 #, python-format msgid "" -"Deleting the %(object_name)s '%(object)s' would result in deleting related " -"objects, but your account doesn't have permission to delete the following " -"types of objects:" +"Deleting the %(object_name)s '%(escaped_object)s' would result in deleting " +"related objects, but your account doesn't have permission to delete the " +"following types of objects:" msgstr "" -"A(z) %(object_name)s '%(object)s' törlése a kapcsolódó objektumok törlését " -"is eredményezi, de a hozzáférésed nem engedi a következő típusú objektumok " -"törlését:" +"'%(escaped_object)s' %(object_name)s törlése a kapcsolódó objektumok " +"törlését is eredményezi, de a hozzáférése nem engedi a következő típusú " +"objektumok törlését:" #: contrib/admin/templates/admin/delete_confirmation.html:21 #, python-format msgid "" -"Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of " -"the following related items will be deleted:" +"Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? " +"All of the following related items will be deleted:" msgstr "" -"Biztos hogy törlöd a(z) %(object_name)s \"%(object)s\"? A összes következő " -"kapcsolódó elem is törlődik:" +"Biztos hogy törli a következőt: \"%(escaped_object)s\" (típus: %(object_name)" +"s)? A összes további kapcsolódó elem is törlődik:" #: contrib/admin/templates/admin/delete_confirmation.html:26 msgid "Yes, I'm sure" msgstr "Igen, biztos vagyok benne" -#: contrib/admin/templates/admin/filter.html:2 -#, python-format -msgid " By %(title)s " -msgstr " Szerző %(title)s " - -#: contrib/admin/templates/admin/search_form.html:8 -msgid "Go" -msgstr "Mehet" - -#: contrib/admin/templates/admin/change_form.html:21 -msgid "View on site" -msgstr "Megtekintés a honlapon" - -#: contrib/admin/templates/admin/change_form.html:30 -msgid "Please correct the error below." -msgid_plural "Please correct the errors below." -msgstr[0] "Kérlek javítsd az alábbi hibát." -msgstr[1] "Kérlek javítsd az alábbi hibákat." - -#: contrib/admin/templates/admin/change_form.html:48 -msgid "Ordering" -msgstr "Rendezés" - -#: contrib/admin/templates/admin/change_form.html:51 -msgid "Order:" -msgstr "Rendezettség:" +#: contrib/admin/templates/admin/base.html:25 +msgid "Welcome," +msgstr "Üdvözlöm," #: contrib/admin/templates/admin/submit_line.html:4 msgid "Save as new" @@ -870,12 +1819,44 @@ msgstr "Mentés és a szerkesztés folytatása" msgid "Save" msgstr "Mentés" +#: contrib/admin/templates/admin/auth/user/change_password.html:28 +#, python-format +msgid "Enter a new password for the user <strong>%(username)s</strong>." +msgstr "Adjon meg egy új jelszót a <strong>%(username)s</strong> nevű felhasználónak." + +#: contrib/admin/templates/admin/auth/user/change_password.html:34 +#: contrib/admin/templates/admin/auth/user/add_form.html:18 +msgid "Password" +msgstr "Jelszó" + +#: contrib/admin/templates/admin/auth/user/change_password.html:39 +#: contrib/admin/templates/admin/auth/user/add_form.html:23 +msgid "Password (again)" +msgstr "Jelszó újra" + +#: contrib/admin/templates/admin/auth/user/change_password.html:40 +#: contrib/admin/templates/admin/auth/user/add_form.html:24 +msgid "Enter the same password as above, for verification." +msgstr "Írja be a fenti jelszót ellenőrzés céljából." + +#: contrib/admin/templates/admin/auth/user/add_form.html:6 +msgid "" +"First, enter a username and password. Then, you'll be able to edit more user " +"options." +msgstr "" +"Először adjon meg egy felhasználói nevet és egy jelszót. Ezek után további " +"módosításokat is végezhet a felhasználó adatain." + +#: contrib/admin/templates/admin/auth/user/add_form.html:12 +msgid "Username" +msgstr "Felhasználó" + #: contrib/admin/templates/registration/password_change_done.html:4 #: contrib/admin/templates/registration/password_change_form.html:4 #: contrib/admin/templates/registration/password_change_form.html:6 #: contrib/admin/templates/registration/password_change_form.html:10 msgid "Password change" -msgstr "Jelszó változtatása" +msgstr "Jelszó megváltoztatása" #: contrib/admin/templates/registration/password_change_done.html:6 #: contrib/admin/templates/registration/password_change_done.html:10 @@ -884,22 +1865,22 @@ msgstr "Sikeres jelszóváltoztatás" #: contrib/admin/templates/registration/password_change_done.html:12 msgid "Your password was changed." -msgstr "Jelszavad megváltozott." +msgstr "Megváltozott a jelszava." #: contrib/admin/templates/registration/password_reset_form.html:4 #: contrib/admin/templates/registration/password_reset_form.html:6 #: contrib/admin/templates/registration/password_reset_form.html:10 #: contrib/admin/templates/registration/password_reset_done.html:4 msgid "Password reset" -msgstr "Jelszó törlés" +msgstr "Jelszó törlése" #: contrib/admin/templates/registration/password_reset_form.html:12 msgid "" "Forgotten your password? Enter your e-mail address below, and we'll reset " "your password and e-mail the new one to you." msgstr "" -"Elfelejtetted a jelszavad? Írd be az e-mail címed, mi töröljük a jelszavad " -"és az újat e-mailben elküldjük neked." +"Elfelejtette a jelszavát? Írja be az e-mail címét, mi töröljük a jelszavát " +"és az újat e-mailben elküldjük." #: contrib/admin/templates/registration/password_reset_form.html:16 msgid "E-mail address:" @@ -911,11 +1892,11 @@ msgstr "Jelszavam törlése" #: contrib/admin/templates/registration/logged_out.html:8 msgid "Thanks for spending some quality time with the Web site today." -msgstr "Köszönjük hogy egy kis időt töltöttél a honlapunkon." +msgstr "Köszönjük hogy egy kis időt eltöltött ma a honlapunkon." #: contrib/admin/templates/registration/logged_out.html:10 msgid "Log in again" -msgstr "Jelentkezz be újra" +msgstr "Jelentkezzen be újra" #: contrib/admin/templates/registration/password_reset_done.html:6 #: contrib/admin/templates/registration/password_reset_done.html:10 @@ -926,15 +1907,17 @@ msgstr "Sikeres jelszótörlés" msgid "" "We've e-mailed a new password to the e-mail address you submitted. You " "should be receiving it shortly." -msgstr "Új jelszavadat elküldtük e-mailben. Hamarosan meg kell kapnod." +msgstr "" +"Új jelszavát elküldtük e-mailben a megadott címre. Hamarosan meg kell " +"érkeznie." #: contrib/admin/templates/registration/password_change_form.html:12 msgid "" "Please enter your old password, for security's sake, and then enter your new " "password twice so we can verify you typed it in correctly." msgstr "" -"Írd be a régi jelszavad biztonsági okokból, majd az újat kétszer, hogy " -"biztosan ne gépeld el." +"Írja be a régi jelszavát biztonsági okokból, majd az újat kétszer, hogy " +"biztosan ne gépelje el." #: contrib/admin/templates/registration/password_change_form.html:17 msgid "Old password:" @@ -954,34 +1937,34 @@ msgstr "Jelszavam megváltoztatása" #: contrib/admin/templates/registration/password_reset_email.html:2 msgid "You're receiving this e-mail because you requested a password reset" -msgstr "Ezt az e-mail-t azért kaptad, mert jelszótörlést kértél" +msgstr "Ezt az e-mail-t azért kapta, mert jelszótörlést kért" #: contrib/admin/templates/registration/password_reset_email.html:3 #, python-format msgid "for your user account at %(site_name)s" -msgstr "hozzáférésedhez a következő honlapon: %(site_name)s" +msgstr "hozzáféréséhez a következő honlapon: %(site_name)s" #: contrib/admin/templates/registration/password_reset_email.html:5 #, python-format msgid "Your new password is: %(new_password)s" -msgstr "Új jelszavad: %(new_password)s" +msgstr "Új jelszava: %(new_password)s" #: contrib/admin/templates/registration/password_reset_email.html:7 msgid "Feel free to change this password by going to this page:" -msgstr "Bármikor megváltoztathatod a jelszavad a következő oldalon:" +msgstr "Bármikor megváltoztathatja a jelszavát a következő oldalon:" #: contrib/admin/templates/registration/password_reset_email.html:11 msgid "Your username, in case you've forgotten:" -msgstr "Felhasználóneved, ha elfelejtetted volna:" +msgstr "Felhasználóneve, ha elfelejtette volna:" #: contrib/admin/templates/registration/password_reset_email.html:13 msgid "Thanks for using our site!" -msgstr "Köszönjük, hogy használtad honlapunkat!" +msgstr "Köszönjük, hogy használta honlapunkat!" #: contrib/admin/templates/registration/password_reset_email.html:15 #, python-format msgid "The %(site_name)s team" -msgstr "A %(site_name)s csapata" +msgstr "%(site_name)s csapat" #: contrib/admin/templates/admin_doc/bookmarklets.html:3 msgid "Bookmarklets" @@ -1002,11 +1985,12 @@ msgid "" "your computer is \"internal\").</p>\n" msgstr "" "\n" -"<p class=\"help\">A könyvjelzők felvételéhez húzd a könyvjelzők linkjét az " -"eszköztárra, vagy kattints rájuk jobb egérgombot és úgy add hozzá. Ezután \n" -"már ki tudod választani a könyvjelzőt a honlap bármely oldaláról. A " -"könyvjelzők között néhány oldal csak 'belső' gépekről nézhető meg.\n" -"(Beszélj a rendszergazdával hogy a te géped 'belső' gép-e.).</p>\n" +"<p class=\"help\">A könyvjelzők felvételéhez húzza a könyvjelzők linkjét az " +"eszköztárra, vagy kattintson rájuk jobb egérgombbal és úgy adja hozzá. " +"Ezután \n" +"már ki tudja választani a könyvjelzőt a honlap bármely oldaláról. A " +"könyvjelzők között néhány oldal csak \"belső\" gépekről nézhető meg.\n" +"(Kérdezze meg rendszergazdáját, hogy az Ön gépe \"belső\" gép-e.).</p>\n" #: contrib/admin/templates/admin_doc/bookmarklets.html:19 msgid "Documentation for this page" @@ -1017,12 +2001,12 @@ msgid "" "Jumps you from any page to the documentation for the view that generates " "that page." msgstr "" -"Bármely oldalról annak a nézetnek a dokumentációjára ugrik, mely a kérdéses " +"Bármely oldalról annak a nézetnek a dokumentációjára ugrik, amely a kérdéses " "oldalt generálta." #: contrib/admin/templates/admin_doc/bookmarklets.html:22 msgid "Show object ID" -msgstr "Az objektum ID kijelzése" +msgstr "Az objektum ID mutatása" #: contrib/admin/templates/admin_doc/bookmarklets.html:23 msgid "" @@ -1046,977 +2030,1468 @@ msgstr "Objektum szerkesztése (új ablakban)" #: contrib/admin/templates/admin_doc/bookmarklets.html:29 msgid "As above, but opens the admin page in a new window." -msgstr "Mint fentebb, de az adminisztrációs oldalt új ablakban nyitja." - -#: contrib/admin/templates/widget/date_time.html:3 -msgid "Date:" -msgstr "Dátum:" - -#: contrib/admin/templates/widget/date_time.html:4 -msgid "Time:" -msgstr "Idő:" - -#: contrib/admin/templates/widget/file.html:2 -msgid "Currently:" -msgstr "Éppen:" - -#: contrib/admin/templates/widget/file.html:3 -msgid "Change:" -msgstr "Változás:" - -#: contrib/redirects/models.py:7 -msgid "redirect from" -msgstr "átirányítva innen" - -#: contrib/redirects/models.py:8 -msgid "" -"This should be an absolute path, excluding the domain name. Example: '/" -"events/search/'." -msgstr "" -"Ennek abszolút elérési útnak kell lennie, a domén név nélkül. Példa: '/" -"events/search/'" - -#: contrib/redirects/models.py:9 -msgid "redirect to" -msgstr "átirányítva ide" +msgstr "Mint fentebb, de az adminisztrációs oldalt új ablakban nyitja meg." -#: contrib/redirects/models.py:10 -msgid "" -"This can be either an absolute path (as above) or a full URL starting with " -"'http://'." -msgstr "" -"Ennek vagy abszolút elérési útnak kell lennie (mint fentebb) vagy teljes URL-" -"nek 'http://' -vel kezdve." - -#: contrib/redirects/models.py:12 -msgid "redirect" -msgstr "átirányítás" - -#: contrib/redirects/models.py:13 -msgid "redirects" -msgstr "átirányít" - -#: contrib/flatpages/models.py:8 -msgid "" -"Example: '/about/contact/'. Make sure to have leading and trailing slashes." -msgstr "Például: '/about/contact/'. Figyelj a nyitó és záró perjelre!" - -#: contrib/flatpages/models.py:9 -msgid "title" -msgstr "cím" - -#: contrib/flatpages/models.py:10 -msgid "content" -msgstr "tartalom" - -#: contrib/flatpages/models.py:11 -msgid "enable comments" -msgstr "megjegyzések engedélyezése" - -#: contrib/flatpages/models.py:12 -msgid "template name" -msgstr "sablon neve" - -#: contrib/flatpages/models.py:13 -msgid "" -"Example: 'flatpages/contact_page'. If this isn't provided, the system will " -"use 'flatpages/default'." -msgstr "" -"Példa: 'flatpages/contact_page'. Ha ez nem létezik, a rendszer a 'flatpages/" -"default' -ot használja." - -#: contrib/flatpages/models.py:14 -msgid "registration required" -msgstr "regisztráció szükséges" +#: contrib/contenttypes/models.py:37 +msgid "python model class name" +msgstr "python modell osztály neve" -#: contrib/flatpages/models.py:14 -msgid "If this is checked, only logged-in users will be able to view the page." -msgstr "" -"Ha ez be van jelölve, csak bejelentkezett felhasználó tudja az oldalt " -"megnézni." +#: contrib/contenttypes/models.py:40 +msgid "content type" +msgstr "tartalom típusa" -#: contrib/flatpages/models.py:18 -msgid "flat page" -msgstr "egyszerű oldal" +#: contrib/contenttypes/models.py:41 +msgid "content types" +msgstr "tartalom típusok" -#: contrib/flatpages/models.py:19 -msgid "flat pages" -msgstr "egyszerű oldalak" +#: contrib/auth/views.py:47 +msgid "Logged out" +msgstr "Kijelentkezve" -#: contrib/auth/models.py:13 contrib/auth/models.py:26 +#: contrib/auth/models.py:53 contrib/auth/models.py:73 msgid "name" msgstr "név" -#: contrib/auth/models.py:15 +#: contrib/auth/models.py:55 msgid "codename" msgstr "kódnév" -#: contrib/auth/models.py:17 -#, fuzzy +#: contrib/auth/models.py:58 msgid "permission" -msgstr "Engedély" +msgstr "jogosultság" -#: contrib/auth/models.py:18 contrib/auth/models.py:27 -#, fuzzy +#: contrib/auth/models.py:59 contrib/auth/models.py:74 msgid "permissions" -msgstr "Engedélyek" +msgstr "jogosultságok" -#: contrib/auth/models.py:29 -#, fuzzy +#: contrib/auth/models.py:77 msgid "group" -msgstr "Csoport" +msgstr "csoport" -#: contrib/auth/models.py:30 contrib/auth/models.py:65 -#, fuzzy +#: contrib/auth/models.py:78 contrib/auth/models.py:121 msgid "groups" -msgstr "Csoportok" +msgstr "csoportok" -#: contrib/auth/models.py:55 +#: contrib/auth/models.py:111 msgid "username" msgstr "felhasználónév" -#: contrib/auth/models.py:56 +#: contrib/auth/models.py:111 +msgid "" +"Required. 30 characters or fewer. Alphanumeric characters only (letters, " +"digits and underscores)." +msgstr "" +"Kötelező. Legfeljebb 30 karakter. Csak alfanumerikus karaktereket " +"tartalmazhat (betűk, számok és aláhúzás)." + +#: contrib/auth/models.py:112 msgid "first name" msgstr "keresztnév" -#: contrib/auth/models.py:57 +#: contrib/auth/models.py:113 msgid "last name" msgstr "vezetéknév" -#: contrib/auth/models.py:58 +#: contrib/auth/models.py:114 msgid "e-mail address" msgstr "e-mail cím" -#: contrib/auth/models.py:59 +#: contrib/auth/models.py:115 msgid "password" msgstr "jelszó" -#: contrib/auth/models.py:59 -msgid "Use '[algo]$[salt]$[hexdigest]'" -msgstr "Használat '[algo]$[salt]$[hexdigest]'" +#: contrib/auth/models.py:115 +msgid "" +"Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change " +"password form</a>." +msgstr "" +"Használja az \"[algo]$[salt]$[hexdigest]\" formátumot, vagy a <a href=" +"\"password/\">jelszó megváltoztatása űrlapot</a>." -#: contrib/auth/models.py:60 +#: contrib/auth/models.py:116 msgid "staff status" -msgstr "Személyzet státusa" +msgstr "személyzet státusz" -#: contrib/auth/models.py:60 +#: contrib/auth/models.py:116 msgid "Designates whether the user can log into this admin site." -msgstr "" -"Megadja hogy a felhasználó bejelentkezhet-e erre az adminisztrációs oldalra." +msgstr "Megadja, hogy a felhasználó bejelentkezhet-e erre az adminisztrációs oldalra." -#: contrib/auth/models.py:61 +#: contrib/auth/models.py:117 msgid "active" msgstr "aktív" -#: contrib/auth/models.py:62 +#: contrib/auth/models.py:117 +msgid "" +"Designates whether this user can log into the Django admin. Unselect this " +"instead of deleting accounts." +msgstr "" +"Megadja, hogy a felhasználó bejelentkezhet-e erre az adminisztrációs " +"oldalra. Állítsa át ezt az értéket a fiókok törlése helyett." + +#: contrib/auth/models.py:118 msgid "superuser status" msgstr "rendszergazda státusz" -#: contrib/auth/models.py:63 +#: contrib/auth/models.py:118 +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Megadja, hogy ez a felhasználó rendelkezik-e minden jogosultsággal anélkül, " +"hogy azt külön meg kellene adni." + +#: contrib/auth/models.py:119 msgid "last login" msgstr "utolsó bejelentkezés" -#: contrib/auth/models.py:64 +#: contrib/auth/models.py:120 msgid "date joined" msgstr "csatlakozás dátuma" -#: contrib/auth/models.py:66 +#: contrib/auth/models.py:122 msgid "" "In addition to the permissions manually assigned, this user will also get " "all permissions granted to each group he/she is in." msgstr "" -"A kézzel beállított jogosultságok mellett a felhasználó a csoportjának a " +"A kézzel beállított jogosultságok mellett a felhasználó a csoportjának " "jogait is megkapja." -#: contrib/auth/models.py:67 -#, fuzzy +#: contrib/auth/models.py:123 msgid "user permissions" -msgstr "Engedélyek" +msgstr "felhasználói jogosultságok" -#: contrib/auth/models.py:70 -#, fuzzy +#: contrib/auth/models.py:127 msgid "user" -msgstr "Felhasználó" +msgstr "felhasználó" -#: contrib/auth/models.py:71 -#, fuzzy +#: contrib/auth/models.py:128 msgid "users" -msgstr "Felhasználók" +msgstr "felhasználók" -#: contrib/auth/models.py:76 +#: contrib/auth/models.py:134 msgid "Personal info" -msgstr "Személyes információ" +msgstr "személyes információ" -#: contrib/auth/models.py:77 +#: contrib/auth/models.py:135 msgid "Permissions" -msgstr "Engedélyek" +msgstr "jogosultságok" -#: contrib/auth/models.py:78 +#: contrib/auth/models.py:136 msgid "Important dates" msgstr "Fontos dátumok" -#: contrib/auth/models.py:79 +#: contrib/auth/models.py:137 msgid "Groups" msgstr "Csoportok" -#: contrib/auth/models.py:219 -#, fuzzy +#: contrib/auth/models.py:288 msgid "message" -msgstr "Üzenet" +msgstr "üzenet" + +#: contrib/auth/forms.py:17 contrib/auth/forms.py:138 +msgid "The two password fields didn't match." +msgstr "A két jelszó mező tartalma nem egyezik meg." + +#: contrib/auth/forms.py:25 +msgid "A user with that username already exists." +msgstr "Létezik már egy felhasználó ezzel a névvel." -#: contrib/auth/forms.py:30 +#: contrib/auth/forms.py:53 msgid "" "Your Web browser doesn't appear to have cookies enabled. Cookies are " "required for logging in." msgstr "" -"A böngésződ úgy tűnik nem támogatja a cookie-kat. A cookie-k engedélyezése " +"A böngészője úgy tűnik nem támogatja a cookie-kat. A cookie-k engedélyezése " "szükséges a bejelentkezéshez." -#: contrib/contenttypes/models.py:25 -#, fuzzy -msgid "python model class name" -msgstr "python modul név" +#: contrib/auth/forms.py:62 +msgid "This account is inactive." +msgstr "Ez a fiók inaktív." -#: contrib/contenttypes/models.py:28 -msgid "content type" -msgstr "tartalom típusa" +#: contrib/auth/forms.py:84 +msgid "" +"That e-mail address doesn't have an associated user account. Are you sure " +"you've registered?" +msgstr "" +"Ehhez az e-mail címhez nem tartozik felhasználói fiók. Biztos benne, hogy " +"regisztrált?" -#: contrib/contenttypes/models.py:29 -msgid "content types" -msgstr "tartalom típusok" +#: contrib/auth/forms.py:117 +msgid "The two 'new password' fields didn't match." +msgstr "A két \"új jelszó\" mezó tartalma nem egyezik meg." -#: contrib/sessions/models.py:35 -msgid "session key" -msgstr "munkamenet kulcs" +#: contrib/auth/forms.py:124 +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "A régi jelszó hibásan lett megadva. Írja be újra." -#: contrib/sessions/models.py:36 -msgid "session data" -msgstr "munkamenet adat" +#: contrib/localflavor/uk/forms.py:18 +msgid "Enter a postcode. A space is required between the two postcode parts." +msgstr "" +"Írjon be egy irányítószámot. Az irányítószám két része között szóköznek kell " +"állnia." -#: contrib/sessions/models.py:37 -msgid "expire date" -msgstr "lejárat dátuma" +#: contrib/localflavor/br/forms.py:18 +msgid "Enter a zip code in the format XXXXX-XXX." +msgstr "Írjon be egy irányítószámot 'XXXXX-XXX' alakban." -#: contrib/sessions/models.py:41 -msgid "session" -msgstr "munkamenet" +#: contrib/localflavor/br/forms.py:30 +msgid "Phone numbers must be in XX-XXXX-XXXX format." +msgstr "A telefonszámoknak 'XXX-XXX-XXXX' formátumúnak kell lenniük." -#: contrib/sessions/models.py:42 -msgid "sessions" -msgstr "munkamenetek" +#: contrib/localflavor/br/forms.py:72 +msgid "This field requires only numbers." +msgstr "Ez a mező csak számokat tartalmazhat." -#: contrib/sites/models.py:10 -msgid "domain name" -msgstr "domén neve" +#: contrib/localflavor/br/forms.py:74 +msgid "This field requires at most 11 digits or 14 characters." +msgstr "Ez a mező legfeljebb 11 számjegyet vagy 14 karaktert tartalmazhat." -#: contrib/sites/models.py:11 -msgid "display name" -msgstr "megjelenő név" +#: contrib/localflavor/br/forms.py:84 +msgid "Invalid CPF number." +msgstr "Érvénytelen CPF szám." -#: contrib/sites/models.py:15 -msgid "site" -msgstr "honlap" +#: contrib/localflavor/br/forms.py:106 +msgid "This field requires at least 14 digits" +msgstr "Ennek a mezőnek legalább 14 számjegyet kell tartalmaznia." -#: contrib/sites/models.py:16 -msgid "sites" -msgstr "honlapok" +#: contrib/localflavor/br/forms.py:116 +msgid "Invalid CNPJ number." +msgstr "Érvénytelen CNPJ szám." -#: utils/translation.py:360 -msgid "DATE_FORMAT" -msgstr "N j, Y" +#: contrib/localflavor/au/forms.py:18 +msgid "Enter a 4 digit post code." +msgstr "Írjon be egy négyjegyű irányítószámot." -#: utils/translation.py:361 -msgid "DATETIME_FORMAT" -msgstr "N j, Y, P" +#: contrib/localflavor/fr/forms.py:17 contrib/localflavor/de/forms.py:16 +#: contrib/localflavor/fi/forms.py:14 +msgid "Enter a zip code in the format XXXXX." +msgstr "Írjon be egy irányítószámot 'XXXXX' alakban." -#: utils/translation.py:362 -msgid "TIME_FORMAT" -msgstr "P" +#: contrib/localflavor/us/forms.py:18 +msgid "Enter a zip code in the format XXXXX or XXXXX-XXXX." +msgstr "Írjon be egy irányítószámot 'XXXXX', vagy 'XXXXX-XXXX' alakban." -#: utils/dates.py:6 -msgid "Monday" -msgstr "Hétfő" +#: contrib/localflavor/us/forms.py:51 +msgid "Enter a valid U.S. Social Security number in XXX-XX-XXXX format." +msgstr "Írjon be egy érvényes USA SSN-t 'XXX-XX-XXXX' formátumban." -#: utils/dates.py:6 -msgid "Tuesday" -msgstr "Kedd" +#: contrib/localflavor/de/de_states.py:5 +msgid "Baden-Wuerttemberg" +msgstr "Baden-Württemberg" -#: utils/dates.py:6 -msgid "Wednesday" -msgstr "Szerda" +#: contrib/localflavor/de/de_states.py:6 +msgid "Bavaria" +msgstr "Bajorország" -#: utils/dates.py:6 -msgid "Thursday" -msgstr "Csütörtök" +#: contrib/localflavor/de/de_states.py:7 +msgid "Berlin" +msgstr "Berlin" -#: utils/dates.py:6 -msgid "Friday" -msgstr "Péntek" +#: contrib/localflavor/de/de_states.py:8 +msgid "Brandenburg" +msgstr "Brandenburg" -#: utils/dates.py:7 -msgid "Saturday" -msgstr "Szombat" +#: contrib/localflavor/de/de_states.py:9 +msgid "Bremen" +msgstr "Bréma" -#: utils/dates.py:7 -msgid "Sunday" -msgstr "Vasárnap" +#: contrib/localflavor/de/de_states.py:10 +msgid "Hamburg" +msgstr "Hamburg" -#: utils/dates.py:14 -msgid "January" -msgstr "Január" +#: contrib/localflavor/de/de_states.py:11 +msgid "Hessen" +msgstr "Hessen" -#: utils/dates.py:14 -msgid "February" -msgstr "Február" +#: contrib/localflavor/de/de_states.py:12 +msgid "Mecklenburg-Western Pomerania" +msgstr "Mecklenburg-Nyugat-Pomeránia" -#: utils/dates.py:14 utils/dates.py:27 -msgid "March" -msgstr "Március" +#: contrib/localflavor/de/de_states.py:13 +msgid "Lower Saxony" +msgstr "Alsó-Szászország" -#: utils/dates.py:14 utils/dates.py:27 -msgid "April" -msgstr "Április" +#: contrib/localflavor/de/de_states.py:14 +msgid "North Rhine-Westphalia" +msgstr "Észak-Rajna-Vesztfália" -#: utils/dates.py:14 utils/dates.py:27 -msgid "May" -msgstr "Május" +#: contrib/localflavor/de/de_states.py:15 +msgid "Rhineland-Palatinate" +msgstr "Rhineland-Palatinate" -#: utils/dates.py:14 utils/dates.py:27 -msgid "June" -msgstr "Június" +#: contrib/localflavor/de/de_states.py:16 +msgid "Saarland" +msgstr "Szárföld" -#: utils/dates.py:15 utils/dates.py:27 -msgid "July" -msgstr "Július" +#: contrib/localflavor/de/de_states.py:17 +msgid "Saxony" +msgstr "Szászország" -#: utils/dates.py:15 -msgid "August" -msgstr "Augusztus" +#: contrib/localflavor/de/de_states.py:18 +msgid "Saxony-Anhalt" +msgstr "Szász-Anhalt" -#: utils/dates.py:15 -msgid "September" -msgstr "Szeptember" +#: contrib/localflavor/de/de_states.py:19 +msgid "Schleswig-Holstein" +msgstr "Schleswig-Holstein" -#: utils/dates.py:15 -msgid "October" -msgstr "Október" +#: contrib/localflavor/de/de_states.py:20 +msgid "Thuringia" +msgstr "Türingia" -#: utils/dates.py:15 -msgid "November" -msgstr "November" +#: contrib/localflavor/de/forms.py:60 +msgid "" +"Enter a valid German identity card number in XXXXXXXXXXX-XXXXXXX-XXXXXXX-X " +"format." +msgstr "" +"Írjon be egy érvényes német személyazonosító számot \"XXXXXXXXXXX-XXXXXXX-" +"XXXXXXX-X\" alakban." -#: utils/dates.py:16 -msgid "December" -msgstr "December" +#: contrib/localflavor/jp/jp_prefectures.py:4 +msgid "Hokkaido" +msgstr "Hokkaido" -#: utils/dates.py:19 -#, fuzzy -msgid "jan" -msgstr "és" +#: contrib/localflavor/jp/jp_prefectures.py:5 +msgid "Aomori" +msgstr "Aomori" -#: utils/dates.py:19 -msgid "feb" -msgstr "" +#: contrib/localflavor/jp/jp_prefectures.py:6 +msgid "Iwate" +msgstr "Iwate" -#: utils/dates.py:19 -msgid "mar" -msgstr "" +#: contrib/localflavor/jp/jp_prefectures.py:7 +msgid "Miyagi" +msgstr "Miyagi" -#: utils/dates.py:19 -msgid "apr" -msgstr "" +#: contrib/localflavor/jp/jp_prefectures.py:8 +msgid "Akita" +msgstr "Akita" -#: utils/dates.py:19 -#, fuzzy -msgid "may" -msgstr "nap" +#: contrib/localflavor/jp/jp_prefectures.py:9 +msgid "Yamagata" +msgstr "Yamagata" -#: utils/dates.py:19 -msgid "jun" -msgstr "" +#: contrib/localflavor/jp/jp_prefectures.py:10 +msgid "Fukushima" +msgstr "Fukushima" -#: utils/dates.py:20 -msgid "jul" -msgstr "" +#: contrib/localflavor/jp/jp_prefectures.py:11 +msgid "Ibaraki" +msgstr "Ibaraki" -#: utils/dates.py:20 -msgid "aug" -msgstr "" +#: contrib/localflavor/jp/jp_prefectures.py:12 +msgid "Tochigi" +msgstr "Tochigi" -#: utils/dates.py:20 -msgid "sep" -msgstr "" +#: contrib/localflavor/jp/jp_prefectures.py:13 +msgid "Gunma" +msgstr "Gunma" -#: utils/dates.py:20 -msgid "oct" -msgstr "" +#: contrib/localflavor/jp/jp_prefectures.py:14 +msgid "Saitama" +msgstr "Saitama" -#: utils/dates.py:20 -msgid "nov" -msgstr "" +#: contrib/localflavor/jp/jp_prefectures.py:15 +msgid "Chiba" +msgstr "Chiba" -#: utils/dates.py:20 -msgid "dec" -msgstr "" +#: contrib/localflavor/jp/jp_prefectures.py:16 +msgid "Tokyo" +msgstr "Tókió" -#: utils/dates.py:27 -msgid "Jan." -msgstr "Jan." +#: contrib/localflavor/jp/jp_prefectures.py:17 +msgid "Kanagawa" +msgstr "Kanagawa" -#: utils/dates.py:27 -msgid "Feb." -msgstr "Feb." +#: contrib/localflavor/jp/jp_prefectures.py:18 +msgid "Yamanashi" +msgstr "Yamanashi" -#: utils/dates.py:28 -msgid "Aug." -msgstr "Aug." +#: contrib/localflavor/jp/jp_prefectures.py:19 +msgid "Nagano" +msgstr "Nagano" -#: utils/dates.py:28 -msgid "Sept." -msgstr "Szept." +#: contrib/localflavor/jp/jp_prefectures.py:20 +msgid "Niigata" +msgstr "Niigata" -#: utils/dates.py:28 -msgid "Oct." -msgstr "Okt." +#: contrib/localflavor/jp/jp_prefectures.py:21 +msgid "Toyama" +msgstr "Toyama" -#: utils/dates.py:28 -msgid "Nov." -msgstr "Nov." +#: contrib/localflavor/jp/jp_prefectures.py:22 +msgid "Ishikawa" +msgstr "Ishikawa" -#: utils/dates.py:28 -msgid "Dec." -msgstr "Dec." +#: contrib/localflavor/jp/jp_prefectures.py:23 +msgid "Fukui" +msgstr "Fukui" -#: utils/timesince.py:12 -msgid "year" -msgid_plural "years" -msgstr[0] "év" -msgstr[1] "évek" +#: contrib/localflavor/jp/jp_prefectures.py:24 +msgid "Gifu" +msgstr "Gifu" -#: utils/timesince.py:13 -msgid "month" -msgid_plural "months" -msgstr[0] "hónap" -msgstr[1] "hónapok" +#: contrib/localflavor/jp/jp_prefectures.py:25 +msgid "Shizuoka" +msgstr "Shizuoka" -#: utils/timesince.py:14 -msgid "week" -msgid_plural "weeks" -msgstr[0] "" -msgstr[1] "" +#: contrib/localflavor/jp/jp_prefectures.py:26 +msgid "Aichi" +msgstr "Aichi" -#: utils/timesince.py:15 -msgid "day" -msgid_plural "days" -msgstr[0] "nap" -msgstr[1] "napok" +#: contrib/localflavor/jp/jp_prefectures.py:27 +msgid "Mie" +msgstr "Mie" -#: utils/timesince.py:16 -msgid "hour" -msgid_plural "hours" -msgstr[0] "óra" -msgstr[1] "órák" +#: contrib/localflavor/jp/jp_prefectures.py:28 +msgid "Shiga" +msgstr "Shiga" -#: utils/timesince.py:17 -msgid "minute" -msgid_plural "minutes" -msgstr[0] "perc" -msgstr[1] "percek" +#: contrib/localflavor/jp/jp_prefectures.py:29 +msgid "Kyoto" +msgstr "Kiotó" -#: conf/global_settings.py:37 -msgid "Bengali" -msgstr "Bengáli" +#: contrib/localflavor/jp/jp_prefectures.py:30 +msgid "Osaka" +msgstr "Oszaka" -#: conf/global_settings.py:38 -msgid "Czech" -msgstr "Cseh" +#: contrib/localflavor/jp/jp_prefectures.py:31 +msgid "Hyogo" +msgstr "Hyogo" -#: conf/global_settings.py:39 -msgid "Welsh" -msgstr "Walesi" +#: contrib/localflavor/jp/jp_prefectures.py:32 +msgid "Nara" +msgstr "Nara" -#: conf/global_settings.py:40 -msgid "Danish" -msgstr "Dán" +#: contrib/localflavor/jp/jp_prefectures.py:33 +msgid "Wakayama" +msgstr "Wakayama" -#: conf/global_settings.py:41 -msgid "German" -msgstr "Német" +#: contrib/localflavor/jp/jp_prefectures.py:34 +msgid "Tottori" +msgstr "Tottori" -#: conf/global_settings.py:42 -msgid "Greek" -msgstr "" +#: contrib/localflavor/jp/jp_prefectures.py:35 +msgid "Shimane" +msgstr "Shimane" -#: conf/global_settings.py:43 -msgid "English" -msgstr "Angol" +#: contrib/localflavor/jp/jp_prefectures.py:36 +msgid "Okayama" +msgstr "Okayama" -#: conf/global_settings.py:44 -msgid "Spanish" -msgstr "Spanyol" +#: contrib/localflavor/jp/jp_prefectures.py:37 +msgid "Hiroshima" +msgstr "Hiroshima" -#: conf/global_settings.py:45 -msgid "French" -msgstr "Francia" +#: contrib/localflavor/jp/jp_prefectures.py:38 +msgid "Yamaguchi" +msgstr "Yamaguchi" -#: conf/global_settings.py:46 -msgid "Galician" -msgstr "Gall" +#: contrib/localflavor/jp/jp_prefectures.py:39 +msgid "Tokushima" +msgstr "Tokushima" -#: conf/global_settings.py:47 -msgid "Hungarian" -msgstr "" +#: contrib/localflavor/jp/jp_prefectures.py:40 +msgid "Kagawa" +msgstr "Kagawa" -#: conf/global_settings.py:48 -msgid "Hebrew" -msgstr "" +#: contrib/localflavor/jp/jp_prefectures.py:41 +msgid "Ehime" +msgstr "Ehime" -#: conf/global_settings.py:49 -msgid "Icelandic" -msgstr "Izlandi" +#: contrib/localflavor/jp/jp_prefectures.py:42 +msgid "Kochi" +msgstr "Kochi" -#: conf/global_settings.py:50 -msgid "Italian" -msgstr "Olasz" +#: contrib/localflavor/jp/jp_prefectures.py:43 +msgid "Fukuoka" +msgstr "Fukuoka" -#: conf/global_settings.py:51 -msgid "Japanese" -msgstr "Japán" +#: contrib/localflavor/jp/jp_prefectures.py:44 +msgid "Saga" +msgstr "Saga" -#: conf/global_settings.py:52 -msgid "Dutch" -msgstr "Holland" +#: contrib/localflavor/jp/jp_prefectures.py:45 +msgid "Nagasaki" +msgstr "Nagaszaki" -#: conf/global_settings.py:53 -msgid "Norwegian" -msgstr "Norvég" +#: contrib/localflavor/jp/jp_prefectures.py:46 +msgid "Kumamoto" +msgstr "Kumamoto" -#: conf/global_settings.py:54 -msgid "Brazilian" -msgstr "Brazil" +#: contrib/localflavor/jp/jp_prefectures.py:47 +msgid "Oita" +msgstr "Oita" -#: conf/global_settings.py:55 -msgid "Romanian" -msgstr "Román" +#: contrib/localflavor/jp/jp_prefectures.py:48 +msgid "Miyazaki" +msgstr "Miyazaki" -#: conf/global_settings.py:56 -msgid "Russian" -msgstr "Orosz" +#: contrib/localflavor/jp/jp_prefectures.py:49 +msgid "Kagoshima" +msgstr "Kagoshima" -#: conf/global_settings.py:57 -msgid "Slovak" -msgstr "Szlovák" +#: contrib/localflavor/jp/jp_prefectures.py:50 +msgid "Okinawa" +msgstr "Okinawa" -#: conf/global_settings.py:58 -#, fuzzy -msgid "Slovenian" -msgstr "Szlovák" +#: contrib/localflavor/jp/forms.py:21 +msgid "Enter a postal code in the format XXXXXXX or XXX-XXXX." +msgstr "Írjon be egy irányítószámot \"XXXXXXX\" vagy \"XXX-XXXX\" alakban." -#: conf/global_settings.py:59 -msgid "Serbian" -msgstr "Szerb" +#: contrib/localflavor/ch/ch_states.py:5 +msgid "Aargau" +msgstr "Aargau" -#: conf/global_settings.py:60 -msgid "Swedish" -msgstr "Svéd" +#: contrib/localflavor/ch/ch_states.py:6 +msgid "Appenzell Innerrhoden" +msgstr "Appenzell Innerrhoden" -#: conf/global_settings.py:61 -#, fuzzy -msgid "Ukrainian" -msgstr "Brazil" +#: contrib/localflavor/ch/ch_states.py:7 +msgid "Appenzell Ausserrhoden" +msgstr "Appenzell Ausserrhoden" -#: conf/global_settings.py:62 -msgid "Simplified Chinese" -msgstr "Egyszerű kínai" +#: contrib/localflavor/ch/ch_states.py:8 +msgid "Basel-Stadt" +msgstr "Bázel-város" -#: conf/global_settings.py:63 -msgid "Traditional Chinese" -msgstr "Hagyományos kínai" +#: contrib/localflavor/ch/ch_states.py:9 +msgid "Basel-Land" +msgstr "Bázel-vidék" -#: core/validators.py:60 -msgid "This value must contain only letters, numbers and underscores." -msgstr "Az érték csak betűket, számokat és alulvonást tartalmazhat." +#: contrib/localflavor/ch/ch_states.py:10 +msgid "Berne" +msgstr "Berne" -#: core/validators.py:64 -#, fuzzy -msgid "" -"This value must contain only letters, numbers, underscores, dashes or " -"slashes." -msgstr "Az érték csak betűket, számokat, alulvonást és perjelet tartalmazhat." +#: contrib/localflavor/ch/ch_states.py:11 +msgid "Fribourg" +msgstr "Fribourg" -#: core/validators.py:72 -msgid "Uppercase letters are not allowed here." -msgstr "Nagybetűk itt nem megengedettek." +#: contrib/localflavor/ch/ch_states.py:12 +msgid "Geneva" +msgstr "Genf" -#: core/validators.py:76 -msgid "Lowercase letters are not allowed here." -msgstr "Kisbetűk itt nem megengedettek." +#: contrib/localflavor/ch/ch_states.py:13 +msgid "Glarus" +msgstr "Glarus" -#: core/validators.py:83 -msgid "Enter only digits separated by commas." -msgstr "Csak számokat adj meg, vesszőkkel elválasztva." +#: contrib/localflavor/ch/ch_states.py:14 +msgid "Graubuenden" +msgstr "Graubuenden" -#: core/validators.py:95 -msgid "Enter valid e-mail addresses separated by commas." -msgstr "Érvényes e-mail címeket adja meg, vesszőkkel elválasztva." +#: contrib/localflavor/ch/ch_states.py:15 +msgid "Jura" +msgstr "Jura" -#: core/validators.py:99 -msgid "Please enter a valid IP address." -msgstr "Írj be egy érvényes IP címet." +#: contrib/localflavor/ch/ch_states.py:16 +msgid "Lucerne" +msgstr "Lucerne" -#: core/validators.py:103 -msgid "Empty values are not allowed here." -msgstr "Üres érték itt nem megengedett." +#: contrib/localflavor/ch/ch_states.py:17 +msgid "Neuchatel" +msgstr "Neuchatel" -#: core/validators.py:107 -msgid "Non-numeric characters aren't allowed here." -msgstr "Nem szám karakterek itt nem megengedettek." +#: contrib/localflavor/ch/ch_states.py:18 +msgid "Nidwalden" +msgstr "Nidwalden" -#: core/validators.py:111 -msgid "This value can't be comprised solely of digits." -msgstr "Ez az érték nem tartalmazhat kizárólag számokat." +#: contrib/localflavor/ch/ch_states.py:19 +msgid "Obwalden" +msgstr "Obwalden" -#: core/validators.py:116 -msgid "Enter a whole number." -msgstr "Adj meg egy egész számot." +#: contrib/localflavor/ch/ch_states.py:20 +msgid "Schaffhausen" +msgstr "Schaffhausen" -#: core/validators.py:120 -msgid "Only alphabetical characters are allowed here." -msgstr "Itt csak betűk megengedettek." +#: contrib/localflavor/ch/ch_states.py:21 +msgid "Schwyz" +msgstr "Schwyz" -#: core/validators.py:124 -msgid "Enter a valid date in YYYY-MM-DD format." -msgstr "Írj be egy érvényes dátumot 'ÉÉÉÉ-HH-NN' alakban." +#: contrib/localflavor/ch/ch_states.py:22 +msgid "Solothurn" +msgstr "Solothurn" -#: core/validators.py:128 -msgid "Enter a valid time in HH:MM format." -msgstr "Írj be egy érvényes időt 'ÓÓ:PP' alakban." +#: contrib/localflavor/ch/ch_states.py:23 +msgid "St. Gallen" +msgstr "St. Gallen" -#: core/validators.py:132 db/models/fields/__init__.py:468 -msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format." -msgstr "Írj be egy érvényes dátumot/időt 'ÉÉÉÉ-HH-NN ÓÓ-PP' alakban." +#: contrib/localflavor/ch/ch_states.py:24 +msgid "Thurgau" +msgstr "Thurgau" -#: core/validators.py:136 -msgid "Enter a valid e-mail address." -msgstr "Írj be egy érvényes e-mail címet." +#: contrib/localflavor/ch/ch_states.py:25 +msgid "Ticino" +msgstr "Ticino" -#: core/validators.py:148 -msgid "" -"Upload a valid image. The file you uploaded was either not an image or a " -"corrupted image." -msgstr "" -"Tölts fel egy érvényes képfájlt. A feltöltött fájl vagy nem kép volt vagy " -"megsérült." +#: contrib/localflavor/ch/ch_states.py:26 +msgid "Uri" +msgstr "Uri" -#: core/validators.py:155 -#, python-format -msgid "The URL %s does not point to a valid image." -msgstr "A(z) %s URL nem érvényes képfájlra mutat." +#: contrib/localflavor/ch/ch_states.py:27 +msgid "Valais" +msgstr "Valais" -#: core/validators.py:159 -#, python-format -msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid." -msgstr "" -"A telefonszámoknak 'XXX-XXX-XXXX' formátumúnak kell lennie. \"%s\" " -"érvénytelen." +#: contrib/localflavor/ch/ch_states.py:28 +msgid "Vaud" +msgstr "Vaud" -#: core/validators.py:167 -#, python-format -msgid "The URL %s does not point to a valid QuickTime video." -msgstr "A(z) %s URL nem érvényes QuickTime videóra mutat." +#: contrib/localflavor/ch/ch_states.py:29 +msgid "Zug" +msgstr "Zug" -#: core/validators.py:171 -msgid "A valid URL is required." -msgstr "Érvényes URL szükséges." +#: contrib/localflavor/ch/ch_states.py:30 +msgid "Zurich" +msgstr "Zürich" -#: core/validators.py:185 -#, python-format +#: contrib/localflavor/ch/forms.py:18 contrib/localflavor/no/forms.py:14 +msgid "Enter a zip code in the format XXXX." +msgstr "Írjon be egy irányítószámot 'XXXX' alakban." + +#: contrib/localflavor/ch/forms.py:90 msgid "" -"Valid HTML is required. Specific errors are:\n" -"%s" +"Enter a valid Swiss identity or passport card number in X1234567<0 or " +"1234567890 format." msgstr "" -"Érvényes HTML kell. A hiba:\n" -"%s" +"Írjon be egy érvényes svájci személyazonosító vagy útlevél számot " +"\"X1234567<0\" vagy \"1234567890\" alakban." -#: core/validators.py:192 -#, python-format -msgid "Badly formed XML: %s" -msgstr "Rosszul formázott XML: %s" +#: contrib/localflavor/is_/forms.py:17 +msgid "Enter a valid Icelandic identification number. The format is XXXXXX-XXXX." +msgstr "" +"Írjon be egy érvényes izlandi személyazonosító számot \"XXXXXX-XXXX\" " +"alakban." -#: core/validators.py:202 -#, python-format -msgid "Invalid URL: %s" -msgstr "Érvénytelen URL: %s" +#: contrib/localflavor/is_/forms.py:31 +msgid "The Icelandic identification number is not valid." +msgstr "Az izlandi személyazonosító szám érvénytelen." -#: core/validators.py:206 core/validators.py:208 -#, python-format -msgid "The URL %s is a broken link." -msgstr "A(z) %s URL egy rossz link." +#: contrib/localflavor/it/forms.py:16 +msgid "Enter a valid zip code." +msgstr "Adjon meg egy érvényes irányítószámot." -#: core/validators.py:214 -msgid "Enter a valid U.S. state abbreviation." -msgstr "Írj be egy érvényes USA állam rövidítést." +#: contrib/localflavor/it/forms.py:41 +msgid "Enter a valid Social Security number." +msgstr "Adjon meg egy érvényes társadalombiztosítási számot." -#: core/validators.py:229 -#, python-format -msgid "Watch your mouth! The word %s is not allowed here." -msgid_plural "Watch your mouth! The words %s are not allowed here." -msgstr[0] "Vigyázz a szádra! Az ilyen szavak (%s) itt nem megengedettek." -msgstr[1] "Vigyázz a szádra! Az ilyen szavak (%s) itt nem megengedettek." +#: contrib/localflavor/it/forms.py:68 +msgid "Enter a valid VAT number." +msgstr "Adjon meg egy érvényes ÁFA számot." -#: core/validators.py:236 -#, python-format -msgid "This field must match the '%s' field." -msgstr "A mezőnek egyeznie kell a(z) %s mezővel." +#: contrib/localflavor/no/forms.py:35 +msgid "Enter a valid Norwegian social security number." +msgstr "Írjon be egy érvényes norvég társadalombiztosítási számot." -#: core/validators.py:255 -msgid "Please enter something for at least one field." -msgstr "Írj be valamit legalább egy mezőbe." +#: contrib/localflavor/sk/sk_regions.py:8 +msgid "Banska Bystrica region" +msgstr "Besztercebánya régió" -#: core/validators.py:264 core/validators.py:275 -msgid "Please enter both fields or leave them both empty." -msgstr "Töltsd ki mindkét mezőt vagy hagyd üresen mindkettőt." +#: contrib/localflavor/sk/sk_regions.py:9 +msgid "Bratislava region" +msgstr "Pozsony régió" -#: core/validators.py:282 -#, python-format -msgid "This field must be given if %(field)s is %(value)s" -msgstr "Ezt a mezőt meg kell adni, ha %(field)s értéke %(value)s" +#: contrib/localflavor/sk/sk_regions.py:10 +msgid "Kosice region" +msgstr "Kassa régió" -#: core/validators.py:294 -#, python-format -msgid "This field must be given if %(field)s is not %(value)s" -msgstr "Ezt a mezőt meg kell adni, ha %(field)s értéke nem %(value)s" +#: contrib/localflavor/sk/sk_regions.py:11 +msgid "Nitra region" +msgstr "Nyitra régió" -#: core/validators.py:313 -msgid "Duplicate values are not allowed." -msgstr "Ugyanazok az értékek nem megengedettek." +#: contrib/localflavor/sk/sk_regions.py:12 +msgid "Presov region" +msgstr "Presov régió" -#: core/validators.py:336 -#, python-format -msgid "This value must be a power of %s." -msgstr "Az értéknek %s hatványának kell lennie." +#: contrib/localflavor/sk/sk_regions.py:13 +msgid "Trencin region" +msgstr "Trencsén régió" -#: core/validators.py:347 -msgid "Please enter a valid decimal number." -msgstr "Írj be egy érvényes tizes számrendszerű számot." +#: contrib/localflavor/sk/sk_regions.py:14 +msgid "Trnava region" +msgstr "Trnava régió" -#: core/validators.py:349 -#, python-format -msgid "Please enter a valid decimal number with at most %s total digit." -msgid_plural "" -"Please enter a valid decimal number with at most %s total digits." -msgstr[0] "Írj be egy legalább %s jegyű érvényes tizes számrendszerű számot." -msgstr[1] "Írj be egy legalább %s jegyű érvényes tizes számrendszerű számot." +#: contrib/localflavor/sk/sk_regions.py:15 +msgid "Zilina region" +msgstr "Zsolna régió" -#: core/validators.py:352 -#, python-format -msgid "Please enter a valid decimal number with at most %s decimal place." -msgid_plural "" -"Please enter a valid decimal number with at most %s decimal places." -msgstr[0] "" -"Írj be egy érvényes tizes számrendszerű számot, legfeljebb %s tizedessel." -msgstr[1] "" -"Írj be egy érvényes tizes számrendszerű számot, legfeljebb %s tizedessel." +#: contrib/localflavor/sk/sk_districts.py:8 +msgid "Banska Bystrica" +msgstr "Besztercebánya" -#: core/validators.py:362 -#, python-format -msgid "Make sure your uploaded file is at least %s bytes big." -msgstr "A feltöltött fájlod legalább %s bájt méretű legyen." +#: contrib/localflavor/sk/sk_districts.py:9 +msgid "Banska Stiavnica" +msgstr "Banska Stiavnica" -#: core/validators.py:363 -#, python-format -msgid "Make sure your uploaded file is at most %s bytes big." -msgstr "A feltöltött fájlod legfeljebb %s bájt méretű legyen." +#: contrib/localflavor/sk/sk_districts.py:10 +msgid "Bardejov" +msgstr "Bardejov" -#: core/validators.py:376 -msgid "The format for this field is wrong." -msgstr "Ennek a mezőnek a formátuma rossz." +#: contrib/localflavor/sk/sk_districts.py:11 +msgid "Banovce nad Bebravou" +msgstr "Banovce nad Bebravou" -#: core/validators.py:391 -msgid "This field is invalid." -msgstr "A mező érvénytelen." +#: contrib/localflavor/sk/sk_districts.py:12 +msgid "Brezno" +msgstr "Brezno" -#: core/validators.py:426 -#, python-format -msgid "Could not retrieve anything from %s." -msgstr "Nem lehet semmit kinyerni %s -ból." +#: contrib/localflavor/sk/sk_districts.py:13 +msgid "Bratislava I" +msgstr "Pozsony I" -#: core/validators.py:429 -#, python-format -msgid "" -"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'." -msgstr "" -"A(z) %(url)s URL érvénytelen Content-Type fejlécet adott vissza '%" -"(contenttype)s'." +#: contrib/localflavor/sk/sk_districts.py:14 +msgid "Bratislava II" +msgstr "Pozsony II" -#: core/validators.py:462 -#, python-format -msgid "" -"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with " -"\"%(start)s\".)" -msgstr "" -"Zárd le a nyitott %(tag)s címkét a %(line)s sorban. (A sor kezdete: \"%" -"(start)s\".)" +#: contrib/localflavor/sk/sk_districts.py:15 +msgid "Bratislava III" +msgstr "Pozsony III" -#: core/validators.py:466 -#, python-format -msgid "" -"Some text starting on line %(line)s is not allowed in that context. (Line " -"starts with \"%(start)s\".)" -msgstr "" -"Valamely szöveg a(z) %(line)s sorban nem megengedett ebben a környezetben. " -"(A sor kezdete: \"%(start)s\".)" +#: contrib/localflavor/sk/sk_districts.py:16 +msgid "Bratislava IV" +msgstr "Pozsony IV" -#: core/validators.py:471 -#, python-format -msgid "" -"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%" -"(start)s\".)" -msgstr "" -"\"%(attr)s\" a(z) %(line)s sorban érvénytelen tulajdonság. (A sor kezdete: " -"\"%(start)s\".)" +#: contrib/localflavor/sk/sk_districts.py:17 +msgid "Bratislava V" +msgstr "Pozsony V" -#: core/validators.py:476 -#, python-format -msgid "" -"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%" -"(start)s\".)" -msgstr "" -"\"<%(tag)s>\" a(z) %(line)s sorban érvénytelen címke. (A sor kezdete: \"%" -"(start)s\".)" +#: contrib/localflavor/sk/sk_districts.py:18 +msgid "Bytca" +msgstr "Bytca" -#: core/validators.py:480 -#, python-format +#: contrib/localflavor/sk/sk_districts.py:19 +msgid "Cadca" +msgstr "Cadca" + +#: contrib/localflavor/sk/sk_districts.py:20 +msgid "Detva" +msgstr "Detva" + +#: contrib/localflavor/sk/sk_districts.py:21 +msgid "Dolny Kubin" +msgstr "Dolny Kubin" + +#: contrib/localflavor/sk/sk_districts.py:22 +msgid "Dunajska Streda" +msgstr "Dunaszerdahely" + +#: contrib/localflavor/sk/sk_districts.py:23 +msgid "Galanta" +msgstr "Galánta" + +#: contrib/localflavor/sk/sk_districts.py:24 +msgid "Gelnica" +msgstr "Gelnica" + +#: contrib/localflavor/sk/sk_districts.py:25 +msgid "Hlohovec" +msgstr "Hlohovec" + +#: contrib/localflavor/sk/sk_districts.py:26 +msgid "Humenne" +msgstr "Humenne" + +#: contrib/localflavor/sk/sk_districts.py:27 +msgid "Ilava" +msgstr "Ilava" + +#: contrib/localflavor/sk/sk_districts.py:28 +msgid "Kezmarok" +msgstr "Késmárk" + +#: contrib/localflavor/sk/sk_districts.py:29 +msgid "Komarno" +msgstr "Komárom" + +#: contrib/localflavor/sk/sk_districts.py:30 +msgid "Kosice I" +msgstr "Kassa I" + +#: contrib/localflavor/sk/sk_districts.py:31 +msgid "Kosice II" +msgstr "Kassa II" + +#: contrib/localflavor/sk/sk_districts.py:32 +msgid "Kosice III" +msgstr "Kassa III" + +#: contrib/localflavor/sk/sk_districts.py:33 +msgid "Kosice IV" +msgstr "Kassa IV" + +#: contrib/localflavor/sk/sk_districts.py:34 +msgid "Kosice - okolie" +msgstr "Kosice - okolie" + +#: contrib/localflavor/sk/sk_districts.py:35 +msgid "Krupina" +msgstr "Krupina" + +#: contrib/localflavor/sk/sk_districts.py:36 +msgid "Kysucke Nove Mesto" +msgstr "Kysucke Nove Mesto" + +#: contrib/localflavor/sk/sk_districts.py:37 +msgid "Levice" +msgstr "Levice" + +#: contrib/localflavor/sk/sk_districts.py:38 +msgid "Levoca" +msgstr "Levoca" + +#: contrib/localflavor/sk/sk_districts.py:39 +msgid "Liptovsky Mikulas" +msgstr "Liptovsky Mikulas" + +#: contrib/localflavor/sk/sk_districts.py:40 +msgid "Lucenec" +msgstr "Lucenec" + +#: contrib/localflavor/sk/sk_districts.py:41 +msgid "Malacky" +msgstr "Malacky" + +#: contrib/localflavor/sk/sk_districts.py:42 +msgid "Martin" +msgstr "Martin" + +#: contrib/localflavor/sk/sk_districts.py:43 +msgid "Medzilaborce" +msgstr "Medzilaborce" + +#: contrib/localflavor/sk/sk_districts.py:44 +msgid "Michalovce" +msgstr "Michalovce" + +#: contrib/localflavor/sk/sk_districts.py:45 +msgid "Myjava" +msgstr "Myjava" + +#: contrib/localflavor/sk/sk_districts.py:46 +msgid "Namestovo" +msgstr "Namestovo" + +#: contrib/localflavor/sk/sk_districts.py:47 +msgid "Nitra" +msgstr "Nyitra" + +#: contrib/localflavor/sk/sk_districts.py:48 +msgid "Nove Mesto nad Vahom" +msgstr "Nove Mesto nad Vahom" + +#: contrib/localflavor/sk/sk_districts.py:49 +msgid "Nove Zamky" +msgstr "Nove Zamky" + +#: contrib/localflavor/sk/sk_districts.py:50 +msgid "Partizanske" +msgstr "Partizanske" + +#: contrib/localflavor/sk/sk_districts.py:51 +msgid "Pezinok" +msgstr "Pezinok" + +#: contrib/localflavor/sk/sk_districts.py:52 +msgid "Piestany" +msgstr "Piestany" + +#: contrib/localflavor/sk/sk_districts.py:53 +msgid "Poltar" +msgstr "Poltar" + +#: contrib/localflavor/sk/sk_districts.py:54 +msgid "Poprad" +msgstr "Poprád" + +#: contrib/localflavor/sk/sk_districts.py:55 +msgid "Povazska Bystrica" +msgstr "Povazska Bystrica" + +#: contrib/localflavor/sk/sk_districts.py:56 +msgid "Presov" +msgstr "Presov" + +#: contrib/localflavor/sk/sk_districts.py:57 +msgid "Prievidza" +msgstr "Prievidza" + +#: contrib/localflavor/sk/sk_districts.py:58 +msgid "Puchov" +msgstr "Puchov" + +#: contrib/localflavor/sk/sk_districts.py:59 +msgid "Revuca" +msgstr "Revuca" + +#: contrib/localflavor/sk/sk_districts.py:60 +msgid "Rimavska Sobota" +msgstr "Rimaszombat" + +#: contrib/localflavor/sk/sk_districts.py:61 +msgid "Roznava" +msgstr "Rozsnyó" + +#: contrib/localflavor/sk/sk_districts.py:62 +msgid "Ruzomberok" +msgstr "Rózsahegy" + +#: contrib/localflavor/sk/sk_districts.py:63 +msgid "Sabinov" +msgstr "Sabinov" + +#: contrib/localflavor/sk/sk_districts.py:64 +msgid "Senec" +msgstr "Senec" + +#: contrib/localflavor/sk/sk_districts.py:65 +msgid "Senica" +msgstr "Senica" + +#: contrib/localflavor/sk/sk_districts.py:66 +msgid "Skalica" +msgstr "Skalica" + +#: contrib/localflavor/sk/sk_districts.py:67 +msgid "Snina" +msgstr "Snina" + +#: contrib/localflavor/sk/sk_districts.py:68 +msgid "Sobrance" +msgstr "Sobrance" + +#: contrib/localflavor/sk/sk_districts.py:69 +msgid "Spisska Nova Ves" +msgstr "Igló" + +#: contrib/localflavor/sk/sk_districts.py:70 +msgid "Stara Lubovna" +msgstr "Stara Lubovna" + +#: contrib/localflavor/sk/sk_districts.py:71 +msgid "Stropkov" +msgstr "Stropkov" + +#: contrib/localflavor/sk/sk_districts.py:72 +msgid "Svidnik" +msgstr "Svidnik" + +#: contrib/localflavor/sk/sk_districts.py:73 +msgid "Sala" +msgstr "Sellye" + +#: contrib/localflavor/sk/sk_districts.py:74 +msgid "Topolcany" +msgstr "Topolcany" + +#: contrib/localflavor/sk/sk_districts.py:75 +msgid "Trebisov" +msgstr "Trebisov" + +#: contrib/localflavor/sk/sk_districts.py:76 +msgid "Trencin" +msgstr "Trencsén" + +#: contrib/localflavor/sk/sk_districts.py:77 +msgid "Trnava" +msgstr "Trnava" + +#: contrib/localflavor/sk/sk_districts.py:78 +msgid "Turcianske Teplice" +msgstr "Turcianske Teplice" + +#: contrib/localflavor/sk/sk_districts.py:79 +msgid "Tvrdosin" +msgstr "Tvrdosin" + +#: contrib/localflavor/sk/sk_districts.py:80 +msgid "Velky Krtis" +msgstr "Velky Krtis" + +#: contrib/localflavor/sk/sk_districts.py:81 +msgid "Vranov nad Toplou" +msgstr "Vranov nad Toplou" + +#: contrib/localflavor/sk/sk_districts.py:82 +msgid "Zlate Moravce" +msgstr "Zlate Moravce" + +#: contrib/localflavor/sk/sk_districts.py:83 +msgid "Zvolen" +msgstr "Zvolen" + +#: contrib/localflavor/sk/sk_districts.py:84 +msgid "Zarnovica" +msgstr "Zarnovica" + +#: contrib/localflavor/sk/sk_districts.py:85 +msgid "Ziar nad Hronom" +msgstr "Ziar nad Hronom" + +#: contrib/localflavor/sk/sk_districts.py:86 +msgid "Zilina" +msgstr "Zsolna" + +#: contrib/localflavor/sk/forms.py:32 +msgid "Enter a postal code in the format XXXXX or XXX XX." +msgstr "Írjon be egy irányítószámot \"XXXXX\" vagy \"XXX XX\" alakban." + +#: contrib/localflavor/cl/forms.py:32 +msgid "Enter valid a Chilean RUT. The format is XX.XXX.XXX-X." +msgstr "Írjon be egy érvényes chilei RUT-ot \"XX.XXX.XXX-X\" alakban." + +#: contrib/localflavor/cl/forms.py:37 +msgid "Enter valid a Chilean RUT" +msgstr "Írjon be egy érvényes chilei RUT-ot" + +#: contrib/localflavor/fi/forms.py:40 contrib/localflavor/fi/forms.py:45 +msgid "Enter a valid Finnish social security number." +msgstr "Adjon meg egy érvényes finn társadalombiztosítási számot." + +#: contrib/localflavor/in_/forms.py:16 +msgid "Enter a zip code in the format XXXXXXX." +msgstr "Írjon be egy irányítószámot \"XXXXXXX\" alakban." + +#: contrib/localflavor/pl/pl_voivodeships.py:8 +msgid "Lower Silesia" +msgstr "Alsó-Szilézia" + +#: contrib/localflavor/pl/pl_voivodeships.py:9 +msgid "Kuyavia-Pomerania" +msgstr "Kuyavia-Pomerania" + +#: contrib/localflavor/pl/pl_voivodeships.py:10 +msgid "Lublin" +msgstr "Lublin" + +#: contrib/localflavor/pl/pl_voivodeships.py:11 +msgid "Lubusz" +msgstr "Lubusz" + +#: contrib/localflavor/pl/pl_voivodeships.py:12 +msgid "Lodz" +msgstr "Lodz" + +#: contrib/localflavor/pl/pl_voivodeships.py:13 +msgid "Lesser Poland" +msgstr "Kis-Lengyelország" + +#: contrib/localflavor/pl/pl_voivodeships.py:14 +msgid "Masovia" +msgstr "Masovia" + +#: contrib/localflavor/pl/pl_voivodeships.py:15 +msgid "Opole" +msgstr "Opole" + +#: contrib/localflavor/pl/pl_voivodeships.py:16 +msgid "Subcarpatia" +msgstr "Szubkárpátok" + +#: contrib/localflavor/pl/pl_voivodeships.py:17 +msgid "Podlasie" +msgstr "Podlasie" + +#: contrib/localflavor/pl/pl_voivodeships.py:18 +msgid "Pomerania" +msgstr "Pomeránia" + +#: contrib/localflavor/pl/pl_voivodeships.py:19 +msgid "Silesia" +msgstr "Szilézia" + +#: contrib/localflavor/pl/pl_voivodeships.py:20 +msgid "Swietokrzyskie" +msgstr "Swietokrzyskie" + +#: contrib/localflavor/pl/pl_voivodeships.py:21 +msgid "Warmia-Masuria" +msgstr "Warmia-Masuria" + +#: contrib/localflavor/pl/pl_voivodeships.py:22 +msgid "Greater Poland" +msgstr "Nagy-Lengyelország" + +#: contrib/localflavor/pl/pl_voivodeships.py:23 +msgid "West Pomerania" +msgstr "Nyugat-Pomeránia" + +#: contrib/localflavor/pl/forms.py:53 +msgid "National Identification Number consists of 11 digits." +msgstr "A nemzeti azonosítószám 11 számjegyből áll." + +#: contrib/localflavor/pl/forms.py:59 +msgid "Wrong checksum for the National Identification Number." +msgstr "Hibás a nemzeti azonosítószám ellenőrző kódja." + +#: contrib/localflavor/pl/forms.py:71 +msgid "Enter a tax number field (NIP) in the format XXX-XXX-XX-XX or XX-XX-XXX-XXX." +msgstr "Írjon be egy adószámot \"XXX-XXX-XX-XX\" vagy \"XX-XX-XXX-XXX\" alakban." + +#: contrib/localflavor/pl/forms.py:82 +msgid "Enter a postal code in the format XX-XXX." +msgstr "Írjon be egy irányítószámot 'XX-XXX' alakban." + +#: contrib/sessions/models.py:68 +msgid "session key" +msgstr "munkamenet kulcs" + +#: contrib/sessions/models.py:69 +msgid "session data" +msgstr "munkamenet adat" + +#: contrib/sessions/models.py:70 +msgid "expire date" +msgstr "lejárat dátuma" + +#: contrib/sessions/models.py:74 +msgid "session" +msgstr "munkamenet" + +#: contrib/sessions/models.py:75 +msgid "sessions" +msgstr "munkamenetek" + +#: contrib/flatpages/models.py:8 +msgid "Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "Például: '/about/contact/'. Figyeljen a nyitó és záró perjelre!" + +#: contrib/flatpages/models.py:9 +msgid "title" +msgstr "cím" + +#: contrib/flatpages/models.py:10 +msgid "content" +msgstr "tartalom" + +#: contrib/flatpages/models.py:11 +msgid "enable comments" +msgstr "megjegyzések engedélyezése" + +#: contrib/flatpages/models.py:12 +msgid "template name" +msgstr "sablon neve" + +#: contrib/flatpages/models.py:13 msgid "" -"A tag on line %(line)s is missing one or more required attributes. (Line " -"starts with \"%(start)s\".)" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." msgstr "" -"A %(line)s sorban lévő címkéről hiányzik egy vagy több kötelező tulajdonság. " -"(A sor kezdete: \"%(start)s\".)" +"Példa: 'flatpages/contact_page'. Ha ez nem létezik, a rendszer a 'flatpages/" +"default.html' sablont fogja használni." -#: core/validators.py:485 -#, python-format -msgid "" -"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line " -"starts with \"%(start)s\".)" +#: contrib/flatpages/models.py:14 +msgid "registration required" +msgstr "regisztráció szükséges" + +#: contrib/flatpages/models.py:14 +msgid "If this is checked, only logged-in users will be able to view the page." msgstr "" -"A(z) \"%(attr)s\" jellemző a %(line)s sorban érvénytelen. (A sor kezdete: \"%" -"(start)s\".)" +"Ha ez be van jelölve, csak bejelentkezett felhasználó tudja az oldalt " +"megnézni." -#: db/models/manipulators.py:302 -#, python-format -msgid "%(object)s with this %(type)s already exists for the given %(field)s." -msgstr "%(object)s ezzel a(z) %(type)s már létezik az adott %(field)s -nél." +#: contrib/flatpages/models.py:18 +msgid "flat page" +msgstr "egyszerű oldal" -#: db/models/fields/__init__.py:40 -#, python-format -msgid "%(optname)s with this %(fieldname)s already exists." -msgstr "%(optname)s ezzel a(z) %(fieldname)s már létezik." +#: contrib/flatpages/models.py:19 +msgid "flat pages" +msgstr "egyszerű oldalak" -#: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265 -#: db/models/fields/__init__.py:542 db/models/fields/__init__.py:553 -#: forms/__init__.py:346 -msgid "This field is required." -msgstr "Kötelező mező." +#: utils/dates.py:6 +msgid "Monday" +msgstr "hétfő" -#: db/models/fields/__init__.py:337 -#, fuzzy -msgid "This value must be an integer." -msgstr "Az értéknek %s hatványának kell lennie." +#: utils/dates.py:6 +msgid "Tuesday" +msgstr "kedd" -#: db/models/fields/__init__.py:369 -#, fuzzy -msgid "This value must be either True or False." -msgstr "Az értéknek %s hatványának kell lennie." +#: utils/dates.py:6 +msgid "Wednesday" +msgstr "szerda" -#: db/models/fields/__init__.py:385 -#, fuzzy -msgid "This field cannot be null." -msgstr "A mező érvénytelen." +#: utils/dates.py:6 +msgid "Thursday" +msgstr "csütörtök" -#: db/models/fields/__init__.py:562 -msgid "Enter a valid filename." -msgstr "Adj meg egy érvényes fájlnevet." +#: utils/dates.py:6 +msgid "Friday" +msgstr "péntek" -#: db/models/fields/related.py:43 -#, python-format -msgid "Please enter a valid %s." -msgstr "Írj be érvényes %s -t." +#: utils/dates.py:7 +msgid "Saturday" +msgstr "szombat" -#: db/models/fields/related.py:579 -#, fuzzy -msgid "Separate multiple IDs with commas." -msgstr "Az ID-ket vesszőkkel válaszd el." +#: utils/dates.py:7 +msgid "Sunday" +msgstr "vasárnap" -#: db/models/fields/related.py:581 -#, fuzzy -msgid "" -"Hold down \"Control\", or \"Command\" on a Mac, to select more than one." -msgstr "" -"Tartsd lenyomva a \"Control\"-t (vagy Mac-en a \"Command\"-ot) több elem " -"kiválasztásához." +#: utils/dates.py:10 +msgid "Mon" +msgstr "hét" + +#: utils/dates.py:10 +msgid "Tue" +msgstr "kedd" + +#: utils/dates.py:10 +msgid "Wed" +msgstr "sze" + +#: utils/dates.py:10 +msgid "Thu" +msgstr "csüt" + +#: utils/dates.py:10 +msgid "Fri" +msgstr "pén" + +#: utils/dates.py:11 +msgid "Sat" +msgstr "szo" + +#: utils/dates.py:11 +msgid "Sun" +msgstr "vas" + +#: utils/dates.py:18 +msgid "January" +msgstr "január" + +#: utils/dates.py:18 +msgid "February" +msgstr "február" + +#: utils/dates.py:18 utils/dates.py:31 +msgid "March" +msgstr "március" + +#: utils/dates.py:18 utils/dates.py:31 +msgid "April" +msgstr "április" + +#: utils/dates.py:18 utils/dates.py:31 +msgid "May" +msgstr "május" + +#: utils/dates.py:18 utils/dates.py:31 +msgid "June" +msgstr "június" + +#: utils/dates.py:19 utils/dates.py:31 +msgid "July" +msgstr "július" + +#: utils/dates.py:19 +msgid "August" +msgstr "augusztus" + +#: utils/dates.py:19 +msgid "September" +msgstr "szeptember" + +#: utils/dates.py:19 +msgid "October" +msgstr "október" + +#: utils/dates.py:19 +msgid "November" +msgstr "november" + +#: utils/dates.py:20 +msgid "December" +msgstr "december" + +#: utils/dates.py:23 +msgid "jan" +msgstr "jan" + +#: utils/dates.py:23 +msgid "feb" +msgstr "febr" -#: db/models/fields/related.py:625 +#: utils/dates.py:23 +msgid "mar" +msgstr "márc" + +#: utils/dates.py:23 +msgid "apr" +msgstr "ápr" + +#: utils/dates.py:23 +msgid "may" +msgstr "máj" + +#: utils/dates.py:23 +msgid "jun" +msgstr "jún" + +#: utils/dates.py:24 +msgid "jul" +msgstr "júl" + +#: utils/dates.py:24 +msgid "aug" +msgstr "aug" + +#: utils/dates.py:24 +msgid "sep" +msgstr "szept" + +#: utils/dates.py:24 +msgid "oct" +msgstr "okt" + +#: utils/dates.py:24 +msgid "nov" +msgstr "nov" + +#: utils/dates.py:24 +msgid "dec" +msgstr "dec" + +#: utils/dates.py:31 +msgid "Jan." +msgstr "jan." + +#: utils/dates.py:31 +msgid "Feb." +msgstr "febr." + +#: utils/dates.py:32 +msgid "Aug." +msgstr "aug." + +#: utils/dates.py:32 +msgid "Sept." +msgstr "szept." + +#: utils/dates.py:32 +msgid "Oct." +msgstr "okt." + +#: utils/dates.py:32 +msgid "Nov." +msgstr "nov." + +#: utils/dates.py:32 +msgid "Dec." +msgstr "dec." + +#: utils/timesince.py:12 +msgid "year" +msgid_plural "years" +msgstr[0] "év" +msgstr[1] "év" + +#: utils/timesince.py:13 +msgid "month" +msgid_plural "months" +msgstr[0] "hónap" +msgstr[1] "hónap" + +#: utils/timesince.py:14 +msgid "week" +msgid_plural "weeks" +msgstr[0] "hét" +msgstr[1] "hét" + +#: utils/timesince.py:15 +msgid "day" +msgid_plural "days" +msgstr[0] "nap" +msgstr[1] "nap" + +#: utils/timesince.py:16 +msgid "hour" +msgid_plural "hours" +msgstr[0] "óra" +msgstr[1] "óra" + +#: utils/timesince.py:17 +msgid "minute" +msgid_plural "minutes" +msgstr[0] "perc" +msgstr[1] "perc" + +#: utils/timesince.py:39 #, python-format -msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid." -msgid_plural "" -"Please enter valid %(self)s IDs. The values %(value)r are invalid." -msgstr[0] "" -"Kérlek írj be érvényes %(self)s ID-t. A mostani érték %(value)r érvénytelen." -msgstr[1] "" -"Kérlek írj be érvényes %(self)s ID-ket. A mostani értékek %(value)r " -"érvénytelenek." +msgid "%(number)d %(type)s" +msgstr "%(number)d %(type)s" -#: forms/__init__.py:380 +#: utils/timesince.py:45 #, python-format -msgid "Ensure your text is less than %s character." -msgid_plural "Ensure your text is less than %s characters." -msgstr[0] "A szövegnek kevesebbnek kell lennie %s karakternél." -msgstr[1] "A szövegnek kevesebbnek kell lennie %s karakternél." +msgid ", %(number)d %(type)s" +msgstr ", %(number)d %(type)s" -#: forms/__init__.py:385 -msgid "Line breaks are not allowed here." -msgstr "Sortörések itt nem megengedettek." +#: utils/text.py:127 +msgid "or" +msgstr "vagy" -#: forms/__init__.py:480 forms/__init__.py:551 forms/__init__.py:589 -#, python-format -msgid "Select a valid choice; '%(data)s' is not in %(choices)s." -msgstr "Válassz érvényes elemet, '%(data)s' nincs a(z) %(choices)s között." +#: utils/dateformat.py:41 +msgid "p.m." +msgstr "du" -#: forms/__init__.py:645 -msgid "The submitted file is empty." -msgstr "A küldött fájl üres." +#: utils/dateformat.py:42 +msgid "a.m." +msgstr "de" -#: forms/__init__.py:699 -msgid "Enter a whole number between -32,768 and 32,767." -msgstr "Írj be egy számot -32,768 és 32,767 között." +#: utils/dateformat.py:47 +msgid "PM" +msgstr "DU" -#: forms/__init__.py:708 -msgid "Enter a positive number." -msgstr "Írj be egy pozitív számot." +#: utils/dateformat.py:48 +msgid "AM" +msgstr "DE" -#: forms/__init__.py:717 -msgid "Enter a whole number between 0 and 32,767." -msgstr "Írj be egy egész számot 0 and 32,767 között." +#: utils/dateformat.py:97 +msgid "midnight" +msgstr "éjfél" -#: template/defaultfilters.py:379 -msgid "yes,no,maybe" -msgstr "igen, nem, talán" +#: utils/dateformat.py:99 +msgid "noon" +msgstr "dél" -#~ msgid "Comment" -#~ msgstr "Megjegyzés" +#: utils/translation/trans_real.py:391 +msgid "DATE_FORMAT" +msgstr "Y. F j." -#~ msgid "Comments" -#~ msgstr "Megjegyzések" +#: utils/translation/trans_real.py:392 +msgid "DATETIME_FORMAT" +msgstr "Y. F j., H:i" -#~ msgid "String (up to 50)" -#~ msgstr "Karakterlánc (50 karakterig)" +#: utils/translation/trans_real.py:393 +msgid "TIME_FORMAT" +msgstr "H:i" + +#: utils/translation/trans_real.py:409 +msgid "YEAR_MONTH_FORMAT" +msgstr "Y. F j." + +#: utils/translation/trans_real.py:410 +msgid "MONTH_DAY_FORMAT" +msgstr "Y. F j." -#~ msgid "label" -#~ msgstr "címke" +#: template/defaultfilters.py:485 +msgid "yes,no,maybe" +msgstr "igen,nem,talán" + +#: template/defaultfilters.py:514 +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d bájt" +msgstr[1] "%(size)d bájt" -#~ msgid "package" -#~ msgstr "csomag" +#: template/defaultfilters.py:516 +#, python-format +msgid "%.1f KB" +msgstr "%.1f KB" + +#: template/defaultfilters.py:518 +#, python-format +msgid "%.1f MB" +msgstr "%.1f MB" + +#: template/defaultfilters.py:519 +#, python-format +msgid "%.1f GB" +msgstr "%.1f GB" -#~ msgid "packages" -#~ msgstr "csomagok" diff --git a/django/conf/locale/hu/LC_MESSAGES/djangojs.mo b/django/conf/locale/hu/LC_MESSAGES/djangojs.mo Binary files differindex 5b8214fa31..c481ba2e19 100644 --- a/django/conf/locale/hu/LC_MESSAGES/djangojs.mo +++ b/django/conf/locale/hu/LC_MESSAGES/djangojs.mo diff --git a/django/conf/locale/hu/LC_MESSAGES/djangojs.po b/django/conf/locale/hu/LC_MESSAGES/djangojs.po index 901a90bb41..186902ecdc 100644 --- a/django/conf/locale/hu/LC_MESSAGES/djangojs.po +++ b/django/conf/locale/hu/LC_MESSAGES/djangojs.po @@ -1,20 +1,21 @@ -# translation of djangojs.po to +# translation of djangojs.po to Hungarian +# translation of djangojs.po to # This file is distributed under the same license as the PACKAGE package. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER. -# Nagy Károly <charlie@rendszergazda.com>, 2006. # msgid "" msgstr "" "Project-Id-Version: djangojs\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2005-12-09 11:51+0100\n" -"PO-Revision-Date: 2006-05-10 11:59+0200\n" -"Last-Translator: Nagy Károly <charlie@rendszergazda.com>\n" -"Language-Team: <hu@li.org>\n" +"PO-Revision-Date: 2007-09-13 13:30+0200\n" +"Last-Translator: Szilveszter Farkas <szilveszter.farkas@gmail.com>\n" +"Language-Team: Hungarian <hu@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: KBabel 1.9.1\n" +"X-Generator: KBabel 1.11.4\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" #: contrib/admin/media/js/SelectFilter2.js:33 #, perl-format @@ -23,15 +24,15 @@ msgstr "Elérhető %s" #: contrib/admin/media/js/SelectFilter2.js:41 msgid "Choose all" -msgstr "Mindent kijelöl" +msgstr "Mindet kijelölni" #: contrib/admin/media/js/SelectFilter2.js:46 msgid "Add" -msgstr "Hozzáad" +msgstr "Hozzáadás" #: contrib/admin/media/js/SelectFilter2.js:48 msgid "Remove" -msgstr "Eltávolít" +msgstr "Eltávolítás" #: contrib/admin/media/js/SelectFilter2.js:53 #, perl-format @@ -40,7 +41,7 @@ msgstr "%s kiválasztva" #: contrib/admin/media/js/SelectFilter2.js:54 msgid "Select your choice(s) and click " -msgstr "Válaszd ki a kért elemeket és kattints" +msgstr "Válassza ki a kért elemeket és kattintson" #: contrib/admin/media/js/SelectFilter2.js:59 msgid "Clear all" @@ -51,11 +52,11 @@ msgstr "Összes törlése" msgid "" "January February March April May June July August September October November " "December" -msgstr "Január Február Március Április Május Június Július Szeptember Október November December" +msgstr "január február március április május június július augusztus szeptember október november december" #: contrib/admin/media/js/dateparse.js:27 msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday" -msgstr "Vasárnap Hétfő Kedd Szerda Csütörtök Péntek Szombat" +msgstr "vasárnap hétfő kedd szerda csütörtök péntek szombat" #: contrib/admin/media/js/calendar.js:25 msgid "S M T W T F S" @@ -72,7 +73,7 @@ msgstr "Óra" #: contrib/admin/media/js/admin/DateTimeShortcuts.js:77 msgid "Choose a time" -msgstr "Válaszd ki az időt" +msgstr "Válassza ki az időt" #: contrib/admin/media/js/admin/DateTimeShortcuts.js:81 msgid "Midnight" diff --git a/django/conf/locale/ja/LC_MESSAGES/django.mo b/django/conf/locale/ja/LC_MESSAGES/django.mo Binary files differindex 20eb7dbcd3..647717ea06 100644 --- a/django/conf/locale/ja/LC_MESSAGES/django.mo +++ b/django/conf/locale/ja/LC_MESSAGES/django.mo diff --git a/django/conf/locale/ja/LC_MESSAGES/django.po b/django/conf/locale/ja/LC_MESSAGES/django.po index 56f1bf99da..593f5d8a6d 100644 --- a/django/conf/locale/ja/LC_MESSAGES/django.po +++ b/django/conf/locale/ja/LC_MESSAGES/django.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Django 1.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-06-26 11:33+0900\n" +"POT-Creation-Date: 2007-08-27 13:00+0900\n" "PO-Revision-Date: 2006-05-18 00:28+0900\n" "Last-Translator: makoto tsuyuki <mtsuyuki@gmail.com>\n" "Language-Team: Japanese <django-ja@googlegroups.com>\n" @@ -87,102 +87,106 @@ msgid "Hebrew" msgstr "ヘブライ語" #: conf/global_settings.py:57 +msgid "Croatian" +msgstr "クロアチア語" + +#: conf/global_settings.py:58 msgid "Icelandic" msgstr "アイスランド語" -#: conf/global_settings.py:58 +#: conf/global_settings.py:59 msgid "Italian" msgstr "イタリア語" -#: conf/global_settings.py:59 +#: conf/global_settings.py:60 msgid "Japanese" msgstr "日本語" -#: conf/global_settings.py:60 +#: conf/global_settings.py:61 msgid "Korean" msgstr "韓国語" -#: conf/global_settings.py:61 +#: conf/global_settings.py:62 msgid "Kannada" msgstr "カンナダ語" -#: conf/global_settings.py:62 +#: conf/global_settings.py:63 msgid "Latvian" msgstr "ラトビア語" -#: conf/global_settings.py:63 +#: conf/global_settings.py:64 msgid "Macedonian" msgstr "マケドニア語" -#: conf/global_settings.py:64 +#: conf/global_settings.py:65 msgid "Dutch" msgstr "オランダ語" -#: conf/global_settings.py:65 +#: conf/global_settings.py:66 msgid "Norwegian" msgstr "ノルウェー語" -#: conf/global_settings.py:66 +#: conf/global_settings.py:67 msgid "Polish" msgstr "ポーランド語" -#: conf/global_settings.py:67 +#: conf/global_settings.py:68 msgid "Portugese" msgstr "ポルトガル語" -#: conf/global_settings.py:68 +#: conf/global_settings.py:69 msgid "Brazilian" msgstr "ブラジル語" -#: conf/global_settings.py:69 +#: conf/global_settings.py:70 msgid "Romanian" msgstr "ルーマニア語" -#: conf/global_settings.py:70 +#: conf/global_settings.py:71 msgid "Russian" msgstr "ロシア語" -#: conf/global_settings.py:71 +#: conf/global_settings.py:72 msgid "Slovak" msgstr "スロバキア語" -#: conf/global_settings.py:72 +#: conf/global_settings.py:73 msgid "Slovenian" msgstr "スロヴェニア語" -#: conf/global_settings.py:73 +#: conf/global_settings.py:74 msgid "Serbian" msgstr "セルビア語" -#: conf/global_settings.py:74 +#: conf/global_settings.py:75 msgid "Swedish" msgstr "スウェーデン語" -#: conf/global_settings.py:75 +#: conf/global_settings.py:76 msgid "Tamil" msgstr "タミル語" -#: conf/global_settings.py:76 +#: conf/global_settings.py:77 msgid "Telugu" msgstr "テルグ語" -#: conf/global_settings.py:77 +#: conf/global_settings.py:78 msgid "Turkish" msgstr "トルコ語" -#: conf/global_settings.py:78 +#: conf/global_settings.py:79 msgid "Ukrainian" msgstr "ウクライナ語" -#: conf/global_settings.py:79 +#: conf/global_settings.py:80 msgid "Simplified Chinese" msgstr "簡体字中国語" -#: conf/global_settings.py:80 +#: conf/global_settings.py:81 msgid "Traditional Chinese" msgstr "繁体字中国語" -#: contrib/admin/filterspecs.py:40 +#: contrib/admin/filterspecs.py:42 #, python-format msgid "" "<h3>By %s:</h3>\n" @@ -191,71 +195,71 @@ msgstr "" "<h3>%s で絞り込む</h3>\n" "<ul>\n" -#: contrib/admin/filterspecs.py:70 contrib/admin/filterspecs.py:88 -#: contrib/admin/filterspecs.py:143 contrib/admin/filterspecs.py:169 +#: contrib/admin/filterspecs.py:72 contrib/admin/filterspecs.py:90 +#: contrib/admin/filterspecs.py:145 contrib/admin/filterspecs.py:171 msgid "All" msgstr "全て" -#: contrib/admin/filterspecs.py:109 +#: contrib/admin/filterspecs.py:111 msgid "Any date" msgstr "いつでも" -#: contrib/admin/filterspecs.py:110 +#: contrib/admin/filterspecs.py:112 msgid "Today" msgstr "今日" -#: contrib/admin/filterspecs.py:113 +#: contrib/admin/filterspecs.py:115 msgid "Past 7 days" msgstr "過去 7 日間" -#: contrib/admin/filterspecs.py:115 +#: contrib/admin/filterspecs.py:117 msgid "This month" msgstr "今月" -#: contrib/admin/filterspecs.py:117 +#: contrib/admin/filterspecs.py:119 msgid "This year" msgstr "今年" -#: contrib/admin/filterspecs.py:143 newforms/widgets.py:181 -#: oldforms/__init__.py:577 +#: contrib/admin/filterspecs.py:145 newforms/widgets.py:188 +#: oldforms/__init__.py:591 msgid "Yes" msgstr "はい" -#: contrib/admin/filterspecs.py:143 newforms/widgets.py:181 -#: oldforms/__init__.py:577 +#: contrib/admin/filterspecs.py:145 newforms/widgets.py:188 +#: oldforms/__init__.py:591 msgid "No" msgstr "いいえ" -#: contrib/admin/filterspecs.py:150 newforms/widgets.py:181 -#: oldforms/__init__.py:577 +#: contrib/admin/filterspecs.py:152 newforms/widgets.py:188 +#: oldforms/__init__.py:591 msgid "Unknown" msgstr "不明" -#: contrib/admin/models.py:16 +#: contrib/admin/models.py:17 msgid "action time" msgstr "操作時刻" -#: contrib/admin/models.py:19 +#: contrib/admin/models.py:20 msgid "object id" msgstr "オブジェクト ID" -#: contrib/admin/models.py:20 +#: contrib/admin/models.py:21 msgid "object repr" msgstr "オブジェクトの文字列表現" -#: contrib/admin/models.py:21 +#: contrib/admin/models.py:22 msgid "action flag" msgstr "操作種別" -#: contrib/admin/models.py:22 +#: contrib/admin/models.py:23 msgid "change message" msgstr "変更メッセージ" -#: contrib/admin/models.py:25 +#: contrib/admin/models.py:26 msgid "log entry" msgstr "ログエントリ" -#: contrib/admin/models.py:26 +#: contrib/admin/models.py:27 msgid "log entries" msgstr "ログエントリ" @@ -792,29 +796,29 @@ msgstr "現在:" msgid "Change:" msgstr "変更:" -#: contrib/admin/templatetags/admin_list.py:249 +#: contrib/admin/templatetags/admin_list.py:254 msgid "All dates" msgstr "いつでも" -#: contrib/admin/views/auth.py:19 contrib/admin/views/main.py:262 +#: contrib/admin/views/auth.py:20 contrib/admin/views/main.py:264 #, python-format msgid "The %(name)s \"%(obj)s\" was added successfully." msgstr "%(name)s \"%(obj)s\" を追加しました。" -#: contrib/admin/views/auth.py:24 contrib/admin/views/main.py:266 -#: contrib/admin/views/main.py:352 +#: contrib/admin/views/auth.py:25 contrib/admin/views/main.py:268 +#: contrib/admin/views/main.py:354 msgid "You may edit it again below." msgstr "続けて編集できます。" -#: contrib/admin/views/auth.py:30 +#: contrib/admin/views/auth.py:31 msgid "Add user" msgstr "ユーザを追加" -#: contrib/admin/views/auth.py:57 +#: contrib/admin/views/auth.py:58 msgid "Password changed successfully." msgstr "パスワードを変更しました" -#: contrib/admin/views/auth.py:64 +#: contrib/admin/views/auth.py:65 #, python-format msgid "Change password: %s" msgstr "パスワードの変更: %s" @@ -851,235 +855,236 @@ msgstr "ユーザ名には '@' を含められません。" msgid "Your e-mail address is not your username. Try '%s' instead." msgstr "メールアドレスはユーザ名ではありません。 '%s' を試してみてください。" -#: contrib/admin/views/doc.py:46 contrib/admin/views/doc.py:48 -#: contrib/admin/views/doc.py:50 +#: contrib/admin/views/doc.py:47 contrib/admin/views/doc.py:49 +#: contrib/admin/views/doc.py:51 msgid "tag:" msgstr "タグ" -#: contrib/admin/views/doc.py:77 contrib/admin/views/doc.py:79 -#: contrib/admin/views/doc.py:81 +#: contrib/admin/views/doc.py:78 contrib/admin/views/doc.py:80 +#: contrib/admin/views/doc.py:82 msgid "filter:" msgstr "フィルタ" -#: contrib/admin/views/doc.py:135 contrib/admin/views/doc.py:137 -#: contrib/admin/views/doc.py:139 +#: contrib/admin/views/doc.py:136 contrib/admin/views/doc.py:138 +#: contrib/admin/views/doc.py:140 msgid "view:" msgstr "ビュー" -#: contrib/admin/views/doc.py:164 +#: contrib/admin/views/doc.py:165 #, python-format msgid "App %r not found" msgstr "アプリケーション %r が見つかりません" -#: contrib/admin/views/doc.py:171 +#: contrib/admin/views/doc.py:172 #, python-format msgid "Model %(name)r not found in app %(label)r" msgstr "モデル %(name)r が %(label)r アプリケーションに見つかりません" -#: contrib/admin/views/doc.py:183 +#: contrib/admin/views/doc.py:184 #, python-format msgid "the related `%(label)s.%(type)s` object" msgstr "`%(label)s.%(type)s` (関連オブジェクト)" -#: contrib/admin/views/doc.py:183 contrib/admin/views/doc.py:205 -#: contrib/admin/views/doc.py:219 contrib/admin/views/doc.py:224 +#: contrib/admin/views/doc.py:184 contrib/admin/views/doc.py:206 +#: contrib/admin/views/doc.py:220 contrib/admin/views/doc.py:225 msgid "model:" msgstr "モデル :" -#: contrib/admin/views/doc.py:214 +#: contrib/admin/views/doc.py:215 #, python-format msgid "related `%(label)s.%(name)s` objects" msgstr "`%(label)s.%(name)s` (関連オブジェクト)" -#: contrib/admin/views/doc.py:219 +#: contrib/admin/views/doc.py:220 #, python-format msgid "all %s" msgstr "全ての %s" -#: contrib/admin/views/doc.py:224 +#: contrib/admin/views/doc.py:225 #, python-format msgid "number of %s" msgstr "%s の数" -#: contrib/admin/views/doc.py:229 +#: contrib/admin/views/doc.py:230 #, python-format msgid "Fields on %s objects" msgstr "%s のフィールド" -#: contrib/admin/views/doc.py:291 contrib/admin/views/doc.py:302 -#: contrib/admin/views/doc.py:304 contrib/admin/views/doc.py:310 -#: contrib/admin/views/doc.py:311 contrib/admin/views/doc.py:313 +#: contrib/admin/views/doc.py:292 contrib/admin/views/doc.py:303 +#: contrib/admin/views/doc.py:305 contrib/admin/views/doc.py:311 +#: contrib/admin/views/doc.py:312 contrib/admin/views/doc.py:314 msgid "Integer" msgstr "整数" -#: contrib/admin/views/doc.py:292 +#: contrib/admin/views/doc.py:293 msgid "Boolean (Either True or False)" msgstr "ブール値 (真: True または偽: False)" -#: contrib/admin/views/doc.py:293 contrib/admin/views/doc.py:312 +#: contrib/admin/views/doc.py:294 contrib/admin/views/doc.py:313 #, python-format -msgid "String (up to %(maxlength)s)" -msgstr "文字列 ( %(maxlength)s 字まで )" +msgid "String (up to %(max_length)s)" +msgstr "文字列 ( %(max_length)s 字まで )" -#: contrib/admin/views/doc.py:294 +#: contrib/admin/views/doc.py:295 msgid "Comma-separated integers" msgstr "カンマ区切りの整数" -#: contrib/admin/views/doc.py:295 +#: contrib/admin/views/doc.py:296 msgid "Date (without time)" msgstr "日付" -#: contrib/admin/views/doc.py:296 +#: contrib/admin/views/doc.py:297 msgid "Date (with time)" msgstr "日時" -#: contrib/admin/views/doc.py:297 +#: contrib/admin/views/doc.py:298 msgid "Decimal number" msgstr "10 進数 (小数可)" -#: contrib/admin/views/doc.py:298 +#: contrib/admin/views/doc.py:299 msgid "E-mail address" msgstr "メールアドレス" -#: contrib/admin/views/doc.py:299 contrib/admin/views/doc.py:300 -#: contrib/admin/views/doc.py:303 +#: contrib/admin/views/doc.py:300 contrib/admin/views/doc.py:301 +#: contrib/admin/views/doc.py:304 msgid "File path" msgstr "ファイルの場所" -#: contrib/admin/views/doc.py:301 +#: contrib/admin/views/doc.py:302 msgid "Floating point number" msgstr "浮動小数点" -#: contrib/admin/views/doc.py:305 contrib/comments/models.py:85 +#: contrib/admin/views/doc.py:306 contrib/comments/models.py:85 msgid "IP address" msgstr "IP アドレス" -#: contrib/admin/views/doc.py:307 +#: contrib/admin/views/doc.py:308 msgid "Boolean (Either True, False or None)" msgstr "ブール値 (真: True 、偽: False または None)" -#: contrib/admin/views/doc.py:308 +#: contrib/admin/views/doc.py:309 msgid "Relation to parent model" msgstr "親モデルへのリレーション" -#: contrib/admin/views/doc.py:309 +#: contrib/admin/views/doc.py:310 msgid "Phone number" msgstr "電話番号" -#: contrib/admin/views/doc.py:314 +#: contrib/admin/views/doc.py:315 msgid "Text" msgstr "テキスト" -#: contrib/admin/views/doc.py:315 +#: contrib/admin/views/doc.py:316 msgid "Time" msgstr "時刻" -#: contrib/admin/views/doc.py:316 contrib/flatpages/models.py:7 +#: contrib/admin/views/doc.py:317 contrib/flatpages/models.py:7 msgid "URL" msgstr "URL" -#: contrib/admin/views/doc.py:317 +#: contrib/admin/views/doc.py:318 msgid "U.S. state (two uppercase letters)" msgstr "アメリカの州 (大文字二文字で)" -#: contrib/admin/views/doc.py:318 +#: contrib/admin/views/doc.py:319 msgid "XML text" msgstr "XMLテキスト" -#: contrib/admin/views/doc.py:344 +#: contrib/admin/views/doc.py:345 #, python-format msgid "%s does not appear to be a urlpattern object" msgstr "%s はurlpatternオブジェクトでは無いようです" -#: contrib/admin/views/main.py:228 +#: contrib/admin/views/main.py:230 msgid "Site administration" msgstr "サイト管理" -#: contrib/admin/views/main.py:276 contrib/admin/views/main.py:361 +#: contrib/admin/views/main.py:278 contrib/admin/views/main.py:363 #, python-format msgid "You may add another %s below." msgstr "続けて別の %s を追加できます。" -#: contrib/admin/views/main.py:294 +#: contrib/admin/views/main.py:296 #, python-format msgid "Add %s" msgstr "%s を追加" -#: contrib/admin/views/main.py:340 +#: contrib/admin/views/main.py:342 #, python-format msgid "Added %s." msgstr "%s を追加しました。" -#: contrib/admin/views/main.py:340 contrib/admin/views/main.py:342 -#: contrib/admin/views/main.py:344 db/models/manipulators.py:308 +#: contrib/admin/views/main.py:342 contrib/admin/views/main.py:344 +#: contrib/admin/views/main.py:346 core/validators.py:275 +#: db/models/manipulators.py:310 msgid "and" msgstr "と" -#: contrib/admin/views/main.py:342 +#: contrib/admin/views/main.py:344 #, python-format msgid "Changed %s." msgstr "%s を変更しました。" -#: contrib/admin/views/main.py:344 +#: contrib/admin/views/main.py:346 #, python-format msgid "Deleted %s." msgstr "%s を削除しました。" -#: contrib/admin/views/main.py:347 +#: contrib/admin/views/main.py:349 msgid "No fields changed." msgstr "変更はありませんでした。" -#: contrib/admin/views/main.py:350 +#: contrib/admin/views/main.py:352 #, python-format msgid "The %(name)s \"%(obj)s\" was changed successfully." msgstr "%(name)s \"%(obj)s\" を変更しました。" -#: contrib/admin/views/main.py:358 +#: contrib/admin/views/main.py:360 #, python-format msgid "" "The %(name)s \"%(obj)s\" was added successfully. You may edit it again below." msgstr "%(name)s \"%(obj)s\" を追加しました。続けて編集できます。" -#: contrib/admin/views/main.py:396 +#: contrib/admin/views/main.py:398 #, python-format msgid "Change %s" msgstr "%s を変更" -#: contrib/admin/views/main.py:481 +#: contrib/admin/views/main.py:483 #, python-format msgid "One or more %(fieldname)s in %(name)s: %(obj)s" msgstr "%(name)s に %(fieldname)s が一つ以上あります: %(obj)s" -#: contrib/admin/views/main.py:486 +#: contrib/admin/views/main.py:488 #, python-format msgid "One or more %(fieldname)s in %(name)s:" msgstr "%(name)s に %(fieldname)s が一つ以上あります:" -#: contrib/admin/views/main.py:518 +#: contrib/admin/views/main.py:520 #, python-format msgid "The %(name)s \"%(obj)s\" was deleted successfully." msgstr "%(name)s \"%(obj)s\" を削除しました。" -#: contrib/admin/views/main.py:521 +#: contrib/admin/views/main.py:523 msgid "Are you sure?" msgstr "よろしいですか?" -#: contrib/admin/views/main.py:543 +#: contrib/admin/views/main.py:545 #, python-format msgid "Change history: %s" msgstr "変更履歴: %s" -#: contrib/admin/views/main.py:577 +#: contrib/admin/views/main.py:579 #, python-format msgid "Select %s" msgstr "%s を選択" -#: contrib/admin/views/main.py:577 +#: contrib/admin/views/main.py:579 #, python-format msgid "Select %s to change" msgstr "変更する %s を選択" -#: contrib/admin/views/main.py:772 +#: contrib/admin/views/main.py:780 msgid "Database error" msgstr "データベースエラー" @@ -1117,35 +1122,35 @@ msgstr "新しいパスワード(確認用)が一致しません。" msgid "Your old password was entered incorrectly. Please enter it again." msgstr "元のパスワードが間違っています。もう一度入力してください。" -#: contrib/auth/models.py:49 contrib/auth/models.py:69 +#: contrib/auth/models.py:53 contrib/auth/models.py:73 msgid "name" msgstr "名前" -#: contrib/auth/models.py:51 +#: contrib/auth/models.py:55 msgid "codename" msgstr "コード名" -#: contrib/auth/models.py:54 +#: contrib/auth/models.py:58 msgid "permission" msgstr "パーミッション" -#: contrib/auth/models.py:55 contrib/auth/models.py:70 +#: contrib/auth/models.py:59 contrib/auth/models.py:74 msgid "permissions" msgstr "パーミッション" -#: contrib/auth/models.py:73 +#: contrib/auth/models.py:77 msgid "group" msgstr "グループ" -#: contrib/auth/models.py:74 contrib/auth/models.py:114 +#: contrib/auth/models.py:78 contrib/auth/models.py:121 msgid "groups" msgstr "グループ" -#: contrib/auth/models.py:104 +#: contrib/auth/models.py:111 msgid "username" msgstr "ユーザ名" -#: contrib/auth/models.py:104 +#: contrib/auth/models.py:111 msgid "" "Required. 30 characters or fewer. Alphanumeric characters only (letters, " "digits and underscores)." @@ -1153,23 +1158,23 @@ msgstr "" "この項目は必須です。半角アルファベット、半角数字、半角アンダーバーで30文字以" "下にしてください。" -#: contrib/auth/models.py:105 +#: contrib/auth/models.py:112 msgid "first name" msgstr "名" -#: contrib/auth/models.py:106 +#: contrib/auth/models.py:113 msgid "last name" msgstr "姓" -#: contrib/auth/models.py:107 +#: contrib/auth/models.py:114 msgid "e-mail address" msgstr "メールアドレス" -#: contrib/auth/models.py:108 +#: contrib/auth/models.py:115 msgid "password" msgstr "パスワード" -#: contrib/auth/models.py:108 +#: contrib/auth/models.py:115 msgid "" "Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change " "password form</a>." @@ -1177,43 +1182,43 @@ msgstr "" "'[algo]$[salt]$[hexdigest]'形式か、<a href=\"password/\">パスワード変更フォー" "ム</a>を使ってください。" -#: contrib/auth/models.py:109 +#: contrib/auth/models.py:116 msgid "staff status" msgstr "スタッフ権限" -#: contrib/auth/models.py:109 +#: contrib/auth/models.py:116 msgid "Designates whether the user can log into this admin site." msgstr "ユーザが管理サイトにログイン可能かどうかを示します。" -#: contrib/auth/models.py:110 +#: contrib/auth/models.py:117 msgid "active" msgstr "有効" -#: contrib/auth/models.py:110 +#: contrib/auth/models.py:117 msgid "" "Designates whether this user can log into the Django admin. Unselect this " "instead of deleting accounts." msgstr "ユーザが管理サイトにログイン可能かどうかを示します。" -#: contrib/auth/models.py:111 +#: contrib/auth/models.py:118 msgid "superuser status" msgstr "スーパーユーザ権限" -#: contrib/auth/models.py:111 +#: contrib/auth/models.py:118 msgid "" "Designates that this user has all permissions without explicitly assigning " "them." msgstr "全ての権限を持っているとみなされます。" -#: contrib/auth/models.py:112 +#: contrib/auth/models.py:119 msgid "last login" msgstr "最終ログイン" -#: contrib/auth/models.py:113 +#: contrib/auth/models.py:120 msgid "date joined" msgstr "登録日" -#: contrib/auth/models.py:115 +#: contrib/auth/models.py:122 msgid "" "In addition to the permissions manually assigned, this user will also get " "all permissions granted to each group he/she is in." @@ -1221,47 +1226,43 @@ msgstr "" "手動で付与したパーミッションに加え、所属しているグループに付与された全ての" "パーミッションを獲得します。" -#: contrib/auth/models.py:116 +#: contrib/auth/models.py:123 msgid "user permissions" msgstr "ユーザパーミッション" -#: contrib/auth/models.py:120 +#: contrib/auth/models.py:127 msgid "user" msgstr "ユーザ" -#: contrib/auth/models.py:121 +#: contrib/auth/models.py:128 msgid "users" msgstr "ユーザ" -#: contrib/auth/models.py:127 +#: contrib/auth/models.py:134 msgid "Personal info" msgstr "個人情報" -#: contrib/auth/models.py:128 +#: contrib/auth/models.py:135 msgid "Permissions" msgstr "パーミッション" -#: contrib/auth/models.py:129 +#: contrib/auth/models.py:136 msgid "Important dates" msgstr "重要な日程" -#: contrib/auth/models.py:130 +#: contrib/auth/models.py:137 msgid "Groups" msgstr "グループ" -#: contrib/auth/models.py:272 +#: contrib/auth/models.py:288 msgid "message" msgstr "メッセージ" -#: contrib/auth/models.py:285 -msgid "AnonymousUser" -msgstr "非認証ユーザ" - -#: contrib/auth/views.py:40 +#: contrib/auth/views.py:47 msgid "Logged out" msgstr "ログアウト" -#: contrib/comments/models.py:67 contrib/comments/models.py:166 +#: contrib/comments/models.py:67 contrib/comments/models.py:169 msgid "object ID" msgstr "オブジェクト ID" @@ -1270,7 +1271,7 @@ msgid "headline" msgstr "新着情報" #: contrib/comments/models.py:69 contrib/comments/models.py:90 -#: contrib/comments/models.py:167 +#: contrib/comments/models.py:170 msgid "comment" msgstr "コメント" @@ -1310,11 +1311,11 @@ msgstr "レーティング #8" msgid "is valid rating" msgstr "は有効なレーティングです" -#: contrib/comments/models.py:83 contrib/comments/models.py:169 +#: contrib/comments/models.py:83 contrib/comments/models.py:172 msgid "date/time submitted" msgstr "コメント投稿日時" -#: contrib/comments/models.py:84 contrib/comments/models.py:170 +#: contrib/comments/models.py:84 contrib/comments/models.py:173 msgid "is public" msgstr "は公開中です" @@ -1334,11 +1335,11 @@ msgstr "" msgid "comments" msgstr "コメント" -#: contrib/comments/models.py:131 contrib/comments/models.py:207 +#: contrib/comments/models.py:134 contrib/comments/models.py:213 msgid "Content object" msgstr "コンテンツオブジェクト" -#: contrib/comments/models.py:159 +#: contrib/comments/models.py:162 #, python-format msgid "" "Posted by %(user)s at %(date)s\n" @@ -1353,48 +1354,48 @@ msgstr "" "\n" "http://%(domain)s%(url)s" -#: contrib/comments/models.py:168 +#: contrib/comments/models.py:171 msgid "person's name" msgstr "名前" -#: contrib/comments/models.py:171 +#: contrib/comments/models.py:174 msgid "ip address" msgstr "IP アドレス" -#: contrib/comments/models.py:173 +#: contrib/comments/models.py:176 msgid "approved by staff" msgstr "スタッフの承認済み" -#: contrib/comments/models.py:176 +#: contrib/comments/models.py:179 msgid "free comment" msgstr "フリーコメント" -#: contrib/comments/models.py:177 +#: contrib/comments/models.py:180 msgid "free comments" msgstr "フリーコメント" -#: contrib/comments/models.py:233 +#: contrib/comments/models.py:239 msgid "score" msgstr "スコア" -#: contrib/comments/models.py:234 +#: contrib/comments/models.py:240 msgid "score date" msgstr "スコアされた日" -#: contrib/comments/models.py:237 +#: contrib/comments/models.py:243 msgid "karma score" msgstr "カルマスコア" -#: contrib/comments/models.py:238 +#: contrib/comments/models.py:244 msgid "karma scores" msgstr "カルマスコア" -#: contrib/comments/models.py:242 +#: contrib/comments/models.py:248 #, python-format msgid "%(score)d rating by %(user)s" msgstr "%(user)s により %(score)d 点のレーティング" -#: contrib/comments/models.py:258 +#: contrib/comments/models.py:264 #, python-format msgid "" "This comment was flagged by %(user)s:\n" @@ -1405,36 +1406,36 @@ msgstr "" "\n" "%(text)s" -#: contrib/comments/models.py:265 +#: contrib/comments/models.py:271 msgid "flag date" msgstr "フラグ日" -#: contrib/comments/models.py:268 +#: contrib/comments/models.py:274 msgid "user flag" msgstr "ユーザフラグ" -#: contrib/comments/models.py:269 +#: contrib/comments/models.py:275 msgid "user flags" msgstr "ユーザフラグ" -#: contrib/comments/models.py:273 +#: contrib/comments/models.py:279 #, python-format msgid "Flag by %r" msgstr "%r によるフラグ" -#: contrib/comments/models.py:278 +#: contrib/comments/models.py:284 msgid "deletion date" msgstr "削除日" -#: contrib/comments/models.py:280 +#: contrib/comments/models.py:286 msgid "moderator deletion" msgstr "モデレータ削除" -#: contrib/comments/models.py:281 +#: contrib/comments/models.py:287 msgid "moderator deletions" msgstr "モデレータ削除" -#: contrib/comments/models.py:285 +#: contrib/comments/models.py:291 #, python-format msgid "Moderator deletion by %r" msgstr "%r によるモデレータ削除" @@ -1475,13 +1476,13 @@ msgstr "コメントをプレビュー" msgid "Your name:" msgstr "ユーザ名:" -#: contrib/comments/views/comments.py:27 +#: contrib/comments/views/comments.py:28 msgid "" "This rating is required because you've entered at least one other rating." msgstr "" "他のレーティングを入力した場合は、このレーティングは必ず入力してください。" -#: contrib/comments/views/comments.py:111 +#: contrib/comments/views/comments.py:112 #, python-format msgid "" "This comment was posted by a user who has posted fewer than %(count)s " @@ -1496,7 +1497,7 @@ msgid_plural "" msgstr[0] "このコメントを投稿したユーザのコメント数は %(count)s 未満です。" msgstr[1] "このコメントを投稿したユーザのコメント数は %(count)s 未満です。" -#: contrib/comments/views/comments.py:116 +#: contrib/comments/views/comments.py:117 #, python-format msgid "" "This comment was posted by a sketchy user:\n" @@ -1507,23 +1508,23 @@ msgstr "" "\n" "%(text)s" -#: contrib/comments/views/comments.py:188 -#: contrib/comments/views/comments.py:280 +#: contrib/comments/views/comments.py:189 +#: contrib/comments/views/comments.py:281 msgid "Only POSTs are allowed" msgstr "POST メソッドのみ有効です。" -#: contrib/comments/views/comments.py:192 -#: contrib/comments/views/comments.py:284 +#: contrib/comments/views/comments.py:193 +#: contrib/comments/views/comments.py:285 msgid "One or more of the required fields wasn't submitted" msgstr "必須項目がいくつか入力されていません。" -#: contrib/comments/views/comments.py:196 -#: contrib/comments/views/comments.py:286 +#: contrib/comments/views/comments.py:197 +#: contrib/comments/views/comments.py:287 msgid "Somebody tampered with the comment form (security violation)" msgstr "だれかがコメントフォームを改竄しています (セキュリティ侵害です)" -#: contrib/comments/views/comments.py:206 -#: contrib/comments/views/comments.py:292 +#: contrib/comments/views/comments.py:207 +#: contrib/comments/views/comments.py:293 msgid "" "The comment form had an invalid 'target' parameter -- the object ID was " "invalid" @@ -1531,32 +1532,32 @@ msgstr "" "コメントフォームの 'target' パラメータが不正です。 -- オブジェクト IDが不正な" "値でした" -#: contrib/comments/views/comments.py:257 -#: contrib/comments/views/comments.py:321 +#: contrib/comments/views/comments.py:258 +#: contrib/comments/views/comments.py:322 msgid "The comment form didn't provide either 'preview' or 'post'" msgstr "コメントの「プレビュー」「投稿」種別が不明です。" -#: contrib/comments/views/karma.py:19 +#: contrib/comments/views/karma.py:20 msgid "Anonymous users cannot vote" msgstr "非ログインユーザは投票できません。" -#: contrib/comments/views/karma.py:23 +#: contrib/comments/views/karma.py:24 msgid "Invalid comment ID" msgstr "コメント ID が不正です" -#: contrib/comments/views/karma.py:25 +#: contrib/comments/views/karma.py:26 msgid "No voting for yourself" msgstr "自分には投票できません。" -#: contrib/contenttypes/models.py:36 +#: contrib/contenttypes/models.py:37 msgid "python model class name" msgstr "Python モデルクラス名" -#: contrib/contenttypes/models.py:39 +#: contrib/contenttypes/models.py:40 msgid "content type" msgstr "コンテンツタイプ" -#: contrib/contenttypes/models.py:40 +#: contrib/contenttypes/models.py:41 msgid "content types" msgstr "コンテンツタイプ" @@ -1606,79 +1607,91 @@ msgstr "フラットページ" msgid "flat pages" msgstr "フラットページ" -#: contrib/humanize/templatetags/humanize.py:17 +#: contrib/humanize/templatetags/humanize.py:20 msgid "th" msgstr "番目" -#: contrib/humanize/templatetags/humanize.py:17 +#: contrib/humanize/templatetags/humanize.py:20 msgid "st" msgstr "番目" -#: contrib/humanize/templatetags/humanize.py:17 +#: contrib/humanize/templatetags/humanize.py:20 msgid "nd" msgstr "番目" -#: contrib/humanize/templatetags/humanize.py:17 +#: contrib/humanize/templatetags/humanize.py:20 msgid "rd" msgstr "番目" -#: contrib/humanize/templatetags/humanize.py:47 +#: contrib/humanize/templatetags/humanize.py:50 #, python-format msgid "%(value).1f million" msgid_plural "%(value).1f million" msgstr[0] "%(value).1f 百万" msgstr[1] "%(value).1f 百万" -#: contrib/humanize/templatetags/humanize.py:50 +#: contrib/humanize/templatetags/humanize.py:53 #, python-format msgid "%(value).1f billion" msgid_plural "%(value).1f billion" msgstr[0] "%(value).1f 十億" msgstr[1] "%(value).1f 十億" -#: contrib/humanize/templatetags/humanize.py:53 +#: contrib/humanize/templatetags/humanize.py:56 #, python-format msgid "%(value).1f trillion" msgid_plural "%(value).1f trillion" msgstr[0] "%(value).1f 兆" msgstr[1] "%(value).1f 兆" -#: contrib/humanize/templatetags/humanize.py:68 +#: contrib/humanize/templatetags/humanize.py:71 msgid "one" msgstr "1" -#: contrib/humanize/templatetags/humanize.py:68 +#: contrib/humanize/templatetags/humanize.py:71 msgid "two" msgstr "2" -#: contrib/humanize/templatetags/humanize.py:68 +#: contrib/humanize/templatetags/humanize.py:71 msgid "three" msgstr "3" -#: contrib/humanize/templatetags/humanize.py:68 +#: contrib/humanize/templatetags/humanize.py:71 msgid "four" msgstr "4" -#: contrib/humanize/templatetags/humanize.py:68 +#: contrib/humanize/templatetags/humanize.py:71 msgid "five" msgstr "5" -#: contrib/humanize/templatetags/humanize.py:68 +#: contrib/humanize/templatetags/humanize.py:71 msgid "six" msgstr "6" -#: contrib/humanize/templatetags/humanize.py:68 +#: contrib/humanize/templatetags/humanize.py:71 msgid "seven" msgstr "7" -#: contrib/humanize/templatetags/humanize.py:68 +#: contrib/humanize/templatetags/humanize.py:71 msgid "eight" msgstr "8" -#: contrib/humanize/templatetags/humanize.py:68 +#: contrib/humanize/templatetags/humanize.py:71 msgid "nine" msgstr "9" +#: contrib/humanize/templatetags/humanize.py:90 +msgid "today" +msgstr "今日" + +#: contrib/humanize/templatetags/humanize.py:92 +msgid "tomorrow" +msgstr "明日" + +#: contrib/humanize/templatetags/humanize.py:94 +msgid "yesterday" +msgstr "昨日" + #: contrib/localflavor/au/forms.py:18 msgid "Enter a 4 digit post code." msgstr "4桁でポストコードを入力してください。" @@ -1815,7 +1828,7 @@ msgstr "Zug" msgid "Zurich" msgstr "Zurich" -#: contrib/localflavor/ch/forms.py:18 contrib/localflavor/no/forms.py:15 +#: contrib/localflavor/ch/forms.py:18 contrib/localflavor/no/forms.py:14 msgid "Enter a zip code in the format XXXX." msgstr "XXXXの形式でZipコードを入力してください。" @@ -1823,13 +1836,15 @@ msgstr "XXXXの形式でZipコードを入力してください。" msgid "" "Enter a valid Swiss identity or passport card number in X1234567<0 or " "1234567890 format." -msgstr "スイス アイデンティティかパスポート番号を X1234567<0 か 1234567890 の形式で入力して下さい。" +msgstr "" +"スイス アイデンティティかパスポート番号を X1234567<0 か 1234567890 の形式で入" +"力して下さい。" -#: contrib/localflavor/cl/forms.py:21 +#: contrib/localflavor/cl/forms.py:32 msgid "Enter valid a Chilean RUT. The format is XX.XXX.XXX-X." msgstr "XX.XXX.XXX-Xの形式でチリ納税者番号を入力してください。" -#: contrib/localflavor/cl/forms.py:26 +#: contrib/localflavor/cl/forms.py:37 msgid "Enter valid a Chilean RUT" msgstr "正しいチリ納税者番号を入力してください。" @@ -1906,18 +1921,23 @@ msgstr "XXXXXの形式でZipコードを入力してください。" msgid "" "Enter a valid German identity card number in XXXXXXXXXXX-XXXXXXX-XXXXXXX-X " "format." -msgstr "XXXXXXXXXXX-XXXXXXX-XXXXXXX-X の形式でドイツIDカード番号を入力して下さい。" +msgstr "" +"XXXXXXXXXXX-XXXXXXX-XXXXXXX-X の形式でドイツIDカード番号を入力して下さい。" #: contrib/localflavor/fi/forms.py:40 contrib/localflavor/fi/forms.py:45 msgid "Enter a valid Finnish social security number." msgstr "フィンランド社会保証番号を正しく入力してください。" -#: contrib/localflavor/is_/forms.py:16 +#: contrib/localflavor/in_/forms.py:16 +msgid "Enter a zip code in the format XXXXXXX." +msgstr "XXXXXXXの形式でZipコードを入力してください。" + +#: contrib/localflavor/is_/forms.py:17 msgid "" "Enter a valid Icelandic identification number. The format is XXXXXX-XXXX." msgstr "XXXXXか、XXXXX-XXXXの形式でアイスランド納税者番号を入力してください。" -#: contrib/localflavor/is_/forms.py:30 +#: contrib/localflavor/is_/forms.py:31 msgid "The Icelandic identification number is not valid." msgstr "アイスランド納税者番号を正しく入力して下さい。" @@ -2125,10 +2145,443 @@ msgstr "鹿児島県" msgid "Okinawa" msgstr "沖縄県" -#: contrib/localflavor/no/forms.py:36 +#: contrib/localflavor/no/forms.py:35 msgid "Enter a valid Norwegian social security number." msgstr "ノルウェー社会保障番号を正しく入力してください。" +#: contrib/localflavor/pl/forms.py:53 +msgid "National Identification Number consists of 11 digits." +msgstr "国民識別番号は11文字で入力して下さい。" + +#: contrib/localflavor/pl/forms.py:59 +msgid "Wrong checksum for the National Identification Number." +msgstr "国民識別番号のチェックサムがあいません。" + +#: contrib/localflavor/pl/forms.py:71 +msgid "" +"Enter a tax number field (NIP) in the format XXX-XXX-XX-XX or XX-XX-XXX-XXX." +msgstr "XXXXXか、XXXXX-XXXXの形式で納税者欄(NIP)を入力してください。" + +#: contrib/localflavor/pl/forms.py:82 +msgid "Enter a postal code in the format XX-XXX." +msgstr "XX-XXXの形式で郵便番号を入力してください。" + +#: contrib/localflavor/pl/pl_voivodeships.py:8 +msgid "Lower Silesia" +msgstr "Lower Silesia" + +#: contrib/localflavor/pl/pl_voivodeships.py:9 +msgid "Kuyavia-Pomerania" +msgstr "Kuyavia-Pomerania" + +#: contrib/localflavor/pl/pl_voivodeships.py:10 +msgid "Lublin" +msgstr "Lublin" + +#: contrib/localflavor/pl/pl_voivodeships.py:11 +msgid "Lubusz" +msgstr "Lubusz" + +#: contrib/localflavor/pl/pl_voivodeships.py:12 +msgid "Lodz" +msgstr "Lodz" + +#: contrib/localflavor/pl/pl_voivodeships.py:13 +msgid "Lesser Poland" +msgstr "Lesser Poland" + +#: contrib/localflavor/pl/pl_voivodeships.py:14 +msgid "Masovia" +msgstr "Masovia" + +#: contrib/localflavor/pl/pl_voivodeships.py:15 +msgid "Opole" +msgstr "Opole" + +#: contrib/localflavor/pl/pl_voivodeships.py:16 +msgid "Subcarpatia" +msgstr "Subcarpatia" + +#: contrib/localflavor/pl/pl_voivodeships.py:17 +msgid "Podlasie" +msgstr "Podlasie" + +#: contrib/localflavor/pl/pl_voivodeships.py:18 +msgid "Pomerania" +msgstr "Pomerania" + +#: contrib/localflavor/pl/pl_voivodeships.py:19 +msgid "Silesia" +msgstr "Silesia" + +#: contrib/localflavor/pl/pl_voivodeships.py:20 +msgid "Swietokrzyskie" +msgstr "Swietokrzyskie" + +#: contrib/localflavor/pl/pl_voivodeships.py:21 +msgid "Warmia-Masuria" +msgstr "Warmia-Masuria" + +#: contrib/localflavor/pl/pl_voivodeships.py:22 +msgid "Greater Poland" +msgstr "Greater Poland" + +#: contrib/localflavor/pl/pl_voivodeships.py:23 +msgid "West Pomerania" +msgstr "West Pomerania" + +#: contrib/localflavor/sk/forms.py:32 +msgid "Enter a postal code in the format XXXXX or XXX XX." +msgstr "XXXXXか、XXX XXの形式で郵便番号を入力してください。" + +#: contrib/localflavor/sk/sk_districts.py:8 +msgid "Banska Bystrica" +msgstr "Banska Bystrica" + +#: contrib/localflavor/sk/sk_districts.py:9 +msgid "Banska Stiavnica" +msgstr "Banska Stiavnica" + +#: contrib/localflavor/sk/sk_districts.py:10 +msgid "Bardejov" +msgstr "Bardejov" + +#: contrib/localflavor/sk/sk_districts.py:11 +msgid "Banovce nad Bebravou" +msgstr "Banovce nad Bebravou" + +#: contrib/localflavor/sk/sk_districts.py:12 +msgid "Brezno" +msgstr "Brezno" + +#: contrib/localflavor/sk/sk_districts.py:13 +msgid "Bratislava I" +msgstr "Bratislava I" + +#: contrib/localflavor/sk/sk_districts.py:14 +msgid "Bratislava II" +msgstr "Bratislava II" + +#: contrib/localflavor/sk/sk_districts.py:15 +msgid "Bratislava III" +msgstr "Bratislava III" + +#: contrib/localflavor/sk/sk_districts.py:16 +msgid "Bratislava IV" +msgstr "Bratislava IV" + +#: contrib/localflavor/sk/sk_districts.py:17 +msgid "Bratislava V" +msgstr "Bratislava V" + +#: contrib/localflavor/sk/sk_districts.py:18 +msgid "Bytca" +msgstr "Bytca" + +#: contrib/localflavor/sk/sk_districts.py:19 +msgid "Cadca" +msgstr "Cadca" + +#: contrib/localflavor/sk/sk_districts.py:20 +msgid "Detva" +msgstr "Detva" + +#: contrib/localflavor/sk/sk_districts.py:21 +msgid "Dolny Kubin" +msgstr "Dolny Kubin" + +#: contrib/localflavor/sk/sk_districts.py:22 +msgid "Dunajska Streda" +msgstr "Dunajska Streda" + +#: contrib/localflavor/sk/sk_districts.py:23 +msgid "Galanta" +msgstr "Galanta" + +#: contrib/localflavor/sk/sk_districts.py:24 +msgid "Gelnica" +msgstr "Gelnica" + +#: contrib/localflavor/sk/sk_districts.py:25 +msgid "Hlohovec" +msgstr "Hlohovec" + +#: contrib/localflavor/sk/sk_districts.py:26 +msgid "Humenne" +msgstr "Humenne" + +#: contrib/localflavor/sk/sk_districts.py:27 +msgid "Ilava" +msgstr "Ilava" + +#: contrib/localflavor/sk/sk_districts.py:28 +msgid "Kezmarok" +msgstr "Kezmarok" + +#: contrib/localflavor/sk/sk_districts.py:29 +msgid "Komarno" +msgstr "Komarno" + +#: contrib/localflavor/sk/sk_districts.py:30 +msgid "Kosice I" +msgstr "Kosice I" + +#: contrib/localflavor/sk/sk_districts.py:31 +msgid "Kosice II" +msgstr "Kosice II" + +#: contrib/localflavor/sk/sk_districts.py:32 +msgid "Kosice III" +msgstr "Kosice III" + +#: contrib/localflavor/sk/sk_districts.py:33 +msgid "Kosice IV" +msgstr "Kosice IV" + +#: contrib/localflavor/sk/sk_districts.py:34 +msgid "Kosice - okolie" +msgstr "Kosice - okolie" + +#: contrib/localflavor/sk/sk_districts.py:35 +msgid "Krupina" +msgstr "Krupina" + +#: contrib/localflavor/sk/sk_districts.py:36 +msgid "Kysucke Nove Mesto" +msgstr "Kysucke Nove Mesto" + +#: contrib/localflavor/sk/sk_districts.py:37 +msgid "Levice" +msgstr "Levice" + +#: contrib/localflavor/sk/sk_districts.py:38 +msgid "Levoca" +msgstr "Levoca" + +#: contrib/localflavor/sk/sk_districts.py:39 +msgid "Liptovsky Mikulas" +msgstr "Liptovsky Mikulas" + +#: contrib/localflavor/sk/sk_districts.py:40 +msgid "Lucenec" +msgstr "Lucenec" + +#: contrib/localflavor/sk/sk_districts.py:41 +msgid "Malacky" +msgstr "Malacky" + +#: contrib/localflavor/sk/sk_districts.py:42 +msgid "Martin" +msgstr "Martin" + +#: contrib/localflavor/sk/sk_districts.py:43 +msgid "Medzilaborce" +msgstr "Medzilaborce" + +#: contrib/localflavor/sk/sk_districts.py:44 +msgid "Michalovce" +msgstr "Michalovce" + +#: contrib/localflavor/sk/sk_districts.py:45 +msgid "Myjava" +msgstr "Myjava" + +#: contrib/localflavor/sk/sk_districts.py:46 +msgid "Namestovo" +msgstr "Namestovo" + +#: contrib/localflavor/sk/sk_districts.py:47 +msgid "Nitra" +msgstr "Nitra" + +#: contrib/localflavor/sk/sk_districts.py:48 +msgid "Nove Mesto nad Vahom" +msgstr "Nove Mesto nad Vahom" + +#: contrib/localflavor/sk/sk_districts.py:49 +msgid "Nove Zamky" +msgstr "Nove Zamky" + +#: contrib/localflavor/sk/sk_districts.py:50 +msgid "Partizanske" +msgstr "Partizanske" + +#: contrib/localflavor/sk/sk_districts.py:51 +msgid "Pezinok" +msgstr "Pezinok" + +#: contrib/localflavor/sk/sk_districts.py:52 +msgid "Piestany" +msgstr "Piestany" + +#: contrib/localflavor/sk/sk_districts.py:53 +msgid "Poltar" +msgstr "Poltar" + +#: contrib/localflavor/sk/sk_districts.py:54 +msgid "Poprad" +msgstr "Poprad" + +#: contrib/localflavor/sk/sk_districts.py:55 +msgid "Povazska Bystrica" +msgstr "Povazska Bystrica" + +#: contrib/localflavor/sk/sk_districts.py:56 +msgid "Presov" +msgstr "Presov" + +#: contrib/localflavor/sk/sk_districts.py:57 +msgid "Prievidza" +msgstr "Prievidza" + +#: contrib/localflavor/sk/sk_districts.py:58 +msgid "Puchov" +msgstr "Puchov" + +#: contrib/localflavor/sk/sk_districts.py:59 +msgid "Revuca" +msgstr "Revuca" + +#: contrib/localflavor/sk/sk_districts.py:60 +msgid "Rimavska Sobota" +msgstr "Rimavska Sobota" + +#: contrib/localflavor/sk/sk_districts.py:61 +msgid "Roznava" +msgstr "Roznava" + +#: contrib/localflavor/sk/sk_districts.py:62 +msgid "Ruzomberok" +msgstr "Ruzomberok" + +#: contrib/localflavor/sk/sk_districts.py:63 +msgid "Sabinov" +msgstr "Sabinov" + +#: contrib/localflavor/sk/sk_districts.py:64 +msgid "Senec" +msgstr "Senec" + +#: contrib/localflavor/sk/sk_districts.py:65 +msgid "Senica" +msgstr "Senica" + +#: contrib/localflavor/sk/sk_districts.py:66 +msgid "Skalica" +msgstr "Skalica" + +#: contrib/localflavor/sk/sk_districts.py:67 +msgid "Snina" +msgstr "Snina" + +#: contrib/localflavor/sk/sk_districts.py:68 +msgid "Sobrance" +msgstr "Sobrance" + +#: contrib/localflavor/sk/sk_districts.py:69 +msgid "Spisska Nova Ves" +msgstr "Spisska Nova Ves" + +#: contrib/localflavor/sk/sk_districts.py:70 +msgid "Stara Lubovna" +msgstr "Stara Lubovna" + +#: contrib/localflavor/sk/sk_districts.py:71 +msgid "Stropkov" +msgstr "Stropkov" + +#: contrib/localflavor/sk/sk_districts.py:72 +msgid "Svidnik" +msgstr "Svidnik" + +#: contrib/localflavor/sk/sk_districts.py:73 +msgid "Sala" +msgstr "Sala" + +#: contrib/localflavor/sk/sk_districts.py:74 +msgid "Topolcany" +msgstr "Topolcany" + +#: contrib/localflavor/sk/sk_districts.py:75 +msgid "Trebisov" +msgstr "Trebisov" + +#: contrib/localflavor/sk/sk_districts.py:76 +msgid "Trencin" +msgstr "Trencin" + +#: contrib/localflavor/sk/sk_districts.py:77 +msgid "Trnava" +msgstr "Trnava" + +#: contrib/localflavor/sk/sk_districts.py:78 +msgid "Turcianske Teplice" +msgstr "Turcianske Teplice" + +#: contrib/localflavor/sk/sk_districts.py:79 +msgid "Tvrdosin" +msgstr "Tvrdosin" + +#: contrib/localflavor/sk/sk_districts.py:80 +msgid "Velky Krtis" +msgstr "Velky Krtis" + +#: contrib/localflavor/sk/sk_districts.py:81 +msgid "Vranov nad Toplou" +msgstr "Vranov nad Toplou" + +#: contrib/localflavor/sk/sk_districts.py:82 +msgid "Zlate Moravce" +msgstr "Zlate Moravce" + +#: contrib/localflavor/sk/sk_districts.py:83 +msgid "Zvolen" +msgstr "Zvolen" + +#: contrib/localflavor/sk/sk_districts.py:84 +msgid "Zarnovica" +msgstr "Zarnovica" + +#: contrib/localflavor/sk/sk_districts.py:85 +msgid "Ziar nad Hronom" +msgstr "Ziar nad Hronom" + +#: contrib/localflavor/sk/sk_districts.py:86 +msgid "Zilina" +msgstr "Zilina" + +#: contrib/localflavor/sk/sk_regions.py:8 +msgid "Banska Bystrica region" +msgstr "Banska Bystrica region" + +#: contrib/localflavor/sk/sk_regions.py:9 +msgid "Bratislava region" +msgstr "Bratislava region" + +#: contrib/localflavor/sk/sk_regions.py:10 +msgid "Kosice region" +msgstr "Kosice region" + +#: contrib/localflavor/sk/sk_regions.py:11 +msgid "Nitra region" +msgstr "Nitra region" + +#: contrib/localflavor/sk/sk_regions.py:12 +msgid "Presov region" +msgstr "Presov region" + +#: contrib/localflavor/sk/sk_regions.py:13 +msgid "Trencin region" +msgstr "Trencin region" + +#: contrib/localflavor/sk/sk_regions.py:14 +msgid "Trnava region" +msgstr "Trnava region" + +#: contrib/localflavor/sk/sk_regions.py:15 +msgid "Zilina region" +msgstr "Zilina region" + #: contrib/localflavor/uk/forms.py:18 msgid "Enter a postcode. A space is required between the two postcode parts." msgstr "" @@ -2191,108 +2644,109 @@ msgstr "セッション" msgid "sessions" msgstr "セッション" -#: contrib/sites/models.py:10 +#: contrib/sites/models.py:15 msgid "domain name" msgstr "ドメイン名" -#: contrib/sites/models.py:11 +#: contrib/sites/models.py:16 msgid "display name" msgstr "表示名" -#: contrib/sites/models.py:15 +#: contrib/sites/models.py:20 msgid "site" msgstr "サイト" -#: contrib/sites/models.py:16 +#: contrib/sites/models.py:21 msgid "sites" msgstr "サイト" -#: core/validators.py:65 +#: core/validators.py:71 msgid "This value must contain only letters, numbers and underscores." msgstr "半角の英数字およびアンダースコア以外は使用できません。" -#: core/validators.py:69 +#: core/validators.py:75 msgid "" "This value must contain only letters, numbers, underscores, dashes or " "slashes." msgstr "" "半角の英数字、アンダースコア、ダッシュ、スラッシュ以外は使用できません。" -#: core/validators.py:73 +#: core/validators.py:79 msgid "This value must contain only letters, numbers, underscores or hyphens." msgstr "半角の英数字、アンダースコア、ハイフン以外は使用できません。" -#: core/validators.py:77 +#: core/validators.py:83 msgid "Uppercase letters are not allowed here." msgstr "大文字はここでは使用できません。" -#: core/validators.py:81 +#: core/validators.py:87 msgid "Lowercase letters are not allowed here." msgstr "小文字はここでは使用できません。" -#: core/validators.py:88 +#: core/validators.py:94 msgid "Enter only digits separated by commas." msgstr "カンマ区切りの数字だけを入力してください。" -#: core/validators.py:100 +#: core/validators.py:106 msgid "Enter valid e-mail addresses separated by commas." msgstr "カンマ区切りの有効なメールアドレスを入力してください。" -#: core/validators.py:104 +#: core/validators.py:110 msgid "Please enter a valid IP address." msgstr "有効な IP アドレスを入力してください。" -#: core/validators.py:108 +#: core/validators.py:114 msgid "Empty values are not allowed here." msgstr "入力は必須です。" -#: core/validators.py:112 +#: core/validators.py:118 msgid "Non-numeric characters aren't allowed here." msgstr "数値以外は使用できません。" -#: core/validators.py:116 +#: core/validators.py:122 msgid "This value can't be comprised solely of digits." msgstr "数値だけの値にはできません。" -#: core/validators.py:121 newforms/fields.py:135 +#: core/validators.py:127 newforms/fields.py:142 msgid "Enter a whole number." msgstr "整数を入力してください。" -#: core/validators.py:125 +#: core/validators.py:131 msgid "Only alphabetical characters are allowed here." msgstr "半角アルファベット以外使用できません。" -#: core/validators.py:140 +#: core/validators.py:146 msgid "Year must be 1900 or later." msgstr "1900年以降を指定してください。" -#: core/validators.py:144 +#: core/validators.py:150 #, python-format msgid "Invalid date: %s" msgstr "無効な日付: %s" -#: core/validators.py:149 db/models/fields/__init__.py:468 +#: core/validators.py:155 db/models/fields/__init__.py:501 msgid "Enter a valid date in YYYY-MM-DD format." msgstr "YYYY-MM-DD形式で日付を入力してください。" -#: core/validators.py:154 +#: core/validators.py:160 msgid "Enter a valid time in HH:MM format." msgstr "HH:MM形式で時刻を入力してください。" -#: core/validators.py:158 db/models/fields/__init__.py:537 +#: core/validators.py:164 db/models/fields/__init__.py:570 msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format." msgstr "YYYY-MM-DD HH:MM形式で日時を入力してください。" -#: core/validators.py:163 newforms/fields.py:339 +#: core/validators.py:169 newforms/fields.py:336 msgid "Enter a valid e-mail address." msgstr "有効なメールアドレスを入力してください。" -#: core/validators.py:175 core/validators.py:453 oldforms/__init__.py:672 +#: core/validators.py:181 core/validators.py:461 newforms/fields.py:376 +#: oldforms/__init__.py:686 msgid "No file was submitted. Check the encoding type on the form." msgstr "" "ファイルが取得できませんでした。formのencoding typeを確認してください。" -#: core/validators.py:179 +#: core/validators.py:185 newforms/fields.py:397 msgid "" "Upload a valid image. The file you uploaded was either not an image or a " "corrupted image." @@ -2300,26 +2754,26 @@ msgstr "" "画像をアップロードしてください。アップロードした画像は画像でないか、または壊" "れています。" -#: core/validators.py:186 +#: core/validators.py:192 #, python-format msgid "The URL %s does not point to a valid image." msgstr "URL ( %s ) は画像ではありません。" -#: core/validators.py:190 +#: core/validators.py:196 #, python-format msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid." msgstr "電話番号は XXX-XXX-XXXX 形式で入力してください。\"%s\" は無効です。" -#: core/validators.py:198 +#: core/validators.py:204 #, python-format msgid "The URL %s does not point to a valid QuickTime video." msgstr "URL ( %s ) は QuickTime ビデオではありません。" -#: core/validators.py:202 +#: core/validators.py:208 msgid "A valid URL is required." msgstr "正しい URL を入力してください。" -#: core/validators.py:216 +#: core/validators.py:222 #, python-format msgid "" "Valid HTML is required. Specific errors are:\n" @@ -2328,86 +2782,86 @@ msgstr "" "有効な HTML を入力してください。エラー:\n" "%s" -#: core/validators.py:223 +#: core/validators.py:229 #, python-format msgid "Badly formed XML: %s" msgstr "不正な XML です: %s" -#: core/validators.py:240 +#: core/validators.py:246 #, python-format msgid "Invalid URL: %s" msgstr "無効なURL: %s" -#: core/validators.py:245 core/validators.py:247 +#: core/validators.py:251 core/validators.py:253 #, python-format msgid "The URL %s is a broken link." msgstr "URL ( %s ) はリンクが壊れています。" -#: core/validators.py:253 +#: core/validators.py:259 msgid "Enter a valid U.S. state abbreviation." msgstr "正しい米州略称を入力してください。" -#: core/validators.py:267 +#: core/validators.py:273 #, python-format msgid "Watch your mouth! The word %s is not allowed here." msgid_plural "Watch your mouth! The words %s are not allowed here." msgstr[0] "言葉使いに気を付けて! %s という言葉は使えません。" msgstr[1] "言葉使いに気を付けて! %s という言葉は使えません。" -#: core/validators.py:274 +#: core/validators.py:280 #, python-format msgid "This field must match the '%s' field." msgstr "このフィールドは '%s' フィールドと一致せねばなりません。" -#: core/validators.py:293 +#: core/validators.py:299 msgid "Please enter something for at least one field." msgstr "少なくとも一つのフィールドに何か入力してください。" -#: core/validators.py:302 core/validators.py:313 +#: core/validators.py:308 core/validators.py:319 msgid "Please enter both fields or leave them both empty." msgstr "両方のフィールドに入力するか、両方とも未入力にしてください。" -#: core/validators.py:321 +#: core/validators.py:327 #, python-format msgid "This field must be given if %(field)s is %(value)s" msgstr "" "%(field)s を %(value)s にするのなら、このフィールドに必ず入力してください。" -#: core/validators.py:334 +#: core/validators.py:340 #, python-format msgid "This field must be given if %(field)s is not %(value)s" msgstr "" "%(field)s を %(value)s にしないのなら、このフィールドに必ず入力してください。" -#: core/validators.py:353 +#: core/validators.py:359 msgid "Duplicate values are not allowed." msgstr "重複する値は認められません。" -#: core/validators.py:368 +#: core/validators.py:374 #, python-format msgid "This value must be between %(lower)s and %(upper)s." msgstr "この値は %(lower)s から %(upper)s の間でなければなりません。" -#: core/validators.py:370 +#: core/validators.py:376 #, python-format msgid "This value must be at least %s." msgstr "この値は %s 以上でなければなりません。" -#: core/validators.py:372 +#: core/validators.py:378 #, python-format msgid "This value must be no more than %s." msgstr "この値は %s より小さくなければなりません。" -#: core/validators.py:408 +#: core/validators.py:414 #, python-format msgid "This value must be a power of %s." msgstr "この値は %s の累乗でなければなりません。" -#: core/validators.py:417 +#: core/validators.py:424 msgid "Please enter a valid decimal number." msgstr "有効な 10 進数を入力してください。" -#: core/validators.py:423 +#: core/validators.py:431 #, python-format msgid "Please enter a valid decimal number with at most %s total digit." msgid_plural "" @@ -2415,7 +2869,7 @@ msgid_plural "" msgstr[0] "全体で %s 文字以下の数字を入力してください。" msgstr[1] "全体で %s 文字以下の数字を入力してください。" -#: core/validators.py:426 +#: core/validators.py:434 #, python-format msgid "" "Please enter a valid decimal number with a whole part of at most %s digit." @@ -2424,7 +2878,7 @@ msgid_plural "" msgstr[0] "整数部は %s 文字以下の数字を入力してください。" msgstr[1] "整数部は %s 文字以下の数字を入力してください。" -#: core/validators.py:429 +#: core/validators.py:437 #, python-format msgid "Please enter a valid decimal number with at most %s decimal place." msgid_plural "" @@ -2432,41 +2886,41 @@ msgid_plural "" msgstr[0] "小数部は %s 文字以下の数字を入力してください。" msgstr[1] "小数部は %s 文字以下の数字を入力してください。" -#: core/validators.py:437 +#: core/validators.py:445 msgid "Please enter a valid floating point number." msgstr "有効な 小数 を入力してください。" -#: core/validators.py:446 +#: core/validators.py:454 #, python-format msgid "Make sure your uploaded file is at least %s bytes big." msgstr "アップロードするファイルの大きさは %s バイト以上にしてください。" -#: core/validators.py:447 +#: core/validators.py:455 #, python-format msgid "Make sure your uploaded file is at most %s bytes big." msgstr "アップロードするファイルの大きさは %s 最大バイトまでです。" -#: core/validators.py:464 +#: core/validators.py:472 msgid "The format for this field is wrong." msgstr "フィールドの形式が正しくありません。" -#: core/validators.py:479 +#: core/validators.py:487 msgid "This field is invalid." msgstr "このフィールドは無効です。" -#: core/validators.py:515 +#: core/validators.py:523 #, python-format msgid "Could not retrieve anything from %s." msgstr "%s から何も検索できませんでした。" -#: core/validators.py:518 +#: core/validators.py:526 #, python-format msgid "" "The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'." msgstr "" "URL %(url)s は無効なコンテンツタイプヘッダ '%(contenttype)s' を返しました。" -#: core/validators.py:551 +#: core/validators.py:559 #, python-format msgid "" "Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with " @@ -2475,7 +2929,7 @@ msgstr "" "%(line)s 行目から始まる %(tag)s タグを閉じてください (\"%(start)s\" で始まる" "行です)。" -#: core/validators.py:555 +#: core/validators.py:563 #, python-format msgid "" "Some text starting on line %(line)s is not allowed in that context. (Line " @@ -2484,7 +2938,7 @@ msgstr "" "%(line)s 行目から始まるテキストはこのコンテキストでは使えません。 (\"%(start)" "s\" で始まる行です)。" -#: core/validators.py:560 +#: core/validators.py:568 #, python-format msgid "" "\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%" @@ -2493,7 +2947,7 @@ msgstr "" "%(line)s 行目の \"%(attr)s\" は無効なアトリビュートです (\"%(start)s\" で始ま" "る行です)。" -#: core/validators.py:565 +#: core/validators.py:573 #, python-format msgid "" "\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%" @@ -2502,7 +2956,7 @@ msgstr "" "%(line)s 行目の \"<%(tag)s>\" は無効なタグです( \"%(start)s\" で始まる行で" "す)。" -#: core/validators.py:569 +#: core/validators.py:577 #, python-format msgid "" "A tag on line %(line)s is missing one or more required attributes. (Line " @@ -2511,7 +2965,7 @@ msgstr "" "%(line)s 行目のタグは必須アトリビュートが未入力です( \"%(start)s\" で始まる行" "です)。" -#: core/validators.py:574 +#: core/validators.py:582 #, python-format msgid "" "The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line " @@ -2520,65 +2974,65 @@ msgstr "" "%(line)s 行目の \"%(attr)s\" アトリビュートの値が正しくありません (\"%(start)" "s\" で始まる行です) 。" -#: db/models/manipulators.py:307 +#: db/models/manipulators.py:309 #, python-format msgid "%(object)s with this %(type)s already exists for the given %(field)s." msgstr "" "%(field)s に入力されたものは、この %(type)s の %(object)s に既に存在します。" -#: db/models/fields/__init__.py:46 +#: db/models/fields/__init__.py:49 #, python-format msgid "%(optname)s with this %(fieldname)s already exists." msgstr "%(fieldname)s に %(optname)s は既に存在します。" -#: db/models/fields/__init__.py:126 db/models/fields/__init__.py:283 -#: db/models/fields/__init__.py:680 db/models/fields/__init__.py:691 -#: newforms/fields.py:87 newforms/fields.py:444 newforms/fields.py:522 -#: newforms/fields.py:533 newforms/models.py:185 oldforms/__init__.py:357 +#: db/models/fields/__init__.py:156 db/models/fields/__init__.py:313 +#: db/models/fields/__init__.py:721 db/models/fields/__init__.py:732 +#: newforms/fields.py:92 newforms/fields.py:490 newforms/fields.py:566 +#: newforms/fields.py:577 newforms/models.py:193 oldforms/__init__.py:373 msgid "This field is required." msgstr "このフィールドは必須です。" -#: db/models/fields/__init__.py:378 +#: db/models/fields/__init__.py:411 msgid "This value must be an integer." msgstr "値は整数でなければなりません。" -#: db/models/fields/__init__.py:413 +#: db/models/fields/__init__.py:446 msgid "This value must be either True or False." msgstr "値は真: True または偽: False でなければなりません。" -#: db/models/fields/__init__.py:434 +#: db/models/fields/__init__.py:467 msgid "This field cannot be null." msgstr "このフィールドには NULL を指定できません。" -#: db/models/fields/__init__.py:597 +#: db/models/fields/__init__.py:631 msgid "This value must be a decimal number." msgstr "値は整数でなければなりません。" -#: db/models/fields/__init__.py:700 +#: db/models/fields/__init__.py:741 msgid "Enter a valid filename." msgstr "正しいファイル名を入力してください。" -#: db/models/fields/__init__.py:824 +#: db/models/fields/__init__.py:883 msgid "This value must be either None, True or False." msgstr "値は、空: None、真: True または偽: False でなければなりません。" -#: db/models/fields/related.py:54 +#: db/models/fields/related.py:55 #, python-format msgid "Please enter a valid %s." msgstr "正しい %s を入力してください。" -#: db/models/fields/related.py:640 +#: db/models/fields/related.py:658 msgid "Separate multiple IDs with commas." msgstr "複数の ID はカンマで区切ってください。" -#: db/models/fields/related.py:642 +#: db/models/fields/related.py:660 msgid "" "Hold down \"Control\", or \"Command\" on a Mac, to select more than one." msgstr "" "複数選択するときには Control キーを押したまま選択してください。Mac は " "Command キーを使ってください" -#: db/models/fields/related.py:689 +#: db/models/fields/related.py:707 #, python-format msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid." msgid_plural "" @@ -2586,161 +3040,165 @@ msgid_plural "" msgstr[0] "正しい %(self)s IDを入力してください。 %(value)r は無効です。" msgstr[1] "正しい %(self)s IDを入力してください。 %(value)r は無効です。" -#: newforms/fields.py:110 newforms/fields.py:324 +#: newforms/fields.py:116 #, python-format -msgid "Ensure this value has at most %d characters." -msgstr "%d 字以下で入力してください。" +msgid "Ensure this value has at most %(max)d characters (it has %(length)d)." +msgstr "%(max)d 字以下で入力してください( %(length)d 文字入力されました)。" -#: newforms/fields.py:112 newforms/fields.py:326 +#: newforms/fields.py:118 #, python-format -msgid "Ensure this value has at least %d characters." -msgstr "%d 字以上で入力してください。" +msgid "Ensure this value has at least %(min)d characters (it has %(length)d)." +msgstr "%(min)d 字以上で入力してください。( %(length)d 文字入力されました)。" -#: newforms/fields.py:137 newforms/fields.py:160 newforms/fields.py:192 +#: newforms/fields.py:144 newforms/fields.py:167 newforms/fields.py:197 #, python-format msgid "Ensure this value is less than or equal to %s." msgstr "この値は %s 以下でなければなりません。" -#: newforms/fields.py:139 newforms/fields.py:162 newforms/fields.py:194 +#: newforms/fields.py:146 newforms/fields.py:169 newforms/fields.py:199 #, python-format msgid "Ensure this value is greater than or equal to %s." msgstr "この値は %s 以上でなければなりません。" -#: newforms/fields.py:158 newforms/fields.py:186 +#: newforms/fields.py:165 newforms/fields.py:192 msgid "Enter a number." msgstr "整数を入力してください。" -#: newforms/fields.py:196 +#: newforms/fields.py:201 #, python-format msgid "Ensure that there are no more than %s digits in total." msgstr "整数部と少数部を併せて %s 桁までで入力して下さい。" -#: newforms/fields.py:198 +#: newforms/fields.py:203 #, python-format msgid "Ensure that there are no more than %s decimal places." msgstr "少数部は %s 桁までで入力して下さい。" -#: newforms/fields.py:200 +#: newforms/fields.py:205 #, python-format msgid "Ensure that there are no more than %s digits before the decimal point." msgstr "整数部は %s 桁までで入力して下さい。" -#: newforms/fields.py:233 newforms/fields.py:566 +#: newforms/fields.py:238 newforms/fields.py:610 msgid "Enter a valid date." msgstr "日付を正しく入力してください。" -#: newforms/fields.py:260 newforms/fields.py:568 +#: newforms/fields.py:265 newforms/fields.py:612 msgid "Enter a valid time." msgstr "時間を正しく入力してください。" -#: newforms/fields.py:296 +#: newforms/fields.py:301 msgid "Enter a valid date/time." msgstr "日付/時間を正しく入力してください。" -#: newforms/fields.py:310 +#: newforms/fields.py:314 msgid "Enter a valid value." msgstr "値を正しく入力してください。" -#: newforms/fields.py:357 newforms/fields.py:379 +#: newforms/fields.py:378 +msgid "No file was submitted." +msgstr "ファイルが送信されていません。" + +#: newforms/fields.py:380 oldforms/__init__.py:688 +msgid "The submitted file is empty." +msgstr "入力されたファイルは空です。" + +#: newforms/fields.py:403 newforms/fields.py:425 msgid "Enter a valid URL." msgstr "URLを正しく入力してください。" -#: newforms/fields.py:381 +#: newforms/fields.py:427 msgid "This URL appears to be a broken link." msgstr "このURLはリンクが壊れています。" -#: newforms/fields.py:432 newforms/models.py:172 +#: newforms/fields.py:478 newforms/models.py:180 msgid "Select a valid choice. That choice is not one of the available choices." msgstr "正しく選択してください。選択したものは候補にありません。" -#: newforms/fields.py:448 newforms/fields.py:526 newforms/models.py:189 +#: newforms/fields.py:494 newforms/fields.py:570 newforms/models.py:197 msgid "Enter a list of values." msgstr "リストを入力してください。" -#: newforms/fields.py:457 newforms/models.py:195 +#: newforms/fields.py:500 newforms/models.py:203 #, python-format msgid "Select a valid choice. %s is not one of the available choices." msgstr "正しく選択してください。 %s は候補にありません。" -#: oldforms/__init__.py:392 +#: oldforms/__init__.py:408 #, python-format msgid "Ensure your text is less than %s character." msgid_plural "Ensure your text is less than %s characters." msgstr[0] "%s 字以下で入力してください。" msgstr[1] "%s 字以下で入力してください。" -#: oldforms/__init__.py:397 +#: oldforms/__init__.py:413 msgid "Line breaks are not allowed here." msgstr "改行はできません。" -#: oldforms/__init__.py:498 oldforms/__init__.py:571 oldforms/__init__.py:610 +#: oldforms/__init__.py:511 oldforms/__init__.py:585 oldforms/__init__.py:624 #, python-format msgid "Select a valid choice; '%(data)s' is not in %(choices)s." msgstr "正しく選択してください。; '%(data)s' は %(choices)s にありません。" -#: oldforms/__init__.py:674 -msgid "The submitted file is empty." -msgstr "入力されたファイルは空です。" - -#: oldforms/__init__.py:730 +#: oldforms/__init__.py:744 msgid "Enter a whole number between -32,768 and 32,767." msgstr "-32,768 から 32,767 までの整数を入力してください。" -#: oldforms/__init__.py:740 +#: oldforms/__init__.py:754 msgid "Enter a positive number." msgstr "正の数を入力してください。" -#: oldforms/__init__.py:750 +#: oldforms/__init__.py:764 msgid "Enter a whole number between 0 and 32,767." msgstr "0 から 32,767 までの整数を入力してください。" -#: template/defaultfilters.py:491 +#: template/defaultfilters.py:532 msgid "yes,no,maybe" msgstr "はい,いいえ,たぶん" -#: template/defaultfilters.py:520 +#: template/defaultfilters.py:561 #, python-format msgid "%(size)d byte" msgid_plural "%(size)d bytes" msgstr[0] "%(size)d byte" msgstr[1] "%(size)d bytes" -#: template/defaultfilters.py:522 +#: template/defaultfilters.py:563 #, python-format msgid "%.1f KB" msgstr "%.1f KB" -#: template/defaultfilters.py:524 +#: template/defaultfilters.py:565 #, python-format msgid "%.1f MB" msgstr "%.1f MB" -#: template/defaultfilters.py:525 +#: template/defaultfilters.py:566 #, python-format msgid "%.1f GB" msgstr "%.1f GB" -#: utils/dateformat.py:40 +#: utils/dateformat.py:41 msgid "p.m." msgstr "p.m." -#: utils/dateformat.py:41 +#: utils/dateformat.py:42 msgid "a.m." msgstr "a.m." -#: utils/dateformat.py:46 +#: utils/dateformat.py:47 msgid "PM" msgstr "PM" -#: utils/dateformat.py:47 +#: utils/dateformat.py:48 msgid "AM" msgstr "AM" -#: utils/dateformat.py:95 +#: utils/dateformat.py:97 msgid "midnight" msgstr "0時" -#: utils/dateformat.py:97 +#: utils/dateformat.py:99 msgid "noon" msgstr "12時" @@ -2772,130 +3230,162 @@ msgstr "土曜日" msgid "Sunday" msgstr "日曜日" -#: utils/dates.py:14 +#: utils/dates.py:10 +msgid "Mon" +msgstr "月" + +#: utils/dates.py:10 +msgid "Tue" +msgstr "火" + +#: utils/dates.py:10 +msgid "Wed" +msgstr "水" + +#: utils/dates.py:10 +msgid "Thu" +msgstr "木" + +#: utils/dates.py:10 +msgid "Fri" +msgstr "金" + +#: utils/dates.py:11 +msgid "Sat" +msgstr "土" + +#: utils/dates.py:11 +msgid "Sun" +msgstr "日" + +#: utils/dates.py:18 msgid "January" msgstr "1月" -#: utils/dates.py:14 +#: utils/dates.py:18 msgid "February" msgstr "2月" -#: utils/dates.py:14 utils/dates.py:27 +#: utils/dates.py:18 utils/dates.py:31 msgid "March" msgstr "3月" -#: utils/dates.py:14 utils/dates.py:27 +#: utils/dates.py:18 utils/dates.py:31 msgid "April" msgstr "4月" -#: utils/dates.py:14 utils/dates.py:27 +#: utils/dates.py:18 utils/dates.py:31 msgid "May" msgstr "5月" -#: utils/dates.py:14 utils/dates.py:27 +#: utils/dates.py:18 utils/dates.py:31 msgid "June" msgstr "6月" -#: utils/dates.py:15 utils/dates.py:27 +#: utils/dates.py:19 utils/dates.py:31 msgid "July" msgstr "7月" -#: utils/dates.py:15 +#: utils/dates.py:19 msgid "August" msgstr "8月" -#: utils/dates.py:15 +#: utils/dates.py:19 msgid "September" msgstr "9月" -#: utils/dates.py:15 +#: utils/dates.py:19 msgid "October" msgstr "10月" -#: utils/dates.py:15 +#: utils/dates.py:19 msgid "November" msgstr "11月" -#: utils/dates.py:16 +#: utils/dates.py:20 msgid "December" msgstr "12月" -#: utils/dates.py:19 +#: utils/dates.py:23 msgid "jan" msgstr "1月" -#: utils/dates.py:19 +#: utils/dates.py:23 msgid "feb" msgstr "2月" -#: utils/dates.py:19 +#: utils/dates.py:23 msgid "mar" msgstr "3月" -#: utils/dates.py:19 +#: utils/dates.py:23 msgid "apr" msgstr "4月" -#: utils/dates.py:19 +#: utils/dates.py:23 msgid "may" msgstr "5月" -#: utils/dates.py:19 +#: utils/dates.py:23 msgid "jun" msgstr "6月" -#: utils/dates.py:20 +#: utils/dates.py:24 msgid "jul" msgstr "7月" -#: utils/dates.py:20 +#: utils/dates.py:24 msgid "aug" msgstr "8月" -#: utils/dates.py:20 +#: utils/dates.py:24 msgid "sep" msgstr "9月" -#: utils/dates.py:20 +#: utils/dates.py:24 msgid "oct" msgstr "10月" -#: utils/dates.py:20 +#: utils/dates.py:24 msgid "nov" msgstr "11月" -#: utils/dates.py:20 +#: utils/dates.py:24 msgid "dec" msgstr "12月" -#: utils/dates.py:27 +#: utils/dates.py:31 msgid "Jan." msgstr "1月" -#: utils/dates.py:27 +#: utils/dates.py:31 msgid "Feb." msgstr "2月" -#: utils/dates.py:28 +#: utils/dates.py:32 msgid "Aug." msgstr "8月" -#: utils/dates.py:28 +#: utils/dates.py:32 msgid "Sept." msgstr "9月" -#: utils/dates.py:28 +#: utils/dates.py:32 msgid "Oct." msgstr "10月" -#: utils/dates.py:28 +#: utils/dates.py:32 msgid "Nov." msgstr "11月" -#: utils/dates.py:28 +#: utils/dates.py:32 msgid "Dec." msgstr "12月" +#: utils/text.py:127 +msgid "or" +msgstr "または" + #: utils/timesince.py:12 msgid "year" msgid_plural "years" @@ -2932,38 +3422,33 @@ msgid_plural "minutes" msgstr[0] "分" msgstr[1] "分" -#: utils/timesince.py:40 -#, python-format -msgid "%d milliseconds" -msgstr "%d ミリ秒" - -#: utils/timesince.py:41 +#: utils/timesince.py:39 #, python-format msgid "%(number)d %(type)s" msgstr "%(number)d %(type)s" -#: utils/timesince.py:47 +#: utils/timesince.py:45 #, python-format msgid ", %(number)d %(type)s" msgstr ", %(number)d %(type)s" -#: utils/translation/trans_real.py:358 +#: utils/translation/trans_real.py:391 msgid "DATE_FORMAT" msgstr "Y/m/d" -#: utils/translation/trans_real.py:359 +#: utils/translation/trans_real.py:392 msgid "DATETIME_FORMAT" msgstr "Y/m/d H:i" -#: utils/translation/trans_real.py:360 +#: utils/translation/trans_real.py:393 msgid "TIME_FORMAT" msgstr "H:i" -#: utils/translation/trans_real.py:376 +#: utils/translation/trans_real.py:409 msgid "YEAR_MONTH_FORMAT" msgstr "Y/m/d" -#: utils/translation/trans_real.py:377 +#: utils/translation/trans_real.py:410 msgid "MONTH_DAY_FORMAT" msgstr "m/d" diff --git a/django/conf/locale/km/LC_MESSAGES/django.mo b/django/conf/locale/km/LC_MESSAGES/django.mo Binary files differnew file mode 100644 index 0000000000..cd42e6a5f9 --- /dev/null +++ b/django/conf/locale/km/LC_MESSAGES/django.mo diff --git a/django/conf/locale/km/LC_MESSAGES/django.po b/django/conf/locale/km/LC_MESSAGES/django.po new file mode 100644 index 0000000000..5592c4a2a1 --- /dev/null +++ b/django/conf/locale/km/LC_MESSAGES/django.po @@ -0,0 +1,2508 @@ +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: 01\n" +"Report-Msgid-Bugs-To: sengtha@e-khmer.com\n" +"POT-Creation-Date: 2007-01-15 15:43+0200\n" +"PO-Revision-Date: 2007-08-10 00:21+0900\n" +"Last-Translator: Chay Sengtha <sengtha@e-khmer.com>\n" +"Language-Team: Chay Sengtha <sengtha@e-khmer.com>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: Information +msgid "Administration Page" +msgstr "ទំព័រគ្រប់គ្រង" + +msgid "Tag" +msgstr "ប្រភេទ" + +msgid "Headline" +msgstr "ចំណងជើង" + +msgid "Article" +msgstr "អត្ថបទ" + +msgid "Review" +msgstr "ព្រឹត្តិការណ៍ និង ផលិតផលថ្មីៗ" + +msgid "Keyword" +msgstr "ពាក្យសំខាន់ៗ" + +msgid "Advertisement" +msgstr "ការផ្សាយពាណិជ្ជកម្ម" + +msgid "Link" +msgstr "អត្ថបទភ្ជាប់" + +msgid "Accounting" +msgstr "គណនី" + +msgid "Name" +msgstr "ឈ្មោះ" + +msgid "Slug" +msgstr "ឈ្មោះជាអក្សរឡាតាំង" + +msgid "Created" +msgstr "កាលបរិច្ឆេទនៃការសរសេរ" + +msgid "Modified" +msgstr "កាលបរិច្ឆេទនៃការផ្លាស់ប្តូរ" + +msgid "Summary" +msgstr "អត្ថបទសង្ខេប" + +msgid "Viewed number" +msgstr "ចំនួនអាន" + +msgid "Site" +msgstr "គេហទំព័រ" + +msgid "Rate" +msgstr "ការវាយតំលៃ" + +msgid "Private" +msgstr "សំរាប់សមាជិកបង់លុយ" + +msgid "Public" +msgstr "ផ្សព្វផ្សាយ" + +msgid "Content" +msgstr "អត្ថបទ" + +msgid "Page" +msgstr "ទំព័រទី" + +msgid "Attach Image" +msgstr "រូបភាព" + +msgid "Ads type" +msgstr "ប្រភេទពាណិជ្ជកម្ម" + +msgid "Link type" +msgstr "ប្រភេទអត្ថបទភ្ជាប់" + +msgid "Account type" +msgstr "ប្រភេទគណនី" + +msgid "Amount" +msgstr "ចំនួន" + +msgid "Person" +msgstr "អ្នកទទួលខុសត្រូវ" + +msgid "Date" +msgstr "កាលបរិច្ឆេទ" + +msgid "Information" +msgstr "ការគ្រប់គ្រងព័ត៌មាន" + +msgid "Auth" +msgstr "ការគ្រប់គ្រងសមាជិក" + +msgid "Comments" +msgstr "ការគ្រប់គ្រងមតិយោបល់" + +msgid "Sites" +msgstr "ការគ្រប់គ្រងដមែន" + +msgid "Flatpages" +msgstr "ការគ្រប់គ្រងទំព័រថ្មី" + +msgid "File-Browser" +msgstr "ការគ្រប់គ្រងឯកសារ" + +msgid "Make Directory" +msgstr "បង្កើតថតថ្មី" + +msgid "Multiple Upload" +msgstr "ទាញយកឯកសារ" + +msgid "results" +msgstr "លទ្ធផល" + +msgid "total" +msgstr "សរុប" + +msgid "Total" +msgstr "សរុប" + +msgid "type" +msgstr "ប្រភេទ" + +msgid "filename" +msgstr "ឈ្មោះឯកសារ" + +msgid "size" +msgstr "ទំហំ" + +msgid "Past 30 days" +msgstr "៣០ថ្ងៃកន្លងមក" + +msgid "By Date" +msgstr "តាមកាលបរិច្ឆេទ" + +msgid "By Type" +msgstr "តាមប្រភេទ" + +msgid "no entries found" +msgstr "រកមិនឃើញ" + +msgid "Select files to upload" +msgstr "សូមជ្រើសរើសឯកសារ។" + +msgid "At least one file must be chosen." +msgstr "សូមជ្រើសរើសឯកសារយ៉ាងតិច១។" + +msgid "Wrong filetype for" +msgstr "ប្រភេទឯកសារដែលមិនអាចទាញយកបាន។" + +msgid "File already exists" +msgstr "ឯកសារនេះមានរួចហើយ។" + +msgid "File" +msgstr "ឯកសារ" + +msgid " is existed." +msgstr "ត្រូវបានគេយករួចហើយ។" + +msgid "Account registration is not complete yet.<br/>You need to activate your account first.<br/>We have already sent you the activate URL. Please check you mail box." +msgstr "ការចុះឈ្មោះមិនទាន់ចប់នៅឡើយទេ។ <br/>យើងខ្ញុំបានបញ្ជូនអ៊ីមែលទៅកាន់អាស័យដ្ឋានអ៊ីមែលរបស់លោកអ្នកហើយ សូមចុចអត្ថបទភ្ជាប់នៅក្នុងអ៊ីមែល ដើម្បីបញ្ជប់ការចុះឈ្មោះ។" + +msgid "Help" +msgstr "ជំនួយ" + +msgid "Max. Filesize" +msgstr "ទំហំឯកសារអតិបរិមា" + +msgid "Upload" +msgstr "ទាញយក" + +msgid "Folder" +msgstr "ថត" + +msgid "Video" +msgstr "វីដេអូ" + +msgid "Document" +msgstr "ឯកសារ" + +msgid "Sound" +msgstr "សំលេង" + +msgid "Code" +msgstr "កូត" + +msgid "Allowed" +msgstr "ប្រភេទឯកសារដែលអាចទាញយកបាន" + +msgid "Directory already exists." +msgstr "ថតនេះមានរួចហើយ។" + +msgid "Permission denied." +msgstr "ពុំមានសិទ្ធិអាចបង្កើតបាន។" + +msgid "Please correct the errors below." +msgstr "សូមកែកំហុសដូចខាងក្រោម។" + +msgid "Only letters, numbers and underscores are allowed." +msgstr "ត្រូវបំពេញតែអក្សរឡាតាំង ចំនួនលេខ និង សញ្ញា _ ។" + +msgid "The directory will automatically be converted to lowercase" +msgstr "ឈ្មោះថតនឹងត្រូវផ្លាស់ប្តូរទៅជាអក្សរតូចដោយស្វ័យប្រវត្ត។" + +msgid "Create" +msgstr "បង្កើត" + +msgid "date" +msgstr "កាលបរិច្ឆេទ" + +msgid "Dbtemplate" +msgstr "ការគ្រប់គ្រងឯកសារគំរូ" + +msgid "template" +msgstr "ឯកសារគំរូ" + +msgid "templates" +msgstr "ឯកសារគំរូ" + +msgid "Comment" +msgstr "ផ្សេងៗ" + +msgid "Income" +msgstr "ចំណូល" + +msgid "Expense" +msgstr "ចំណាយ" + +msgid "Image" +msgstr "រូបភាព" + +msgid "Text and Image" +msgstr "អក្សរ និង រូបភាព" + +msgid "New Headlines" +msgstr "អត្ថបទថ្មីៗ" + +msgid "New Reviews" +msgstr "ព្រឹត្តិការណ៍ និង ផលិតផលថ្មីៗ" + +msgid "Login" +msgstr "ពិនិត្យចូល" + +msgid "Logout" +msgstr "ចាកចេញ" + +msgid "Register" +msgstr "ចូលជាសមាជិក" + +msgid "Free" +msgstr "ឥតគិតថ្លៃ" + +msgid "Welcome" +msgstr "សូមស្វាគមន័ " + +msgid "IT Resources" +msgstr "ប្រភពព័ត៌មានអំពី បច្ចេកទេសព័ត៌មានវិទ្យា" + +msgid "Copyrights" +msgstr "រក្សាសិទ្ធិដោយ " + +msgid "Next page" +msgstr "ទំព័របន្ទាប់" + +msgid "Previous page" +msgstr "ទំព័រមុន " + +msgid "Wrong number or password. Please try it again." +msgstr "ឈ្មោះជាសមាជិក ឬ ពាក្យសំងាត់ មិនត្រឹមត្រូវ។ សូមសាកល្បងម្តងទៀត។ " + +msgid "This username has not activated yet." +msgstr "ឈ្មោះសាមាជិកនេះមិនទាន់ត្រូវបានគេអនុញ្ញាតនៅឡើយទេ។" + +msgid "Please write" +msgstr "សូមបំពេញ" + +msgid "More" +msgstr "អត្ថបទផ្សេងទៀត" + +msgid "Please correct below errors." +msgstr "សូកកែកូមហុសខាងក្រោម។" + +msgid "Thank for your comment." +msgstr "សូមអរគុណដែលបានបញ្ជេញមតិយោបល់ទាក់ទងនឹងអត្ថបទនេះ" + +#: Django standard +#: contrib/comments/models.py:67 +#: contrib/comments/models.py:166 +msgid "object ID" +msgstr "លេខសំគាល់កម្មវិធី" + +#: contrib/comments/models.py:68 +msgid "headline" +msgstr "ចំណងជើង" + +#: contrib/comments/models.py:69 +#: contrib/comments/models.py:90 +#: contrib/comments/models.py:167 +msgid "comment" +msgstr "មតិយោបល់" + +#: contrib/comments/models.py:70 +msgid "rating #1" +msgstr "វាយតំលៃ #1" + +#: contrib/comments/models.py:71 +msgid "rating #2" +msgstr "វាយតំលៃ #2" + +#: contrib/comments/models.py:72 +msgid "rating #3" +msgstr "វាយតំលៃ #3" + +#: contrib/comments/models.py:73 +msgid "rating #4" +msgstr "វាយតំលៃ #4" + +#: contrib/comments/models.py:74 +msgid "rating #5" +msgstr "វាយតំលៃ #5" + +#: contrib/comments/models.py:75 +msgid "rating #6" +msgstr "វាយតំលៃ #6" + +#: contrib/comments/models.py:76 +msgid "rating #7" +msgstr "វាយតំលៃ #7" + +#: contrib/comments/models.py:77 +msgid "rating #8" +msgstr "វាយតំលៃ #8" + +#: contrib/comments/models.py:82 +msgid "is valid rating" +msgstr "កំពុងត្រួតពិនិត្យចំពោះការវាយតំលៃ" + +#: contrib/comments/models.py:83 +#: contrib/comments/models.py:169 +msgid "date/time submitted" +msgstr "កាលបរិច្ឆេទនៃការសរសេរ" + +#: contrib/comments/models.py:84 +#: contrib/comments/models.py:170 +msgid "is public" +msgstr "ផ្សព្វផ្សាយជាសធារណៈ" + +#: contrib/comments/models.py:85 +#: contrib/admin/views/doc.py:304 +msgid "IP address" +msgstr "លេខ IP" + +#: contrib/comments/models.py:86 +msgid "is removed" +msgstr "ត្រូវបានលប់ចេញ" + +#: contrib/comments/models.py:86 +msgid "Check this box if the comment is inappropriate. A \"This comment has been removed\" message will be displayed instead." +msgstr "សូមចុចជ្រើសរើសយកប្រអប់នេះ ប្រសិនបើមតិយោបល់មិនសមរម្យ។ ឃ្លា \" មតិយោបល់នេះត្រូវបានគេលប់\" នឹងត្រូវបង្ហាញជំនួសវិញ។" + +#: contrib/comments/models.py:91 +msgid "comments" +msgstr "មតិយោបល់" + +#: contrib/comments/models.py:131 +#: contrib/comments/models.py:207 +msgid "Content object" +msgstr "អត្ថន័យរបស់កម្មវិធី" + +#: contrib/comments/models.py:159 +#: python-format +msgid "" +"Posted by %(user)s at %(date)s\n" +"\n" +"%(comment)s\n" +"\n" +"http://%(domain)s%(url)s" +msgstr "" +"សរសេរដោយ %(user)s នៅថ្ងៃ %(date)s\n" +"\n" +"%(comment)s\n" +"\n" +"http://%(domain)s%(url)s" + +#: contrib/comments/models.py:168 +msgid "person's name" +msgstr "ឈ្មោះ" + +#: contrib/comments/models.py:171 +msgid "ip address" +msgstr "លេខ ip" + +#: contrib/comments/models.py:173 +msgid "approved by staff" +msgstr "យល់ព្រមដោយបុគ្គលិក" + +#: contrib/comments/models.py:176 +msgid "free comment" +msgstr "មតិយោបល់(មិនចាំបាច់សមាជិក)" + +#: contrib/comments/models.py:177 +msgid "free comments" +msgstr "មតិយោបល់(មិនចាំបាច់សមាជិក)" + +#: contrib/comments/models.py:233 +msgid "score" +msgstr "ពិន្ទុ" + +#: contrib/comments/models.py:234 +msgid "score date" +msgstr "កាលបរិច្ឆេទដាក់ពិន្ទុ" + +#: contrib/comments/models.py:237 +msgid "karma score" +msgstr "ពិន្ទុកម្មា(karma)" + +#: contrib/comments/models.py:238 +msgid "karma scores" +msgstr "ពិន្ទុកម្មា(karma)" + +#: contrib/comments/models.py:242 +#, python-format +msgid "%(score)d rating by %(user)s" +msgstr "%(score)d វាយតំលៃដោយ %(user)s" + +#: contrib/comments/models.py:258 +#, python-format +msgid "" +"This comment was flagged by %(user)s:\n" +"\n" +"%(text)s" +msgstr "" +"មតិយោបល់នេះត្រូវបានកត់សំគាល់ទុកដោយ %(user)s:\n" +"\n" +"%(text)s" + +#: contrib/comments/models.py:265 +msgid "flag date" +msgstr "កាលបរិច្ឆេទកត់សំគាល់ទុក" + +#: contrib/comments/models.py:268 +msgid "user flag" +msgstr "ការកត់សំគាល់ទុក" + +#: contrib/comments/models.py:269 +msgid "user flags" +msgstr "ការកត់សំគាល់ទុក" + +#: contrib/comments/models.py:273 +#, python-format +msgid "Flag by %r" +msgstr "កត់សំគាល់ទុកដោយ %r" + +#: contrib/comments/models.py:278 +msgid "deletion date" +msgstr "កាលបរិច្ឆេទនៃការលប់" + +#: contrib/comments/models.py:280 +msgid "moderator deletion" +msgstr "ការលប់ដោយអ្នកគ្រប់គ្រង" + +#: contrib/comments/models.py:281 +msgid "moderator deletions" +msgstr "ការលប់ដោយអ្នកគ្រប់គ្រង" + +#: contrib/comments/models.py:285 +#, python-format +msgid "Moderator deletion by %r" +msgstr "ការលប់ដោយអ្នកគ្រប់គ្រង នៅ %r" + +#: contrib/comments/views/karma.py:19 +msgid "Anonymous users cannot vote" +msgstr "ជនអនាមិកមិនអាចបោះឆ្នោតបានទេ" + +#: contrib/comments/views/karma.py:23 +msgid "Invalid comment ID" +msgstr "លេខសំគាល់មតិយោបល់មិនត្រឹមត្រូវ" + +#: contrib/comments/views/karma.py:25 +msgid "No voting for yourself" +msgstr "មិនអាចបោះឆ្នោតអោយខ្លួនឯងបានទេ" + +#: contrib/comments/views/comments.py:27 +msgid "This rating is required because you've entered at least one other rating." +msgstr "ចាំបាច់ត្រូវការ វាយតំលៃ ពីព្រោះលោកអ្នកបានជ្រើសរើសធ្វើការវាយតំលៃផ្សេងពីនេះ។" + +#: contrib/comments/views/comments.py:111 +#, python-format +msgid "" +"This comment was posted by a user who has posted fewer than %(count)s comment:\n" +"\n" +"%(text)s" +msgid_plural "" +"This comment was posted by a user who has posted fewer than %(count)s comments:\n" +"\n" +"%(text)s" +msgstr[0] "" +"មតិយោបល់នេះត្រូវបានបញ្ជូនដោយសមាជិកម្នាក់ដែលបានផ្តល់មតិយោបល់តិចជាង %(count)s។\n" +"%(text)s" +msgstr[1] "" +"មតិយោបល់នេះត្រូវបានសរសេរដោយសមាជិកម្នាក់ដែលបានផ្តល់មតិយោបល់តិចជាង %(count)s។\n" +"%(text)s" + +#: contrib/comments/views/comments.py:116 +#, python-format +msgid "" +"This comment was posted by a sketchy user:\n" +"\n" +"%(text)s" +msgstr "" +"មតិយោបល់បានសរសេរដោយសមាជិកមិនសូវប្រាកដប្រជា:\n" +"\n" +"%(text)s" + +#: contrib/comments/views/comments.py:188 +#: contrib/comments/views/comments.py:280 +msgid "Only POSTs are allowed" +msgstr "អនុញ្ញាតតែទិន្នន័យតាមរយះ POST ។" + +#: contrib/comments/views/comments.py:192 +#: contrib/comments/views/comments.py:284 +msgid "One or more of the required fields wasn't submitted" +msgstr "ទិន្នន័យរបស់ចំនុចមួយចំនួនដែលចាំបាច់ មិនទាន់បានបំពេញ។" + +#: contrib/comments/views/comments.py:196 +#: contrib/comments/views/comments.py:286 +msgid "Somebody tampered with the comment form (security violation)" +msgstr "មានគេព្យាយាមសរសេរ មតិយោបល់ មិនត្រឹមត្រូវ (ប៉ះពាល់ដល់សុវត្ថិភាព)" + +#: contrib/comments/views/comments.py:206 +#: contrib/comments/views/comments.py:292 +msgid "The comment form had an invalid 'target' parameter -- the object ID was invalid" +msgstr "បែបបទបំពេញមតិយោបល់មិនមាន 'target' និង លេខសំគាល់កម្មវិធី (object ID) ត្រឹមត្រូវ" + +#: contrib/comments/views/comments.py:257 +#: contrib/comments/views/comments.py:321 +msgid "The comment form didn't provide either 'preview' or 'post'" +msgstr "បែបបទបំពេញមតិយោបល់មិនមាន 'preview' or 'post' ។" + +#: contrib/comments/templates/comments/form.html:6 +#: contrib/comments/templates/comments/form.html:8 +#: contrib/admin/templates/admin/login.html:17 +msgid "Username:" +msgstr "ឈ្មោះសមាជិក" + +#: contrib/comments/templates/comments/form.html:6 +#: contrib/admin/templates/admin/object_history.html:3 +#: contrib/admin/templates/admin/change_list.html:5 +#: contrib/admin/templates/admin/base.html:25 +#: contrib/admin/templates/admin/delete_confirmation.html:3 +#: contrib/admin/templates/admin/change_form.html:10 +#: contrib/admin/templates/registration/password_change_done.html:3 +#: contrib/admin/templates/registration/password_change_form.html:3 +#: contrib/admin/templates/admin_doc/bookmarklets.html:4 +#: contrib/admin/templates/admin_doc/view_detail.html:4 +#: contrib/admin/templates/admin_doc/template_tag_index.html:5 +#: contrib/admin/templates/admin_doc/template_detail.html:4 +#: contrib/admin/templates/admin_doc/template_filter_index.html:5 +#: contrib/admin/templates/admin_doc/missing_docutils.html:4 +#: contrib/admin/templates/admin_doc/view_index.html:5 +#: contrib/admin/templates/admin_doc/model_detail.html:3 +#: contrib/admin/templates/admin_doc/index.html:4 +#: contrib/admin/templates/admin_doc/model_index.html:5 +msgid "Log out" +msgstr "ចាកចេញ" + +#: contrib/comments/templates/comments/form.html:8 +#: contrib/admin/templates/admin/login.html:20 +msgid "Password:" +msgstr "ពាក្យសំងាត់" + +#: contrib/comments/templates/comments/form.html:8 +msgid "Forgotten your password?" +msgstr "តើលោកអ្នកភ្លេចពាក្យសំងាត់រឺ?" + +#: contrib/comments/templates/comments/form.html:12 +msgid "Ratings" +msgstr "វាយតំលៃ" + +#: contrib/comments/templates/comments/form.html:12 +#: contrib/comments/templates/comments/form.html:23 +msgid "Required" +msgstr "ចាំបាច់" + +#: contrib/comments/templates/comments/form.html:12 +#: contrib/comments/templates/comments/form.html:23 +msgid "Optional" +msgstr "មិនចាំបាច់ជ្រើសរើសយកក៏បាន" + +#: contrib/comments/templates/comments/form.html:23 +msgid "Post a photo" +msgstr "បញ្ជូនរូបភាព" + +#: contrib/comments/templates/comments/form.html:28 +#: contrib/comments/templates/comments/freeform.html:5 +msgid "Comment:" +msgstr "មតិយោបល់" + +#: contrib/comments/templates/comments/form.html:35 +#: contrib/comments/templates/comments/freeform.html:10 +msgid "Preview comment" +msgstr "មើល មតិយោបល់" + +#: contrib/comments/templates/comments/freeform.html:4 +msgid "Your name:" +msgstr "ឈ្មោះ" + +#: contrib/admin/filterspecs.py:40 +#, python-format +msgid "" +"<h3>By %s:</h3>\n" +"<ul>\n" +msgstr "" +"<h3>ដោយ %s:</h3>\n" +"<ul>\n" + +#: contrib/admin/filterspecs.py:70 +#: contrib/admin/filterspecs.py:88 +#: contrib/admin/filterspecs.py:143 +#: contrib/admin/filterspecs.py:169 +msgid "All" +msgstr "ទាំងអស់" + +#: contrib/admin/filterspecs.py:109 +msgid "Any date" +msgstr "កាលបរិច្ឆេទណាមួយ" + +#: contrib/admin/filterspecs.py:110 +msgid "Today" +msgstr "ថ្ងៃនេះ" + +#: contrib/admin/filterspecs.py:113 +msgid "Past 7 days" +msgstr "៧ថ្ងៃកន្លងមក" + +#: contrib/admin/filterspecs.py:115 +msgid "This month" +msgstr "ខែនេះ" + +#: contrib/admin/filterspecs.py:117 +msgid "This year" +msgstr "ឆ្នាំនេះ" + +#: contrib/admin/filterspecs.py:143 +msgid "Yes" +msgstr "យល់ព្រម" + +#: contrib/admin/filterspecs.py:143 +msgid "No" +msgstr "មិនយល់ព្រម" + +#: contrib/admin/filterspecs.py:150 +msgid "Unknown" +msgstr "មិនដឹង" + +#: contrib/admin/models.py:16 +msgid "action time" +msgstr "ពេលវេលាប្រតិបត្តិការ" + +#: contrib/admin/models.py:19 +msgid "object id" +msgstr "លេខសំគាល់កម្មវិធី (object id)" + +#: contrib/admin/models.py:20 +msgid "object repr" +msgstr "object repr" + +#: contrib/admin/models.py:21 +msgid "action flag" +msgstr "សកម្មភាព" + +#: contrib/admin/models.py:22 +msgid "change message" +msgstr "ផ្លាស់ប្តូរ" + +#: contrib/admin/models.py:25 +msgid "log entry" +msgstr "កំណត់ហេតុ" + +#: contrib/admin/models.py:26 +msgid "log entries" +msgstr "កំណត់ហេតុ" + +#: contrib/admin/templatetags/admin_list.py:230 +msgid "All dates" +msgstr "កាលបរិច្ឆេទទាំងអស់" + +#: contrib/admin/views/decorators.py:10 +#: contrib/auth/forms.py:59 +msgid "Please enter a correct username and password. Note that both fields are case-sensitive." +msgstr "សូមបំពេញ ឈ្មោះសមាជិក និង ពាក្យសំងាត់ ។ " + +#: contrib/admin/views/decorators.py:24 +#: contrib/admin/templates/admin/login.html:25 +msgid "Log in" +msgstr "ពិនិត្យចូល" + +#: contrib/admin/views/decorators.py:62 +msgid "Please log in again, because your session has expired. Don't worry: Your submission has been saved." +msgstr "សូមពិនិត្យចូលម្តងទៀត ។" + +#: contrib/admin/views/decorators.py:69 +msgid "Looks like your browser isn't configured to accept cookies. Please enable cookies, reload this page, and try again." +msgstr "ប្រហែលជាកម្មវិធីមើលគេះទំព័រដែលលោកអ្នកកំពុងប្រើ មិនទទួល គូគី (cookies) ។ សូមកំណត់កម្មវិធីដែលលោកអ្នកកំពុងប្រើនេះអោយទទួលយក គូគី ហើយចូលមកមើលទំព័រនេះម្តងទៀត ។" + +#: contrib/admin/views/decorators.py:83 +msgid "Usernames cannot contain the '@' character." +msgstr "ឈ្មោះសមាជិកមិនអាចមាន សញ្ញា '@' ។" + +#: contrib/admin/views/decorators.py:85 +#, python-format +msgid "Your e-mail address is not your username. Try '%s' instead." +msgstr "អ៊ីមែលរបស់លោកអ្នក មិនអាចធ្វើជា ឈ្មោះសមាជិកបានទេ ។ សូមសាកល្បងជាមួយ '%s'។" + +#: contrib/admin/views/main.py:223 +msgid "Site administration" +msgstr "ទំព័រគ្រប់គ្រង" + +#: contrib/admin/views/main.py:257 +#: contrib/admin/views/auth.py:17 +#, python-format +msgid "The %(name)s \"%(obj)s\" was added successfully." +msgstr "ឈ្មោះកម្មវិធី %(name)s \"%(obj)s\" បានបញ្ជូលដោយជោគជ័យ។" + +#: contrib/admin/views/main.py:261 +#: contrib/admin/views/main.py:347 +#: contrib/admin/views/auth.py:22 +msgid "You may edit it again below." +msgstr "សូមសាកល្បងកែប្រែម្តងទៀត។" + +#: contrib/admin/views/main.py:271 +#: contrib/admin/views/main.py:356 +#, python-format +msgid "You may add another %s below." +msgstr "លោកអ្នកអាចបន្ថែម %s ផ្សេងទៀតដូចខាងក្រោម។" + +#: contrib/admin/views/main.py:289 +#, python-format +msgid "Add %s" +msgstr "បន្ថែម %s" + +#: contrib/admin/views/main.py:335 +#, python-format +msgid "Added %s." +msgstr "បានបន្ថែម %s" + +#: contrib/admin/views/main.py:335 +#: contrib/admin/views/main.py:337 +#: contrib/admin/views/main.py:339 +msgid "and" +msgstr "និង" + +#: contrib/admin/views/main.py:337 +#, python-format +msgid "Changed %s." +msgstr "បានផ្លាស់ប្តូរ %s" + +#: contrib/admin/views/main.py:339 +#, python-format +msgid "Deleted %s." +msgstr "បានលប់ %s" + +#: contrib/admin/views/main.py:342 +msgid "No fields changed." +msgstr "ពុំមានទិន្នន័យត្រូវបានផ្លាស់ប្តូរ។" + +#: contrib/admin/views/main.py:345 +#, python-format +msgid "The %(name)s \"%(obj)s\" was changed successfully." +msgstr "កម្មវិធីឈ្មោះ %(name)s \"%(obj)s\" ត្រូវបានផ្លាស់ប្តូរដោយជោគជ័យ។" + +#: contrib/admin/views/main.py:353 +#, python-format +msgid "The %(name)s \"%(obj)s\" was added successfully. You may edit it again below." +msgstr "ឈ្មោះកម្មវីធី %(name)s \"%(obj)s\" ត្រូវបានបន្ថែមដោយជោគជ័យ។ លោកអ្នកអាចផ្លាស់ប្តូរម្តងទៀតនៅខាងក្រោម។" + +#: contrib/admin/views/main.py:391 +#, python-format +msgid "Change %s" +msgstr "ផ្លាស់ប្តូរ %s" + +#: contrib/admin/views/main.py:473 +#, python-format +msgid "One or more %(fieldname)s in %(name)s: %(obj)s" +msgstr "មានទិន្នន័យ %(fieldname)s មួយចំនួននៅក្នុង %(name)s: %(obj)s" + +#: contrib/admin/views/main.py:478 +#, python-format +msgid "One or more %(fieldname)s in %(name)s:" +msgstr "មានទិន្នន័យ %(fieldname)s មួយចំនួននៅក្នុង %(name)s:" + +#: contrib/admin/views/main.py:511 +#, python-format +msgid "The %(name)s \"%(obj)s\" was deleted successfully." +msgstr "ឈ្មោះកម្មវិធី %(name)s \"%(obj)s\" ត្រូវបានលប់ដោយជោគជ័យ។" + +#: contrib/admin/views/main.py:514 +msgid "Are you sure?" +msgstr "តើលោកអ្នកប្រាកដទេ?" + +#: contrib/admin/views/main.py:536 +#, python-format +msgid "Change history: %s" +msgstr "សកម្មភាពផ្លាស់ប្តូរកន្លងមក : %s" + +#: contrib/admin/views/main.py:570 +#, python-format +msgid "Select %s" +msgstr "ជ្រើសរើស %s" + +#: contrib/admin/views/main.py:570 +#, python-format +msgid "Select %s to change" +msgstr "ជ្រើសរើស %s ដើម្បីផ្លាស់ប្តូរ" + +#: contrib/admin/views/main.py:758 +msgid "Database error" +msgstr "ទិន្នន័យមូលដ្ឋានមានបញ្ហា" + +#: contrib/admin/views/doc.py:46 +#: contrib/admin/views/doc.py:48 +#: contrib/admin/views/doc.py:50 +msgid "tag:" +msgstr "ប្រភេទ:" + +#: contrib/admin/views/doc.py:77 +#: contrib/admin/views/doc.py:79 +#: contrib/admin/views/doc.py:81 +msgid "filter:" +msgstr "ពាក្យស្វែងរក" + +#: contrib/admin/views/doc.py:135 +#: contrib/admin/views/doc.py:137 +#: contrib/admin/views/doc.py:139 +msgid "view:" +msgstr "មើល" + +#: contrib/admin/views/doc.py:164 +#, python-format +msgid "App %r not found" +msgstr "ស្វែងរក App %r មិនឃើញ ។" + +#: contrib/admin/views/doc.py:171 +#, python-format +msgid "Model %r not found in app %r" +msgstr "Model %r រកមិនឃើញនៅក្នុង app %r" + +#: contrib/admin/views/doc.py:183 +#, python-format +msgid "the related `%s.%s` object" +msgstr " `%s.%s` object ដែលពាក់ព័ន្ធ" + +#: contrib/admin/views/doc.py:183 +#: contrib/admin/views/doc.py:205 +#: contrib/admin/views/doc.py:219 +#: contrib/admin/views/doc.py:224 +msgid "model:" +msgstr "model:" + +#: contrib/admin/views/doc.py:214 +#, python-format +msgid "related `%s.%s` objects" +msgstr "ជាប់ទាក់ទងជាមួយនឹងកម្មវិធី `%s.%s` " + +#: contrib/admin/views/doc.py:219 +#, python-format +msgid "all %s" +msgstr "ទាំងអស់ %s" + +#: contrib/admin/views/doc.py:224 +#, python-format +msgid "number of %s" +msgstr "ចំនួននៃ%s" + +#: contrib/admin/views/doc.py:229 +#, python-format +msgid "Fields on %s objects" +msgstr "ទិន្នន័យអំពី %s កម្មវិធី" + +#: contrib/admin/views/doc.py:291 +#: contrib/admin/views/doc.py:301 +#: contrib/admin/views/doc.py:303 +#: contrib/admin/views/doc.py:309 +#: contrib/admin/views/doc.py:310 +#: contrib/admin/views/doc.py:312 +msgid "Integer" +msgstr "ចំនួនពិត(Integer)" + +#: contrib/admin/views/doc.py:292 +msgid "Boolean (Either True or False)" +msgstr "Boolean (អាចជា True រឺ False)" + +#: contrib/admin/views/doc.py:293 +#: contrib/admin/views/doc.py:311 +#, python-format +msgid "String (up to %(maxlength)s)" +msgstr "String (អាចសរសេរបានរហូតដល់ %(maxlength)s)" + +#: contrib/admin/views/doc.py:294 +msgid "Comma-separated integers" +msgstr "ចំនួនពិត(Integer) ដែលផ្តាច់ចេញពីគ្នាដោយក្បៀស" + +#: contrib/admin/views/doc.py:295 +msgid "Date (without time)" +msgstr "កាលបរិច្ឆេទ (Date) (មិនមានសរសេរម៉ោង)" + +#: contrib/admin/views/doc.py:296 +msgid "Date (with time)" +msgstr "កាលបរិច្ឆេទ (Date) (មានសរសេរម៉ោង)" + +#: contrib/admin/views/doc.py:297 +msgid "E-mail address" +msgstr "អ៊ីម៉ែល" + +#: contrib/admin/views/doc.py:298 +#: contrib/admin/views/doc.py:299 +#: contrib/admin/views/doc.py:302 +msgid "File path" +msgstr "ផ្លូវទៅកាន់ឯកសារ" + +#: contrib/admin/views/doc.py:300 +msgid "Decimal number" +msgstr "ចំនួនទសភាគ (Decimal)" + +#: contrib/admin/views/doc.py:306 +msgid "Boolean (Either True, False or None)" +msgstr "Boolean (អាចជា True រឺ False រឺ None)" + +#: contrib/admin/views/doc.py:307 +msgid "Relation to parent model" +msgstr "ទាក់ទងទៅនឹងម៉ូដែល (model)មេ" + +#: contrib/admin/views/doc.py:308 +msgid "Phone number" +msgstr "លេខទូរស័ព្ទ" + +#: contrib/admin/views/doc.py:313 +msgid "Text" +msgstr "អត្ថបទ" + +#: contrib/admin/views/doc.py:314 +msgid "Time" +msgstr "ពេលវេលា" + +#: contrib/admin/views/doc.py:315 +#: contrib/flatpages/models.py:7 +msgid "URL" +msgstr "អាស័យដ្ឋានគេហទំព័រ(URL)" + +#: contrib/admin/views/doc.py:316 +msgid "U.S. state (two uppercase letters)" +msgstr "សហរដ្ឋអាមេរិក U.S. (ជាមួយនឹងអក្សរធំពីរ)" + +#: contrib/admin/views/doc.py:317 +msgid "XML text" +msgstr "អត្ថបទ XML" + +#: contrib/admin/views/doc.py:343 +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s ហាក់បីដូចជា URL ដែលត្រឹមត្រូវទេ" + +#: contrib/admin/views/auth.py:28 +msgid "Add user" +msgstr "បន្ថែមសមាជិក" + +#: contrib/admin/templates/admin/object_history.html:3 +#: contrib/admin/templates/admin/change_list.html:5 +#: contrib/admin/templates/admin/base.html:25 +#: contrib/admin/templates/admin/delete_confirmation.html:3 +#: contrib/admin/templates/admin/change_form.html:10 +#: contrib/admin/templates/registration/password_change_done.html:3 +#: contrib/admin/templates/registration/password_change_form.html:3 +#: contrib/admin/templates/admin_doc/bookmarklets.html:3 +msgid "Documentation" +msgstr "ឯកសារ" + +#: contrib/admin/templates/admin/object_history.html:3 +#: contrib/admin/templates/admin/change_list.html:5 +#: contrib/admin/templates/admin/base.html:25 +#: contrib/admin/templates/admin/delete_confirmation.html:3 +#: contrib/admin/templates/admin/change_form.html:10 +#: contrib/admin/templates/registration/password_change_done.html:3 +#: contrib/admin/templates/registration/password_change_form.html:3 +#: contrib/admin/templates/admin_doc/bookmarklets.html:4 +#: contrib/admin/templates/admin_doc/view_detail.html:4 +#: contrib/admin/templates/admin_doc/template_tag_index.html:5 +#: contrib/admin/templates/admin_doc/template_detail.html:4 +#: contrib/admin/templates/admin_doc/template_filter_index.html:5 +#: contrib/admin/templates/admin_doc/missing_docutils.html:4 +#: contrib/admin/templates/admin_doc/view_index.html:5 +#: contrib/admin/templates/admin_doc/model_detail.html:3 +#: contrib/admin/templates/admin_doc/index.html:4 +#: contrib/admin/templates/admin_doc/model_index.html:5 +msgid "Change password" +msgstr "ផ្លាស់ប្តូរពាក្យសំងាត់" + +#: contrib/admin/templates/admin/object_history.html:5 +#: contrib/admin/templates/admin/500.html:4 +#: contrib/admin/templates/admin/change_list.html:6 +#: contrib/admin/templates/admin/base.html:30 +#: contrib/admin/templates/admin/delete_confirmation.html:6 +#: contrib/admin/templates/admin/change_form.html:13 +#: contrib/admin/templates/admin/invalid_setup.html:4 +#: contrib/admin/templates/registration/password_change_done.html:4 +#: contrib/admin/templates/registration/password_reset_form.html:4 +#: contrib/admin/templates/registration/logged_out.html:4 +#: contrib/admin/templates/registration/password_reset_done.html:4 +#: contrib/admin/templates/registration/password_change_form.html:4 +#: contrib/admin/templates/admin_doc/bookmarklets.html:3 +msgid "Home" +msgstr "គេហទំព័រ" + +#: contrib/admin/templates/admin/object_history.html:5 +#: contrib/admin/templates/admin/change_form.html:20 +msgid "History" +msgstr "សកម្មភាពកន្លងមក" + +#: contrib/admin/templates/admin/object_history.html:18 +msgid "Date/time" +msgstr "Date/time" + +#: contrib/admin/templates/admin/object_history.html:19 +msgid "User" +msgstr "សមាជិក" + +#: contrib/admin/templates/admin/object_history.html:20 +msgid "Action" +msgstr "សកម្មភាព" + +#: contrib/admin/templates/admin/object_history.html:26 +msgid "DATE_WITH_TIME_FULL" +msgstr "N j, Y, P" + +#: contrib/admin/templates/admin/object_history.html:36 +msgid "This object doesn't have a change history. It probably wasn't added via this admin site." +msgstr "កម្មវិធីនេះមិនមានសកម្មភាពកន្លងមកទេ។ ប្រហែលជាសកម្មភាពទាំងនេះមិនបានធ្វើនៅទំព័រគ្រប់គ្រងនេះ។" + +#: contrib/admin/templates/admin/base_site.html:4 +msgid "Django site admin" +msgstr "ទំព័រគ្រប់គ្រងរបស់ Django" + +#: contrib/admin/templates/admin/base_site.html:7 +msgid "Django administration" +msgstr "ការគ្រប់គ្រងរបស់ Django" + +#: contrib/admin/templates/admin/500.html:4 +msgid "Server error" +msgstr "ម៉ាស៊ីនផ្តល់សេវាកម្ម មានបញ្ហា" + +#: contrib/admin/templates/admin/500.html:6 +msgid "Server error (500)" +msgstr "ម៉ាស៊ីនផ្តល់សេវាកម្ម មានបញ្ហា (៥០០)" + +#: contrib/admin/templates/admin/500.html:9 +msgid "Server Error <em>(500)</em>" +msgstr "ម៉ាស៊ីនផ្តល់សេវាកម្ម មានបញ្ហា <em>(៥០០)</em>" + +#: contrib/admin/templates/admin/500.html:10 +msgid "There's been an error. It's been reported to the site administrators via e-mail and should be fixed shortly. Thanks for your patience." +msgstr "មានកំហុស។ កំហុសនេះត្រូវបានបញ្ជូនទៅកាន់អ្នកគ្រប់គ្រងគេហទំព័រនេះរួចហើយ។ សូមអភ័យទោសចំពោះបញ្ហានេះ។" + +#: contrib/admin/templates/admin/404.html:4 +#: contrib/admin/templates/admin/404.html:8 +msgid "Page not found" +msgstr "ទំព័រដែលលោកអ្នកចង់រកនេះពុំមាននៅក្នុងម៉ាស៊ីនរបស់យើងខ្ញុំទេ" + +#: contrib/admin/templates/admin/404.html:10 +msgid "We're sorry, but the requested page could not be found." +msgstr "សួមអភ័យទោស ទំព័រដែលលោកអ្នកចង់រកនេះពុំមាននឹងក្នុងម៉ាស៊ីនរបស់យើងខ្ញុំទេ" + +#: contrib/admin/templates/admin/index.html:17 +#, python-format +msgid "Models available in the %(name)s application." +msgstr "ម៉ូដែល (Models) មាននៅក្នុងកម្មវិធី %(name)s ។" + +#: contrib/admin/templates/admin/index.html:18 +#, python-format +msgid "%(name)s" +msgstr "%(name)s" + +#: contrib/admin/templates/admin/index.html:28 +#: contrib/admin/templates/admin/change_form.html:15 +msgid "Add" +msgstr "បន្ថែម" + +#: contrib/admin/templates/admin/index.html:34 +msgid "Change" +msgstr "ផ្លាស់ប្តូរ" + +#: contrib/admin/templates/admin/index.html:44 +msgid "You don't have permission to edit anything." +msgstr "លោកអ្នកពុំមានសិទ្ធិ ផ្លាស់ប្តូរ ទេ។" + +#: contrib/admin/templates/admin/index.html:52 +msgid "Recent Actions" +msgstr "សកម្មភាពបច្ចុប្បន្ន" + +#: contrib/admin/templates/admin/index.html:53 +msgid "My Actions" +msgstr "សកម្មភាពរបស់ខ្ញុំ" + +#: contrib/admin/templates/admin/index.html:57 +msgid "None available" +msgstr "គ្មាន" + +#: contrib/admin/templates/admin/change_list.html:11 +#, python-format +msgid "Add %(name)s" +msgstr "បន្ថែម %(name)s" + +#: contrib/admin/templates/admin/login.html:22 +msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?" +msgstr "តើលោកអ្នក <a href=\"/password_reset/\">ភ្លេចពាក្យសំងាត់</a>?" + +#: contrib/admin/templates/admin/base.html:25 +msgid "Welcome," +msgstr "សូមស្វាគមន៏" + +#: contrib/admin/templates/admin/delete_confirmation.html:9 +#: contrib/admin/templates/admin/submit_line.html:3 +msgid "Delete" +msgstr "លប់" + +#: contrib/admin/templates/admin/delete_confirmation.html:14 +#, python-format +msgid "Deleting the %(object_name)s '%(escaped_object)s' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" +msgstr "ការលប់ %(object_name)s '%(escaped_object)s' អាចធ្វើអោយកម្មវិធីដែលពាក់ព័ន្ធបាត់បង់ ។ ក៏ប៉ន្តែលោកអ្នកពុំមានសិទ្ធិលប់កម្មវិធីប្រភេទនេះទេ។" + +#: contrib/admin/templates/admin/delete_confirmation.html:21 +#, python-format +msgid "Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? All of the following related items will be deleted:" +msgstr "តើលោកអ្នកប្រាកដជាចង់លប់ %(object_name)s \"%(escaped_object)s\"? ការលប់ %(object_name)s '%(escaped_object)s' អាចធ្វើអោយកម្មវិធីដែលពាក់ព័ន្ធបាត់បង់។" + +#: contrib/admin/templates/admin/delete_confirmation.html:26 +msgid "Yes, I'm sure" +msgstr "ខ្ញុំច្បាស់ជាចង់លប់" + +#: contrib/admin/templates/admin/filter.html:2 +#, python-format +msgid " By %(filter_title)s " +msgstr "ដោយ %(filter_title)s " + +#: contrib/admin/templates/admin/search_form.html:8 +msgid "Go" +msgstr "ស្វែងរក" + +#: contrib/admin/templates/admin/search_form.html:10 +#, python-format +msgid "1 result" +msgid_plural "%(counter)s results" +msgstr[0] "លទ្ធផល ១" +msgstr[1] "លទ្ធផល %(counter)s " + +#: contrib/admin/templates/admin/search_form.html:10 +#, python-format +msgid "%(full_result_count)s total" +msgstr "សរុបទាំងអស់ %(full_result_count)s" + +#: contrib/admin/templates/admin/pagination.html:10 +msgid "Show all" +msgstr "បង្ហាញទាំងអស់" + +#: contrib/admin/templates/admin/filters.html:4 +msgid "Filter" +msgstr "ស្វែងរកជាមួយ" + +#: contrib/admin/templates/admin/change_form.html:21 +msgid "View on site" +msgstr "មើលនៅលើគេហទំព័រដោយផ្ទាល់" + +#: contrib/admin/templates/admin/change_form.html:30 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "សូមកែប្រែកំហុសខាងក្រោម ។" +msgstr[1] "សូមកែប្រែកំហុសខាងក្រោម ។" + +#: contrib/admin/templates/admin/change_form.html:48 +msgid "Ordering" +msgstr "កំពុងតំរៀប" + +#: contrib/admin/templates/admin/change_form.html:51 +msgid "Order:" +msgstr "តំរៀប" + +#: contrib/admin/templates/admin/submit_line.html:4 +msgid "Save as new" +msgstr "រក្សាទុក" + +#: contrib/admin/templates/admin/submit_line.html:5 +msgid "Save and add another" +msgstr "រក្សាទុក ហើយ បន្ថែមថ្មី" + +#: contrib/admin/templates/admin/submit_line.html:6 +msgid "Save and continue editing" +msgstr "រក្សាទុក ហើយ កែឯកសារដដែល" + +#: contrib/admin/templates/admin/submit_line.html:7 +msgid "Save" +msgstr "រក្សាទុក" + +#: contrib/admin/templates/admin/invalid_setup.html:8 +msgid "Something's wrong with your database installation. Make sure the appropriate database tables have been created, and make sure the database is readable by the appropriate user." +msgstr "មូលដ្ឋានទិន្នន័យ របស់លោកអ្នក មានបញ្ហា។ តើ លោកអ្នកបាន បង្កើត តារាង របស់មូលដ្ឋានទិន្នន័យ ហើយឬនៅ? តើ លោកអ្នកប្រាកដថាសមាជិកអាចអានមូលដ្ឋានទិន្នន័យនេះបានឬទេ? " + +#: contrib/admin/templates/admin/auth/user/add_form.html:6 +msgid "First, enter a username and password. Then, you'll be able to edit more user options." +msgstr "តំបូងសូមបំពេញ ឈ្មោះជាសមាជិក និង ពាក្យសំងាត់។ បន្ទាប់មកលោកអ្នកអាចបំពេញបន្ថែមជំរើសផ្សេងៗទៀតបាន។ " + +#: contrib/admin/templates/admin/auth/user/add_form.html:12 +msgid "Username" +msgstr "ឈ្មោះជាសមាជិក" + +#: contrib/admin/templates/admin/auth/user/add_form.html:18 +msgid "Password" +msgstr "ពាក្យសំងាត់" + +#: contrib/admin/templates/admin/auth/user/add_form.html:23 +msgid "Password (again)" +msgstr "ពាក្យសំងាត់ (ម្តងទៀត)" + +#: contrib/admin/templates/admin/auth/user/add_form.html:24 +msgid "Enter the same password as above, for verification." +msgstr "សូមបំពេញពាក្យសំងាត់ដូចខាងលើ ដើម្បីត្រួតពិនិត្យ។ " + +#: contrib/admin/templates/registration/password_change_done.html:4 +#: contrib/admin/templates/registration/password_change_form.html:4 +#: contrib/admin/templates/registration/password_change_form.html:6 +#: contrib/admin/templates/registration/password_change_form.html:10 +msgid "Password change" +msgstr "ផ្លាស់ប្តូរពាក្យសំងាត់" + +#: contrib/admin/templates/registration/password_change_done.html:6 +#: contrib/admin/templates/registration/password_change_done.html:10 +msgid "Password change successful" +msgstr "ពាក្យសំងាត់បានផ្លាស់ប្តូរដោយជោគជ័យ" + +#: contrib/admin/templates/registration/password_change_done.html:12 +msgid "Your password was changed." +msgstr "ពាក្យសំងាត់របស់លោកអ្នកបានផ្លាស់ប្តូរហើយ" + +#: contrib/admin/templates/registration/password_reset_form.html:4 +#: contrib/admin/templates/registration/password_reset_form.html:6 +#: contrib/admin/templates/registration/password_reset_form.html:10 +#: contrib/admin/templates/registration/password_reset_done.html:4 +msgid "Password reset" +msgstr "ពាក្យសំងាត់បានកំណត់សារជាថ្មី" + +#: contrib/admin/templates/registration/password_reset_form.html:12 +msgid "Forgotten your password? Enter your e-mail address below, and we'll reset your password and e-mail the new one to you." +msgstr "តើលោកអ្នកភ្លេចពាក្យសំងាត់រឺ? សូមបំពេញអ៊ីម៉ែលខាងក្រោម យើងខ្ញុំនឹងកំណត់ពាក្យសំងាត់របស់លោកអ្នកសារឡើងវិញ ហើយបញ្ជូនទៅកាន់អ៊ីម៉ែលរបស់លោកអ្នក។" + +#: contrib/admin/templates/registration/password_reset_form.html:16 +msgid "E-mail address:" +msgstr "អ៊ីមែល" + +#: contrib/admin/templates/registration/password_reset_form.html:16 +msgid "Reset my password" +msgstr "កំណត់ពាក្យសំងាត់សារជាថ្មី" + +#: contrib/admin/templates/registration/logged_out.html:8 +msgid "Thanks for spending some quality time with the Web site today." +msgstr "សូមថ្លែងអំណរគុណ ដែលបានចំណាយ ពេលវេលាដ៏មានតំលៃ របស់លោកអ្នកមកទស្សនាគេហទំព័ររបស់យើងខ្ញុំ" + +#: contrib/admin/templates/registration/logged_out.html:10 +msgid "Log in again" +msgstr "ពិនិត្យចូលម្តងទៀត" + +#: contrib/admin/templates/registration/password_reset_done.html:6 +#: contrib/admin/templates/registration/password_reset_done.html:10 +msgid "Password reset successful" +msgstr "ពាក្យសំងាត់បានផ្លាស់ប្តូរដោយជោគជ័យ" + +#: contrib/admin/templates/registration/password_reset_done.html:12 +msgid "We've e-mailed a new password to the e-mail address you submitted. You should be receiving it shortly." +msgstr "យើងខ្ញុំបានបញ្ជូនពាក្យសំងាត់ទៅកាន់អ៊ីម៉ែលរបស់លោកអ្នករួចហើយ។ លោកអ្នកនឹងបានទទួលនៅពេលបន្តិចទៀតនេះ។" + +#: contrib/admin/templates/registration/password_change_form.html:12 +msgid "Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly." +msgstr "សូមបំពេញពាក្យសំងាត់ចាស់របស់លោកអ្នក។ ដើម្បីសុវត្ថភាព សូមបំពេញពាក្យសំងាត់ថ្មីខាងក្រោមពីរដង។" + +#: contrib/admin/templates/registration/password_change_form.html:17 +msgid "Old password:" +msgstr "ពាក្សំងាត់ចាស់" + +#: contrib/admin/templates/registration/password_change_form.html:19 +msgid "New password:" +msgstr "ពាក្យសំងាត់ថ្មី" + +#: contrib/admin/templates/registration/password_change_form.html:21 +msgid "Confirm password:" +msgstr "បំពេញពាក្យសំងាត់ថ្មីម្តងទៀត" + +#: contrib/admin/templates/registration/password_change_form.html:23 +msgid "Change my password" +msgstr "ផ្លាស់ប្តូរពាក្យសំងាត់" + +#: contrib/admin/templates/registration/password_reset_email.html:2 +msgid "You're receiving this e-mail because you requested a password reset" +msgstr "លោកអ្នកទទួលអ៊ីម៉ែលនេះដោយសារលោកអ្នកកំណត់ពាក្យសំងាត់នេះសារជាថ្មី" + +#: contrib/admin/templates/registration/password_reset_email.html:3 +#, python-format +msgid "for your user account at %(site_name)s" +msgstr "សំរាប់សមាជិកនៅឯគេហទំព័រ %(site_name)s" + +#: contrib/admin/templates/registration/password_reset_email.html:5 +#, python-format +msgid "Your new password is: %(new_password)s" +msgstr "ពាក្យសំងាត់ថ្មីគឺ: %(new_password)s" + +#: contrib/admin/templates/registration/password_reset_email.html:7 +msgid "Feel free to change this password by going to this page:" +msgstr "សូមផ្លាស់ប្តូរពាក្យសំងាត់នៅឯទំព័រនេះ:" + +#: contrib/admin/templates/registration/password_reset_email.html:11 +msgid "Your username, in case you've forgotten:" +msgstr "ឈ្មោះជាសមាជិកក្នុងករណីភ្លេច:" + +#: contrib/admin/templates/registration/password_reset_email.html:13 +msgid "Thanks for using our site!" +msgstr "សូមអរគុណដែលបានប្រើប្រាស់សេវាកម្មរបស់យើងខ្ញុំ" + +#: contrib/admin/templates/registration/password_reset_email.html:15 +#, python-format +msgid "The %(site_name)s team" +msgstr "ក្រុមរបស់គេហទំព័រ %(site_name)s" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:3 +msgid "Bookmarklets" +msgstr "កំរងចំណាំ" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:5 +msgid "Documentation bookmarklets" +msgstr "កំរងចំណាំអំពីឯកសារ" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:9 +msgid "" +"\n" +"<p class=\"help\">To install bookmarklets, drag the link to your bookmarks\n" +"toolbar, or right-click the link and add it to your bookmarks. Now you can\n" +"select the bookmarklet from any page in the site. Note that some of these\n" +"bookmarklets require you to be viewing the site from a computer designated\n" +"as \"internal\" (talk to your system administrator if you aren't sure if\n" +"your computer is \"internal\").</p>\n" +msgstr "" +"\n" +"<p class=\"help\">ដើម្បីតំលើងកំរងចំណាំ សូមទាញយកអត្ថបទភ្ជាប់ទៅកាន់របាឧបករណ៍ ឬក៏ចុចខាងស្តាំលើអត្ថបទភ្ជាប់ហើយបញ្ជូលទៅក្នុងកំរងចំណាំរបស់លោកអ្នក។</p>\n" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:19 +msgid "Documentation for this page" +msgstr "ឯកសារសំរាប់ទំព័រនេះ" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:20 +msgid "Jumps you from any page to the documentation for the view that generates that page." +msgstr "Jumps you from any page to the documentation for the view that generates that page." + +#: contrib/admin/templates/admin_doc/bookmarklets.html:22 +msgid "Show object ID" +msgstr "បង្ហាញលេខសំគាល់កម្មវិធី" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:23 +msgid "Shows the content-type and unique ID for pages that represent a single object." +msgstr "Shows the content-type and unique ID for pages that represent a single object." + +#: contrib/admin/templates/admin_doc/bookmarklets.html:25 +msgid "Edit this object (current window)" +msgstr "កែប្រែកម្មវិធីនេះ(វីនដូវកំពុងប្រើ)" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:26 +msgid "Jumps to the admin page for pages that represent a single object." +msgstr "បង្វែរទៅកាន់ ទំព័រគ្រប់គ្រង សំរាប់ទំព័រណាដែលតំណាងអោយកម្មវិធីតែមួយ។" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:28 +msgid "Edit this object (new window)" +msgstr "កែប្រែកម្មវិធីនេះ(វីនដូវថ្មី)" + +#: contrib/admin/templates/admin_doc/bookmarklets.html:29 +msgid "As above, but opens the admin page in a new window." +msgstr "ដូចខាងលើ តែបើកនៅទំព័រវីនដូវថ្មី" + +#: contrib/admin/templates/widget/date_time.html:3 +msgid "Date:" +msgstr "កាលបរិច្ឆេទ" + +#: contrib/admin/templates/widget/date_time.html:4 +msgid "Time:" +msgstr "ម៉ោង" + +#: contrib/admin/templates/widget/file.html:2 +msgid "Currently:" +msgstr "បច្ចុប្បន្ន" + +#: contrib/admin/templates/widget/file.html:3 +msgid "Change:" +msgstr "ផ្លាស់ប្តូរ" + +#: contrib/redirects/models.py:7 +msgid "redirect from" +msgstr "នាំចេញពី" + +#: contrib/redirects/models.py:8 +msgid "This should be an absolute path, excluding the domain name. Example: '/events/search/'." +msgstr "គួរតែជាផ្លូវពេញ (absolute path) ហើយមិនបញ្ជូលឈ្មោះ ដមែន (domain name)។ឧទាហរណ៍ '/events/search/'។" + +#: contrib/redirects/models.py:9 +msgid "redirect to" +msgstr "នាំចេញទៅ" + +#: contrib/redirects/models.py:10 +msgid "This can be either an absolute path (as above) or a full URL starting with 'http://'." +msgstr "អាចជាផ្លូវពេញ (absolute path) ឬក៏ URL ទាំងមូលដែលចាប់ផ្តើមជាមួយ 'http://'។" + +#: contrib/redirects/models.py:13 +msgid "redirect" +msgstr "នាំចេញ" + +#: contrib/redirects/models.py:14 +msgid "redirects" +msgstr "នាំចេញ" + +#: contrib/flatpages/models.py:8 +msgid "Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "ឧទាហរណ៍ '/about/contact/' ។ ត្រូវប្រាកដថាមានសញ្ញា / ទាំងនៅផ្នែកខាងមុខ និង ខាងក្រោយ។" + +#: contrib/flatpages/models.py:9 +msgid "title" +msgstr "ចំណងជើង" + +msgid "Title" +msgstr "ចំណងជើង" + +#: contrib/flatpages/models.py:10 +msgid "content" +msgstr "អត្ថន័យ" + +#: contrib/flatpages/models.py:11 +msgid "enable comments" +msgstr "អនុញ្ញាត" + +#: contrib/flatpages/models.py:12 +msgid "template name" +msgstr "ឈ្មោះឯកសារគំរូ" + +#: contrib/flatpages/models.py:13 +msgid "Example: 'flatpages/contact_page.html'. If this isn't provided, the system will use 'flatpages/default.html'." +msgstr "ឧទាហរណ៍ 'flatpages/contact_page.html'។ ប្រសិនឯកសារនេះមិនមានទេ នោះឯកសារ 'flatpages/default.html'នឹងត្រូវប្រើ។" + +#: contrib/flatpages/models.py:14 +msgid "registration required" +msgstr "ត្រូវការសមាជិកភាព" + +#: contrib/flatpages/models.py:14 +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "ប្រសិនជាចុចជ្រើសរើសយកជំរើសនេះ នោះ មានតែសមាជិកទេដែលអាចមើលទំព័រនេះបាន។" + +#: contrib/flatpages/models.py:18 +msgid "flat page" +msgstr "ទំព័ថ្មី" + +#: contrib/flatpages/models.py:19 +msgid "flat pages" +msgstr "ទំព័ថ្មី" + +#: contrib/auth/views.py:39 +msgid "Logged out" +msgstr "ចាកចេញ" + +#: contrib/auth/models.py:38 +#: contrib/auth/models.py:57 +msgid "name" +msgstr "ឈ្មោះ" + +#: contrib/auth/models.py:40 +msgid "codename" +msgstr "ឈ្មោះលេខកូត" + +#: contrib/auth/models.py:42 +msgid "permission" +msgstr "អនុញ្ញាត" + +#: contrib/auth/models.py:43 +#: contrib/auth/models.py:58 +msgid "permissions" +msgstr "អនុញ្ញាត" + +#: contrib/auth/models.py:60 +msgid "group" +msgstr "ក្រុម" + +#: contrib/auth/models.py:61 +#: contrib/auth/models.py:100 +msgid "groups" +msgstr "ក្រុម" + +#: contrib/auth/models.py:90 +msgid "username" +msgstr "ឈ្មោះជាសមាជិក" + +#: contrib/auth/models.py:90 +msgid "Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores)." +msgstr "ត្រូចវបំពេញអក្សរឡាតាំងចំនួន៣០ ឬ តិចជាងនេះ (អក្សរ លេខ ឬ សញ្ញា _)។" + +#: contrib/auth/models.py:91 +msgid "First name" +msgstr "នាម" + +#: contrib/auth/models.py:92 +msgid "Last name" +msgstr "គោត្តនាម" + +msgid "first name" +msgstr "នាម" + +#: contrib/auth/models.py:92 +msgid "last name" +msgstr "គោត្តនាម" + +#: contrib/auth/models.py:93 +msgid "e-mail address" +msgstr "អ៊ីមែល" + +#: contrib/auth/models.py:94 +msgid "password" +msgstr "ពាក្យសំងាត់" + +#: contrib/auth/models.py:94 +msgid "Use '[algo]$[salt]$[hexdigest]'" +msgstr "ប្រើ '[algo]$[salt]$[hexdigest]'" + +#: contrib/auth/models.py:95 +msgid "staff status" +msgstr "ស្ថានភាពបុគ្គលិក" + +#: contrib/auth/models.py:95 +msgid "Designates whether the user can log into this admin site." +msgstr "កំណត់អោយសមាជិកអាចចូលមកប្រើប្រាស់ទំព័រគ្រប់គ្រងនេះ។" + +#: contrib/auth/models.py:96 +msgid "active" +msgstr "សកម្ម" + +#: contrib/auth/models.py:96 +msgid "Designates whether this user can log into the Django admin. Unselect this instead of deleting accounts." +msgstr "កំណត់ថាតើសមាជិកអាចពិនិត្យចូលមកប្រើទំព័រគ្រប់គ្រង។ មិនជ្រើសរើស ជាជាងលប់ចោល។" + +#: contrib/auth/models.py:97 +msgid "superuser status" +msgstr "ស្ថានភាពអ្នកគ្រងគ្រង" + +#: contrib/auth/models.py:97 +msgid "Designates that this user has all permissions without explicitly assigning them." +msgstr "កំណត់អោយសមាជិកនេះមានសិទ្ធិទាំងអស់។" + +#: contrib/auth/models.py:98 +msgid "last login" +msgstr "ការពិនិត្យចូលកន្លងមក" + +#: contrib/auth/models.py:99 +msgid "date joined" +msgstr "កាលបរិច្ឆេទចូលរួម" + +#: contrib/auth/models.py:101 +msgid "In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in." +msgstr "បន្ថែមចំពោះសិទ្ធិដែលគេបានផ្តល់អោយ សមាជិកនេះអាចទទួលបានសិទ្ធិទាំងអស់ដែលកំណត់សំរាប់ក្រុម ដែលសមាជិកនេះស្ថិតនៅ។" + +#: contrib/auth/models.py:102 +msgid "user permissions" +msgstr "ការអនុញ្ញាតអោយសមាជិក" + +#: contrib/auth/models.py:105 +msgid "user" +msgstr "សមាជិក" + +#: contrib/auth/models.py:106 +msgid "users" +msgstr "សមាជិក" + +#: contrib/auth/models.py:111 +msgid "Personal info" +msgstr "ព័ត៌មានផ្ទាល់ខ្លួន" + +#: contrib/auth/models.py:112 +msgid "Permissions" +msgstr "ការអនុញ្ញាត" + +#: contrib/auth/models.py:113 +msgid "Important dates" +msgstr "កាលបរិច្ឆេទសំខាន់" + +#: contrib/auth/models.py:114 +msgid "Groups" +msgstr "ក្រុម" + +#: contrib/auth/models.py:256 +msgid "message" +msgstr "អត្ថបទ" + +#: contrib/auth/forms.py:52 +msgid "Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in." +msgstr "កម្មវិធីសំរាប់មើលគេហទំព័រនេះហាក់បីដូចជាមិនទាន់បានទទួលយកគុគី ។ ចាំបាច់ត្រូវកំណត់អោយកម្មវិធីសំរាប់មើលគេហទំព័រទទួលយក គុគី ដើម្បីពិនិត្យចូល ។" + +#: contrib/auth/forms.py:61 +msgid "This account is inactive." +msgstr "ឈ្មោះសមាជិកនេះលែងដំណើរការ" + +#: contrib/contenttypes/models.py:20 +msgid "python model class name" +msgstr "ឈ្មោះ python model class" + +#: contrib/contenttypes/models.py:23 +msgid "content type" +msgstr "ប្រភេទអត្ថន័យ" + +#: contrib/contenttypes/models.py:24 +msgid "content types" +msgstr "ប្រភេទអត្ថន័យ" + +#: contrib/sessions/models.py:51 +msgid "session key" +msgstr "លេខសំគាល់រយះពេលពិនិត្យចូល" + +#: contrib/sessions/models.py:52 +msgid "session data" +msgstr "ទិន្នន័យរយះពេលពិនិត្យចូល" + +#: contrib/sessions/models.py:53 +msgid "expire date" +msgstr "ហួសពេលកំណត់" + +#: contrib/sessions/models.py:57 +msgid "session" +msgstr "រយះពេលពិនិត្យចូល" + +#: contrib/sessions/models.py:58 +msgid "sessions" +msgstr "រយះពេលពិនិត្យចូល" + +#: contrib/sites/models.py:10 +msgid "domain name" +msgstr "ឈ្មោះដមែន" + +#: contrib/sites/models.py:11 +msgid "display name" +msgstr "ឈ្មោះសំរាប់បង្ហាញ" + +#: contrib/sites/models.py:15 +msgid "site" +msgstr "គេហទំព័រ" + +#: contrib/sites/models.py:16 +msgid "sites" +msgstr "គេហទំព័រ" + +#: utils/dates.py:6 +msgid "Monday" +msgstr "ច័ន្ទ" + +#: utils/dates.py:6 +msgid "Tuesday" +msgstr "អង្គារ" + +#: utils/dates.py:6 +msgid "Wednesday" +msgstr "ពុធ" + +#: utils/dates.py:6 +msgid "Thursday" +msgstr "ព្រហស្បតិ៍" + +#: utils/dates.py:6 +msgid "Friday" +msgstr "សុក្រ" + +#: utils/dates.py:7 +msgid "Saturday" +msgstr "សៅរ៍" + +#: utils/dates.py:7 +msgid "Sunday" +msgstr "អាទិត្យ" + +#: utils/dates.py:14 +msgid "January" +msgstr "មករា" + +#: utils/dates.py:14 +msgid "February" +msgstr "កុម្ភៈ" + +#: utils/dates.py:14 +#: utils/dates.py:27 +msgid "March" +msgstr "មិនា" + +#: utils/dates.py:14 +#: utils/dates.py:27 +msgid "April" +msgstr "មេសា" + +#: utils/dates.py:14 +#: utils/dates.py:27 +msgid "May" +msgstr "ឧសភា" + +#: utils/dates.py:14 +#: utils/dates.py:27 +msgid "June" +msgstr "មិថុនា" + +#: utils/dates.py:15 +#: utils/dates.py:27 +msgid "July" +msgstr "កក្កដា" + +#: utils/dates.py:15 +msgid "August" +msgstr "សីហា" + +#: utils/dates.py:15 +msgid "September" +msgstr "កញ្ញា" + +#: utils/dates.py:15 +msgid "October" +msgstr "តុលា" + +#: utils/dates.py:15 +msgid "November" +msgstr "វិច្ឆិកា" + +#: utils/dates.py:16 +msgid "December" +msgstr "ធ្នូ" + +#: utils/dates.py:19 +msgid "jan" +msgstr "មករា" + +#: utils/dates.py:19 +msgid "feb" +msgstr "កុម្ភះ" + +#: utils/dates.py:19 +msgid "mar" +msgstr "មិនា" + +#: utils/dates.py:19 +msgid "apr" +msgstr "មេសា" + +#: utils/dates.py:19 +msgid "may" +msgstr "ឧសភា" + +#: utils/dates.py:19 +msgid "jun" +msgstr "មិថុនា" + +#: utils/dates.py:20 +msgid "jul" +msgstr "កក្កដា" + +#: utils/dates.py:20 +msgid "aug" +msgstr "សីហា" + +#: utils/dates.py:20 +msgid "sep" +msgstr "កញ្ញា" + +#: utils/dates.py:20 +msgid "oct" +msgstr "តុលា" + +#: utils/dates.py:20 +msgid "nov" +msgstr "វិច្ឆិកា" + +#: utils/dates.py:20 +msgid "dec" +msgstr "ធ្នូ" + +#: utils/dates.py:27 +msgid "Jan." +msgstr "មករា" + +#: utils/dates.py:27 +msgid "Feb." +msgstr "កុម្ភះ" + +#: utils/dates.py:28 +msgid "Aug." +msgstr "សីហា" + +#: utils/dates.py:28 +msgid "Sept." +msgstr "កញ្ញា" + +#: utils/dates.py:28 +msgid "Oct." +msgstr "តុលា" + +#: utils/dates.py:28 +msgid "Nov." +msgstr "វិច្ឆិកា" + +#: utils/dates.py:28 +msgid "Dec." +msgstr "ធ្នូ" + +#: utils/timesince.py:12 +msgid "year" +msgid_plural "years" +msgstr[0] "ឆ្នាំ" +msgstr[1] "ឆ្នាំ" + +#: utils/timesince.py:13 +msgid "month" +msgid_plural "months" +msgstr[0] "ខែ" +msgstr[1] "ខែ" + +#: utils/timesince.py:14 +msgid "week" +msgid_plural "weeks" +msgstr[0] "សប្តាហ៍" +msgstr[1] "សប្តាហ៍" + +#: utils/timesince.py:15 +msgid "day" +msgid_plural "days" +msgstr[0] "ថ្ងៃ" +msgstr[1] "ថ្ងៃ" + +#: utils/timesince.py:16 +msgid "hour" +msgid_plural "hours" +msgstr[0] "ម៉ោង" +msgstr[1] "ម៉ោង" + +#: utils/timesince.py:17 +msgid "minute" +msgid_plural "minutes" +msgstr[0] "នាទី" +msgstr[1] "នាទី" + +#: utils/translation/trans_real.py:362 +msgid "DATE_FORMAT" +msgstr "ថ្ងៃទី j ខែ N ឆ្នាំ Y" + +#: utils/translation/trans_real.py:363 +msgid "DATETIME_FORMAT" +msgstr "ថ្ងៃទី j ខែ N ឆ្នាំ Y ម៉ោង P" + +#: utils/translation/trans_real.py:364 +msgid "TIME_FORMAT" +msgstr "ម៉ោង P" + +#: utils/translation/trans_real.py:380 +msgid "YEAR_MONTH_FORMAT" +msgstr "ខែ F ឆ្នាំ Y" + +#: utils/translation/trans_real.py:381 +msgid "MONTH_DAY_FORMAT" +msgstr "ថ្ងៃទី j ខែ F" + +#: conf/global_settings.py:39 +msgid "Arabic" +msgstr "ភាសាអារ៉ាប់" + +#: conf/global_settings.py:40 +msgid "Bengali" +msgstr "ភាសាបេឡារុស្ស" + +#: conf/global_settings.py:41 +msgid "Czech" +msgstr "ភាសាឆេក" + +#: conf/global_settings.py:42 +msgid "Welsh" +msgstr "ភាសាអ៊ុយក្រែន" + +#: conf/global_settings.py:43 +msgid "Danish" +msgstr "ភាសាដាណឺម៉ាក" + +#: conf/global_settings.py:44 +msgid "German" +msgstr "ភាសាអាល្លឺម៉ង់" + +#: conf/global_settings.py:45 +msgid "Greek" +msgstr "ភាសាហ្កែលិគ" + +#: conf/global_settings.py:46 +msgid "English" +msgstr "ភាសាអង់គ្លេស" + +#: conf/global_settings.py:47 +msgid "Spanish" +msgstr "ភាសាអេស្ប៉ាញ" + +#: conf/global_settings.py:48 +msgid "Argentinean Spanish" +msgstr "ភាសាអេស្ប៉ាញ" + +#: conf/global_settings.py:49 +msgid "Finnish" +msgstr "ភាសាហ្វាំងឡង់" + +#: conf/global_settings.py:50 +msgid "French" +msgstr "ភាសាបារាំង" + +#: conf/global_settings.py:51 +msgid "Galician" +msgstr "ភាសាហ្កែលិគ" + +#: conf/global_settings.py:52 +msgid "Hungarian" +msgstr "ភាសាហុងគ្រី" + +#: conf/global_settings.py:53 +msgid "Hebrew" +msgstr "ភាសាហេប្រិ" + +#: conf/global_settings.py:54 +msgid "Icelandic" +msgstr "ភាសាអ៉ីស្លង់" + +#: conf/global_settings.py:55 +msgid "Italian" +msgstr "ភាសាអ៊ីតាលី" + +#: conf/global_settings.py:56 +msgid "Japanese" +msgstr "ភាសាជប៉ុន" + +#: conf/global_settings.py:57 +msgid "Dutch" +msgstr "ភាសាហ្វាំងឡង់" + +#: conf/global_settings.py:58 +msgid "Norwegian" +msgstr "ភាសាន័រវែស" + +#: conf/global_settings.py:59 +msgid "Brazilian" +msgstr "ភាសាប្រេស៊ីល" + +#: conf/global_settings.py:60 +msgid "Romanian" +msgstr "ភាសារូម៉ានី" + +#: conf/global_settings.py:61 +msgid "Russian" +msgstr "ភាសាรัរូស្ស៉ី" + +#: conf/global_settings.py:62 +msgid "Slovak" +msgstr "ភាសាស្លូវ៉ាគី" + +#: conf/global_settings.py:63 +msgid "Slovenian" +msgstr "ភាសាស្លូវ៉ានី" + +#: conf/global_settings.py:64 +msgid "Serbian" +msgstr "" + +#: conf/global_settings.py:65 +msgid "Swedish" +msgstr "ភាសាស៊ុយអែដ" + +#: conf/global_settings.py:66 +msgid "Tamil" +msgstr "ភាសាតាមីល" + +#: conf/global_settings.py:67 +msgid "Turkish" +msgstr "ភាសាទួរគី" + +#: conf/global_settings.py:68 +msgid "Ukrainian" +msgstr "ភាសាអ៊ុយក្រែន" + +#: conf/global_settings.py:69 +msgid "Simplified Chinese" +msgstr "ភាសាចិនសាមញ្ញ" + +#: conf/global_settings.py:70 +msgid "Traditional Chinese" +msgstr "ភាសាចិនបុរាណ" + +#: core/validators.py:63 +msgid "This value must contain only letters, numbers and underscores." +msgstr "ត្រូវបំពេញតែអក្សរឡាតាំង ចំនួនលេខ និង សញ្ញា _" + +#: core/validators.py:67 +msgid "This value must contain only letters, numbers, underscores, dashes or slashes." +msgstr "ត្រូវបំពេញតែអក្សរឡាតាំង ចំនួនលេខ និង សញ្ញា _ សញ្ញា - ឬ សញ្ញា / ។" + +#: core/validators.py:71 +msgid "This value must contain only letters, numbers, underscores or hyphens." +msgstr "ត្រូវបំពេញតែអក្សរឡាតាំង ចំនួនលេខ និង សញ្ញា _ សញ្ញា - ។" + +#: core/validators.py:75 +msgid "Uppercase letters are not allowed here." +msgstr "មិនអនុញ្ញាតអោយសរសេរអក្សរធំ។" + +#: core/validators.py:79 +msgid "Lowercase letters are not allowed here." +msgstr "មិនអនុញ្ញាតអោយសរសេរអក្សរតូច។" + +#: core/validators.py:86 +msgid "Enter only digits separated by commas." +msgstr "បំពេញតែលេខហើយផ្តាច់ចេញពីគ្នាដោយសញ្ញាក្បៀស។" + +#: core/validators.py:98 +msgid "Enter valid e-mail addresses separated by commas." +msgstr "បំពេញអ៊ីម៉ែលហើយផ្តាច់ចេញពីគ្នាដោយសញ្ញាក្បៀស។" + +#: core/validators.py:102 +msgid "Please enter a valid IP address." +msgstr "សូមបំពេញអាស័យដ្ឋាន IP។" + +#: core/validators.py:106 +msgid "Empty values are not allowed here." +msgstr "មិនអនុញ្ញាតអោយមានចំនួនទទេ។" + +#: core/validators.py:110 +msgid "Non-numeric characters aren't allowed here." +msgstr "មិនអនុញ្ញាតអោយសរសេរអក្សរដែលមិនមែនជាលេខ។" + +#: core/validators.py:114 +msgid "This value can't be comprised solely of digits." +msgstr "មិនអាចអនុញ្ញាតអោយមានតែចំនួនលេខ។" + +#: core/validators.py:119 +msgid "Enter a whole number." +msgstr "បំពេញចំនួនទាំងអស់។" + +#: core/validators.py:123 +msgid "Only alphabetical characters are allowed here." +msgstr "អនុញ្ញាតអោយសរសេរតែអក្សរឡាតាំង។" + +#: core/validators.py:138 +msgid "Year must be 1900 or later." +msgstr "ត្រូវបំពេញឆ្នាំចាប់ពី ១៩០០។" + +#: core/validators.py:142 +#, python-format +msgid "Invalid date: %s." +msgstr "កាលបរិច្ឆេទមិនត្រឹមត្រូវ : %s។" + +#: core/validators.py:146 +#: db/models/fields/__init__.py:415 +msgid "Enter a valid date in YYYY-MM-DD format." +msgstr "សូមបំពេញកាលបរិច្ឆេទក្នុងទំរង់ជា YYYY-MM-DD ។" + +#: core/validators.py:151 +msgid "Enter a valid time in HH:MM format." +msgstr "សូមបំពេញពេលវេលាក្នុងទំរង់ជា HH:MM ។" + +#: core/validators.py:155 +#: db/models/fields/__init__.py:477 +msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format." +msgstr "សូមបំពេញកាលបរិច្ឆេទក្នុងទំរង់ជា YYYY-MM-DD HH:MM ។" + +#: core/validators.py:160 +msgid "Enter a valid e-mail address." +msgstr "សូមបំពេញអ៊ីមែល" + +#: core/validators.py:172 +#: core/validators.py:401 +#: forms/__init__.py:661 +msgid "No file was submitted. Check the encoding type on the form." +msgstr "មិនមានឯកសារត្រូវបានជ្រើសរើស។ សូមពិនិត្យប្រភេទឯកសារម្តងទៀត។" + +#: core/validators.py:176 +msgid "Upload a valid image. The file you uploaded was either not an image or a corrupted image." +msgstr "រូបភាពដែលទាញយកមិនត្រឹមត្រូវ ប្រហែលជាមិនមែនជារូបភាព ឬក៏ជា រូបភាពខូច។" + +#: core/validators.py:183 +#, python-format +msgid "The URL %s does not point to a valid image." +msgstr "URL រូបភាព %s មិនត្រឹមត្រូវ ។" + +#: core/validators.py:187 +#, python-format +msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid." +msgstr "លេខទូរស័ព្ទត្រូវតែក្នុងទំរង់ជា XXX-XXX-XXXX ។ \"%s\" គឺមិនត្រឹមត្រូវទេ។" + +#: core/validators.py:195 +#, python-format +msgid "The URL %s does not point to a valid QuickTime video." +msgstr "URL ទៅកាន់វីដេអូ QuickTime %s មិនត្រឹមត្រូវ ។" + +#: core/validators.py:199 +msgid "A valid URL is required." +msgstr "URL មិនត្រឹមត្រូវ។" + +#: core/validators.py:213 +#, python-format +msgid "" +"Valid HTML is required. Specific errors are:\n" +"%s" +msgstr "" +"ចាំបាច់ HTML ដែលត្រឹមត្រូវ។ ខាងក្រោមគឺជាកំហុស:\n" +"%s" + +#: core/validators.py:220 +#, python-format +msgid "Badly formed XML: %s" +msgstr "XML មិនត្រឹមត្រូវ: %s" + +#: core/validators.py:230 +#, python-format +msgid "Invalid URL: %s" +msgstr "URL ដែលមិនត្រឹមត្រូវ: %s" + +#: core/validators.py:234 +#: core/validators.py:236 +#, python-format +msgid "The URL %s is a broken link." +msgstr "URLខូច: %s" + +#: core/validators.py:242 +msgid "Enter a valid U.S. state abbreviation." +msgstr "សូមបំពេញអក្សរកាត់រដ្ឋរបស់សហរដ្ឋអាមេរិកអោយបានត្រឹមត្រូវ។" + +#: core/validators.py:256 +#, python-format +msgid "Watch your mouth! The word %s is not allowed here." +msgid_plural "Watch your mouth! The words %s are not allowed here." +msgstr[0] "ពាក្យ %s មិនអនុញ្ញាតអោយប្រើនៅទីនេះទេ។" +msgstr[1] "ពាក្យ %s មិនអនុញ្ញាតអោយប្រើនៅទីនេះទេ។" + +#: core/validators.py:263 +#, python-format +msgid "This field must match the '%s' field." +msgstr "ទិន្នន័យនៅកន្លែងនេះត្រូវតែដូច '%s' ។" + +#: core/validators.py:282 +msgid "Please enter something for at least one field." +msgstr "សូមបំពេញទិន្នន័យយ៉ាងតិចនៅមួយកន្លែង។" + +#: core/validators.py:291 +#: core/validators.py:302 +msgid "Please enter both fields or leave them both empty." +msgstr "អាចបំពេញ ឬ មិនបំពេញ ទិន្នន័យនៅកន្លែងទាំងពីរនេះ។" + +#: core/validators.py:309 +#, python-format +msgid "This field must be given if %(field)s is %(value)s" +msgstr "ទិន្នន័យកន្លែងនេះត្រូវបំពេញប្រសិនបើ %(field)s មានតំលៃ %(value)s" + +#: core/validators.py:321 +#, python-format +msgid "This field must be given if %(field)s is not %(value)s" +msgstr "ទិន្នន័យកន្លែងនេះត្រូវបំពេញប្រសិនបើ %(field)s មិនមានតំលៃ %(value)s" + +#: core/validators.py:340 +msgid "Duplicate values are not allowed." +msgstr "មិនអនុញ្ញាតអោយមានតំលៃដូចគ្នា។" + +#: core/validators.py:363 +#, python-format +msgid "This value must be a power of %s." +msgstr "ចំនួនត្រូវតែជាស្វ័យគុណរបស់ %s។" + +#: core/validators.py:374 +msgid "Please enter a valid decimal number." +msgstr "សូមបំពេញចំនួនទសភាគអោយបានត្រឹមត្រូវ។" + +#: core/validators.py:378 +#, python-format +msgid "Please enter a valid decimal number with at most %s total digit." +msgid_plural "Please enter a valid decimal number with at most %s total digits." +msgstr[0] "សូមបំពេញចំនួនទសភាគយ៉ាងតិច %sខ្ទង់។" +msgstr[1] "សូមបំពេញចំនួនទសភាគយ៉ាងតិច %sខ្ទង់។" + +#: core/validators.py:381 +#, python-format +msgid "Please enter a valid decimal number with a whole part of at most %s digit." +msgid_plural "Please enter a valid decimal number with a whole part of at most %s digits." +msgstr[0] "សូមបំពេញចំនួនទសភាគទាំងអស់ %sខ្ទង់។" +msgstr[1] "សូមបំពេញចំនួនទសភាគទាំងអស់ %sខ្ទង់។" + +#: core/validators.py:384 +#, python-format +msgid "Please enter a valid decimal number with at most %s decimal place." +msgid_plural "Please enter a valid decimal number with at most %s decimal places." +msgstr[0] "សូមបំពេញចំនួនទសភាគយ៉ាងច្រើន %sខ្ទង់។" +msgstr[1] "សូមបំពេញចំនួនទសភាគយ៉ាងច្រើន %sខ្ទង់។" + +#: core/validators.py:394 +#, python-format +msgid "Make sure your uploaded file is at least %s bytes big." +msgstr "ឯកសារដែលទាញយកត្រូវមានទំហំយ៉ាងតិច %s បៃ។" + +#: core/validators.py:395 +#, python-format +msgid "Make sure your uploaded file is at most %s bytes big." +msgstr "ឯកសារដែលទាញយកត្រូវមានទំហំអតិបរិមា %s បៃ។" + +#: core/validators.py:412 +msgid "The format for this field is wrong." +msgstr "ទំរង់ទិន្នន័យនៅកន្លែងនេះមិនត្រឹមត្រូវ។" + +#: core/validators.py:427 +msgid "This field is invalid." +msgstr "ទិន្នន័យកន្លែងនេះមិនត្រឹមត្រូវ។" + +#: core/validators.py:463 +#, python-format +msgid "Could not retrieve anything from %s." +msgstr "មិនអាចទាញយកពី %s។" + +#: core/validators.py:466 +#, python-format +msgid "The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'." +msgstr "ទទួលចំលើយ Content-Type header '%(contenttype)s' មិនត្រឹមត្រូវពី URL %(url)s ។" + +#: core/validators.py:499 +#, python-format +msgid "Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with \"%(start)s\".)" +msgstr "សូមបិទ ថាក់(tag) ដែលមិនទាន់បិទ %(tag)s នៅបន្ទាត់ %(line)s ។ (បន្ទាត់ដែលចាប់ផ្តើមជាមួយ \"%(start)s\".)" + +#: core/validators.py:503 +#, python-format +msgid "Some text starting on line %(line)s is not allowed in that context. (Line starts with \"%(start)s\".)" +msgstr "ពាក្យមួយចំនួននៅបន្ទាត់ %(line)s មិនអនុញ្ញាតអោយប្រើទេ។ (បន្ទាត់ចាប់ផ្តើមជាមួយ \"%(start)s\"។)" + +#: core/validators.py:508 +#, python-format +msgid "\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%(start)s\".)" +msgstr "\"%(attr)s\" on line %(line)s គឺជាគុណលក្ខណៈ(attribute) មិនត្រឹមត្រូវ។ (បន្ទាត់ចាប់ផ្តើមជាមួយ \"%(start)s\".)" + +#: core/validators.py:513 +#, python-format +msgid "\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%(start)s\".)" +msgstr "\"<%(tag)s>\" ថាក់(tag)នៅបន្ទាត់ %(line)s គឺមិនត្រឹមត្រូវ។ (បន្ទាត់ចាប់ផ្តើមជាមួយ \"%(start)s\".)" + +#: core/validators.py:517 +#, python-format +msgid "A tag on line %(line)s is missing one or more required attributes. (Line starts with \"%(start)s\".)" +msgstr "ថាក់ (tag)នៅបន្ទាត់ %(line)s បាត់គុណលក្ខណៈ មួយ ឬ ច្រើន។(បន្ទាត់ចាប់ផ្តើមជាមួយ \"%(start)s\".)" + +#: core/validators.py:522 +#, python-format +msgid "The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line starts with \"%(start)s\".)" +msgstr "គុណលក្ខណៈ \"%(attr)s\" នៅបន្ទាត់ %(line)s ពុំមានតំលៃត្រឹមត្រូវទេ។ (បន្ទាត់ចាប់ផ្តើមជាមួយ \"%(start)s\".)" + +#: views/generic/create_update.py:43 +#: views/generic/create_update.py:117 +#, python-format +msgid "The %(verbose_name)s was updated successfully." +msgstr "The %(verbose_name)s បានផ្លាស់ប្តូរដោយជោគជ័យ។" + +#: views/generic/create_update.py:184 +#, python-format +msgid "The %(verbose_name)s was deleted." +msgstr "The %(verbose_name)s បានលប់។ " + +#: db/models/manipulators.py:302 +#, python-format +msgid "%(object)s with this %(type)s already exists for the given %(field)s." +msgstr "%(object)s ជាមួយនឹងប្រភេទ %(type)s នេះមានម្តងរួចហើយនៅជាមួយ %(field)s" + +#: db/models/fields/__init__.py:40 +#, python-format +msgid "%(optname)s with this %(fieldname)s already exists." +msgstr "%(optname)s ជាមួយឈ្មោះ %(fieldname)s នេះមានរួចរាល់ហើយ។" + +#: db/models/fields/__init__.py:114 +#: db/models/fields/__init__.py:265 +#: db/models/fields/__init__.py:551 +#: db/models/fields/__init__.py:562 +#: forms/__init__.py:346 +msgid "This field is required." +msgstr "ចាំបាច់បំពេញទិន្នន័យកន្លែងនេះ។" + +#: db/models/fields/__init__.py:340 +msgid "This value must be an integer." +msgstr "តំលៃនេះត្រូវតែជាចំនួនលេខ។" + +#: db/models/fields/__init__.py:372 +msgid "This value must be either True or False." +msgstr "តំលៃអាចជា True ឬ False។" + +#: db/models/fields/__init__.py:388 +msgid "This field cannot be null." +msgstr "ចាំបាច់បំពេញទិន្នន័យកន្លែងនេះ។" + +#: db/models/fields/__init__.py:571 +msgid "Enter a valid filename." +msgstr "សូមបំពេញឈ្មោះឯកសារអោយបានត្រឹមត្រូវ។" + +#: db/models/fields/related.py:51 +#, python-format +msgid "Please enter a valid %s." +msgstr "សូមបំពេញ %s អោយបានត្រឹមត្រូវ។" + +#: db/models/fields/related.py:618 +msgid "Separate multiple IDs with commas." +msgstr "ផ្តាច់លេច ID ចេញពីគ្នាដោយក្បៀស។" + +#: db/models/fields/related.py:620 +msgid "Hold down \"Control\", or \"Command\" on a Mac, to select more than one." +msgstr "សូមចុចប៉ូតុន \"Control\", ឬ \"Command\" ចំពោះកុំព្យូទ័រ Mac, ដើម្បីជ្រើសរើសច្រើនជាងមួយ។" + +#: db/models/fields/related.py:664 +#, python-format +msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid." +msgid_plural "Please enter valid %(self)s IDs. The values %(value)r are invalid." +msgstr[0] "សូមបំពេញលេខ %(self)s អោយបានត្រឹមត្រូវ។ តំលៃ %(value)r នេះមិនត្រឹមត្រូវទេ។" +msgstr[1] "សូមបំពេញលេខ %(self)s អោយបានត្រឹមត្រូវ។ តំលៃ %(value)r នេះមិនត្រឹមត្រូវទេ។" + +#: forms/__init__.py:381 +#, python-format +msgid "Ensure your text is less than %s character." +msgid_plural "Ensure your text is less than %s characters." +msgstr[0] "អត្ថបទរបស់អ្នកតិចជាង %s អក្សរ។" +msgstr[1] "" + +msgid "Ensure this value has at most %d characters." +msgstr "អត្ថបទរបស់អ្នកត្រូវតិចជាង %d អក្សរ។" + +#: newforms/fields.py:105 +#: newforms/fields.py:258 +#, python-format +msgid "Ensure this value has at least %d characters." +msgstr "អត្ថបទរបស់អ្នកត្រូវច្រើនជាង %d អក្សរ។" + +#: forms/__init__.py:386 +msgid "Line breaks are not allowed here." +msgstr "បន្ទាត់មិនអនុញ្ញាតនៅទីនេះទេ។" + +#: forms/__init__.py:487 +#: forms/__init__.py:560 +#: forms/__init__.py:599 +#, python-format +msgid "Select a valid choice; '%(data)s' is not in %(choices)s." +msgstr "សូមជ្រើសរើស ; '%(data)s' មិនមាននៅក្នុង %(choices)s" + +#: forms/__init__.py:663 +msgid "The submitted file is empty." +msgstr "ពុំមានឯកសារ។" + +#: forms/__init__.py:719 +msgid "Enter a whole number between -32,768 and 32,767." +msgstr "សូមបំពេញលេខចន្លោះពី -៣២.៧៦៧ និង ៣២.៧៦៧" + +#: forms/__init__.py:729 +msgid "Enter a positive number." +msgstr "សូមបំពេញចំនួនវិជ្ជមាន" + +#: forms/__init__.py:739 +msgid "Enter a whole number between 0 and 32,767." +msgstr "សូមបំពេញលេខចន្លោះពី ០ និង ៣២.៧៦៧" + +#: template/defaultfilters.py:401 +msgid "yes,no,maybe" +msgstr "យល់ព្រម មិនយល់ព្រម ប្រហែល" + +msgid "Your username and password didn't match. Please try again." +msgstr "ឈ្មោះជាសមាជិក និង ពាក្យសំងាត់មិនត្រឹមត្រូវ។" + +msgid "That e-mail address doesn't have an associated user account. Are you sure you've registered?" +msgstr "អ៊ីមែល នេះ មិនមាននៅក្នុងទិន្នន័យរបស់យើងខ្ញុំទេ។" + +msgid "5-30 alphanumeric characters or underscores." +msgstr "ត្រូវបំពេញអក្សរឡាតាំង (អក្សរ លេខ ឬ សញ្ញា _) ចំនួនពី៥ ទៅ ៣០។" + +msgid "Must be 5-30 alphanumeric characters or underscores." +msgstr "ត្រូចវបំពេញអក្សរឡាតាំង (អក្សរ លេខ ឬ សញ្ញា _) ចំនួនពី៥ ទៅ ៣០។" + +msgid "Confirm password" +msgstr "បំពេញពាក្យសំងាត់ម្តងទៀត" + +msgid "Please make sure your passwords match." +msgstr "ពាក្យសំងាត់មិនដូចគ្នា។" + +msgid "The username \"%s\" is already taken." +msgstr "ឈ្មោះជាសមាជិក \"%s\" ត្រូវបានគេយករួចហើយ។ សូមជ្រើសរើសឈ្មោះជាសមាជិកផ្សេងទៀត។" + +msgid "The email \"%s\" existed." +msgstr "អ៊ីមែល \"%s\" មានរួចហើយ។ សូមជ្រើសរើសអ៊ីមែលផ្សេងទៀត។" + +msgid "Audio" +msgstr "ចំរៀង" + +msgid "Video id" +msgstr "លេខ វីដេអូ" + +msgid "Video title" +msgstr "ចំណងជើើង វីដេអូ" + +msgid "Video length" +msgstr "ទំហំ វីដេអូ" + +msgid "Outside url" +msgstr "គេហទំព័រពីក្រៅ" + +msgid "Receive name" +msgstr "ឈ្មោះអ្នកទទួល" + +msgid "Receive email" +msgstr "អ៊ីមែលរបស់អ្នកទទួល" + +msgid "Message" +msgstr "អត្ថបទ" + +msgid "Sending date" +msgstr "បញ្ជូននៅថ្ងៃ" + +msgid "Received date" +msgstr "ថ្ងៃទទួល" + +msgid "Send as private message" +msgstr "ជាអត្ថបទផ្ទាល់ខ្លួន" + +msgid "Sent" +msgstr "បានបញ្ជូន" + +msgid "Question" +msgstr "សំណួរ" + +msgid "Answer" +msgstr "ចំលើយ" + +msgid "Tags" +msgstr "ប្រភេទ" + +msgid "Business" +msgstr "ពាណិជ្ជកម្ម" + +msgid "Beauty & Style" +msgstr "សោភ័ណភាព និង ម៉ូត" + +msgid "Education" +msgstr "ការអប់រំ" + +msgid "Environment" +msgstr "បរិដ្ឋាន" + +msgid "Family & Relationships" +msgstr "គ្រួសារ និង សេចក្តីស្នេហា" + +msgid "Food & Drink" +msgstr "ម្ហូប និង ភេសជ្ជៈ" + +msgid "General" +msgstr "ផ្សេងៗ" + +msgid "Games & Recreation" +msgstr "កំសាន្ត និង ហ្គេម" + +msgid "Health" +msgstr "សុខភាព" + +msgid "Pets" +msgstr "សត្វ ចិញ្ជឹម" + +msgid "Politics & Government" +msgstr "រដ្ឋាភិបាល និង នយោបាយ" + +msgid "Sports" +msgstr "កីឡា" + +msgid "Technology" +msgstr "បច្ចេកវិទ្សា" + +msgid "Travel" +msgstr "ដំណើរកំសាន្ត" + +msgid "Source" +msgstr "ដកស្រង់ចេញ" + +msgid "Left column" +msgstr "ជួរទីមួយ" + +msgid "Right column" +msgstr "ជួរទីពីរ" + +msgid "Start date" +msgstr "ចាប់ផ្តើមនៅ" + +msgid "End date" +msgstr "បញ្ជប់នៅ" + diff --git a/django/conf/locale/km/LC_MESSAGES/djangojs.mo b/django/conf/locale/km/LC_MESSAGES/djangojs.mo Binary files differnew file mode 100644 index 0000000000..61d8cdc8fc --- /dev/null +++ b/django/conf/locale/km/LC_MESSAGES/djangojs.mo diff --git a/django/conf/locale/km/LC_MESSAGES/djangojs.po b/django/conf/locale/km/LC_MESSAGES/djangojs.po new file mode 100644 index 0000000000..031b302dd6 --- /dev/null +++ b/django/conf/locale/km/LC_MESSAGES/djangojs.po @@ -0,0 +1,108 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: 01\n" +"Report-Msgid-Bugs-To: sengtha@e-khmer.com\n" +"POT-Creation-Date: 2007-01-15 15:43+0200\n" +"PO-Revision-Date: 2007-01-21 01:25+0900\n" +"Last-Translator: Chay Sengtha <sengtha@e-khmer.com>\n" +"Language-Team: Chay Sengtha <sengtha@e-khmer.com>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\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 "January February March April May June July August September October November December" + +#: contrib/admin/media/js/dateparse.js:27 +msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday" +msgstr "Sunday Monday Tuesday Wednesday Thursday Friday Saturday" + +#: contrib/admin/media/js/calendar.js:25 +msgid "S M T W T F S" +msgstr "S M T W T F S" + +#: 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 "ម៉ោង ៦ ព្រឹក" + +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83 +msgid "Noon" +msgstr "ពេលថ្ងែត្រង់" + +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87 +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168 +msgid "Cancel" +msgstr "លប់ចោល" + +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111 +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162 +msgid "Today" +msgstr "ថ្ងៃនេះ" + +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114 +msgid "Calendar" +msgstr "ប្រក្រតិទិន" + +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160 +msgid "Yesterday" +msgstr "ម្សិលមិញ" + +#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164 +msgid "Tomorrow" +msgstr "ថ្ងៃស្អែក" + diff --git a/django/conf/locale/ko/LC_MESSAGES/django.mo b/django/conf/locale/ko/LC_MESSAGES/django.mo Binary files differindex 58e97b496e..9b576377ae 100644 --- a/django/conf/locale/ko/LC_MESSAGES/django.mo +++ b/django/conf/locale/ko/LC_MESSAGES/django.mo diff --git a/django/conf/locale/ko/LC_MESSAGES/django.po b/django/conf/locale/ko/LC_MESSAGES/django.po index 476f7316ba..264c5f630d 100644 --- a/django/conf/locale/ko/LC_MESSAGES/django.po +++ b/django/conf/locale/ko/LC_MESSAGES/django.po @@ -825,12 +825,12 @@ msgstr "%d 자 이상 입력해 주세요." #: newforms/fields.py:130 #, python-format msgid "Ensure this value is less than or equal to %s." -msgstr "%s 자 이하로 입력해 주세요." +msgstr "%s 이하의 값을 입력해 주세요." #: newforms/fields.py:132 #, python-format msgid "Ensure this value is greater than or equal to %s." -msgstr "%s 자 이상 입력해 주세요." +msgstr "%s 이상의 값을 입력해 주세요." #: newforms/fields.py:165 msgid "Enter a valid date." diff --git a/django/conf/locale/no/LC_MESSAGES/django.mo b/django/conf/locale/no/LC_MESSAGES/django.mo Binary files differindex 7048e3079d..bd82c8952e 100644 --- a/django/conf/locale/no/LC_MESSAGES/django.mo +++ b/django/conf/locale/no/LC_MESSAGES/django.mo diff --git a/django/conf/locale/no/LC_MESSAGES/django.po b/django/conf/locale/no/LC_MESSAGES/django.po index ea388cfd81..5894d3b6e8 100644 --- a/django/conf/locale/no/LC_MESSAGES/django.po +++ b/django/conf/locale/no/LC_MESSAGES/django.po @@ -1,32 +1,1190 @@ -# translation of django.po to +# translation of django.po to norwegian # Copyright (C) 2005 and beyond -# This file is distributed under the same license as the PACKAGE package. +# This file is distributed under the same license as the Django package. # Espen Grindhaug <espen@grindhaug.org>, Nov 2005. # -# msgid "" msgstr "" "Project-Id-Version: django\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-05-16 10:12+0200\n" -"PO-Revision-Date: 2007-04-27 06:48+0200\n" -"Last-Translator: \n" -"Language-Team: <en@li.org>\n" +"PO-Revision-Date: 2007-08-29 18:22+0200\n" +"Last-Translator: jonklo\n" +"Language-Team: Norsk <no@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: KBabel 1.11.4\n" -#: contrib/comments/models.py:67 contrib/comments/models.py:166 +#: db/models/manipulators.py:309 +#, python-format +msgid "%(object)s with this %(type)s already exists for the given %(field)s." +msgstr "%(object)s med %(type)s finnes allerede for angitt %(field)s." + +#: db/models/manipulators.py:310 core/validators.py:275 +#: contrib/admin/views/main.py:342 contrib/admin/views/main.py:344 +#: contrib/admin/views/main.py:346 +msgid "and" +msgstr "og" + +#: db/models/fields/__init__.py:49 +#, python-format +msgid "%(optname)s with this %(fieldname)s already exists." +msgstr "%(optname)s med %(fieldname)s finnes allerede." + +#: db/models/fields/__init__.py:156 db/models/fields/__init__.py:313 +#: db/models/fields/__init__.py:721 db/models/fields/__init__.py:732 +#: oldforms/__init__.py:373 newforms/models.py:193 newforms/fields.py:92 +#: newforms/fields.py:490 newforms/fields.py:566 newforms/fields.py:577 +msgid "This field is required." +msgstr "Dette feltet er påkrevd." + +#: db/models/fields/__init__.py:411 +msgid "This value must be an integer." +msgstr "Denne verdien må være et heltall." + +#: db/models/fields/__init__.py:446 +msgid "This value must be either True or False." +msgstr "Denne verdien må være enten \"True\" eller \"False\"." + +#: db/models/fields/__init__.py:467 +msgid "This field cannot be null." +msgstr "Dette feltet kan ikke være null/tom." + +#: db/models/fields/__init__.py:501 core/validators.py:155 +msgid "Enter a valid date in YYYY-MM-DD format." +msgstr "Skriv inn en dato i ÅÅÅÅ-MM-DD format." + +#: db/models/fields/__init__.py:570 core/validators.py:164 +msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format." +msgstr "Skriv inn dato og tid i ÅÅÅÅ-MM-DD TT:MM format." + +#: db/models/fields/__init__.py:631 +msgid "This value must be a decimal number." +msgstr "Denne verdien må være et desimaltall." + +#: db/models/fields/__init__.py:741 +msgid "Enter a valid filename." +msgstr "Skriv inn et godkjent filnavn." + +#: db/models/fields/__init__.py:883 +msgid "This value must be either None, True or False." +msgstr "Denne verdien må være enten None, True eller False." + +#: db/models/fields/related.py:55 +#, python-format +msgid "Please enter a valid %s." +msgstr "Vennligst skriv inn en/et gyldig %s." + +#: db/models/fields/related.py:658 +msgid "Separate multiple IDs with commas." +msgstr "Separer flere ID-er med komma." + +#: db/models/fields/related.py:660 +msgid "" +"Hold down \"Control\", or \"Command\" on a Mac, to select more than one." +msgstr "" +"Hold nede \"Control\", eller \"Command\" på en Mac, for å velge mer enn en." + +#: db/models/fields/related.py:707 +#, python-format +msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid." +msgid_plural "" +"Please enter valid %(self)s IDs. The values %(value)r are invalid." +msgstr[0] "Skriv inn gyldige %(self)s ID-er. Verdien %(value)r er ikke gyldig." +msgstr[1] "" +"Skriv inn gyldige %(self)s ID-er. Verdiene %(value)r er ikke gyldige." + +#: conf/global_settings.py:39 +msgid "Arabic" +msgstr "Arabisk" + +#: conf/global_settings.py:40 +msgid "Bengali" +msgstr "Bengalsk" + +#: conf/global_settings.py:41 +msgid "Bulgarian" +msgstr "Bulgarsk" + +#: conf/global_settings.py:42 +msgid "Catalan" +msgstr "Katalansk" + +#: conf/global_settings.py:43 +msgid "Czech" +msgstr "Tsjekkisk" + +#: conf/global_settings.py:44 +msgid "Welsh" +msgstr "Walisisk" + +#: conf/global_settings.py:45 +msgid "Danish" +msgstr "Dansk" + +#: conf/global_settings.py:46 +msgid "German" +msgstr "Tysk" + +#: conf/global_settings.py:47 +msgid "Greek" +msgstr "Gresk" + +#: conf/global_settings.py:48 +msgid "English" +msgstr "Engelsk" + +#: conf/global_settings.py:49 +msgid "Spanish" +msgstr "Spansk" + +#: conf/global_settings.py:50 +msgid "Argentinean Spanish" +msgstr "Argentinsk spansk" + +#: conf/global_settings.py:51 +msgid "Persian" +msgstr "Persisk" + +#: conf/global_settings.py:52 +msgid "Finnish" +msgstr "Finsk" + +#: conf/global_settings.py:53 +msgid "French" +msgstr "Fransk" + +#: conf/global_settings.py:54 +msgid "Galician" +msgstr "Galisisk" + +#: conf/global_settings.py:55 +msgid "Hungarian" +msgstr "Ungarsk" + +#: conf/global_settings.py:56 +msgid "Hebrew" +msgstr "Hebraiske" + +#: conf/global_settings.py:57 +msgid "Croatian" +msgstr "Kroatisk" + +#: conf/global_settings.py:58 +msgid "Icelandic" +msgstr "Islandsk" + +#: conf/global_settings.py:59 +msgid "Italian" +msgstr "Italiensk" + +#: conf/global_settings.py:60 +msgid "Japanese" +msgstr "Japansk" + +#: conf/global_settings.py:61 +msgid "Korean" +msgstr "Koreansk" + +#: conf/global_settings.py:62 +msgid "Kannada" +msgstr "" + +#: conf/global_settings.py:63 +msgid "Latvian" +msgstr "Latvisk" + +#: conf/global_settings.py:64 +msgid "Macedonian" +msgstr "Makedonsk" + +#: conf/global_settings.py:65 +msgid "Dutch" +msgstr "Nederlandsk" + +#: conf/global_settings.py:66 +msgid "Norwegian" +msgstr "Norsk" + +#: conf/global_settings.py:67 +msgid "Polish" +msgstr "Polsk" + +#: conf/global_settings.py:68 +msgid "Portugese" +msgstr "Portugisisk" + +#: conf/global_settings.py:69 +msgid "Brazilian" +msgstr "Brasiliansk" + +#: conf/global_settings.py:70 +msgid "Romanian" +msgstr "Rumensk" + +#: conf/global_settings.py:71 +msgid "Russian" +msgstr "Russisk" + +#: conf/global_settings.py:72 +msgid "Slovak" +msgstr "Slovakisk" + +#: conf/global_settings.py:73 +msgid "Slovenian" +msgstr "Slovensk" + +#: conf/global_settings.py:74 +msgid "Serbian" +msgstr "Serbisk" + +#: conf/global_settings.py:75 +msgid "Swedish" +msgstr "Svensk" + +#: conf/global_settings.py:76 +msgid "Tamil" +msgstr "" + +#: conf/global_settings.py:77 +msgid "Telugu" +msgstr "" + +#: conf/global_settings.py:78 +msgid "Turkish" +msgstr "Tyrkisk" + +#: conf/global_settings.py:79 +msgid "Ukrainian" +msgstr "Ukrainsk" + +#: conf/global_settings.py:80 +msgid "Simplified Chinese" +msgstr "Simplifisert kinesisk" + +#: conf/global_settings.py:81 +msgid "Traditional Chinese" +msgstr "Tradisjonell kinesisk" + +#: core/validators.py:71 +msgid "This value must contain only letters, numbers and underscores." +msgstr "Dette feltet kan bare inneholde bokstaver, nummer eller understreker." + +#: core/validators.py:75 +msgid "" +"This value must contain only letters, numbers, underscores, dashes or " +"slashes." +msgstr "" +"Dette feltet kan bare inneholde bokstaver, nummer, understreker, bindestreker" +" eller skråstreker." + +#: core/validators.py:79 +msgid "This value must contain only letters, numbers, underscores or hyphens." +msgstr "Dette feltet kan bare inneholde bokstaver, nummer, understreker eller " +"bindestreker." + +#: core/validators.py:83 +msgid "Uppercase letters are not allowed here." +msgstr "Store bokstaver er ikke tillatt her." + +#: core/validators.py:87 +msgid "Lowercase letters are not allowed here." +msgstr "Små bokstaver er ikke tillatt her." + +#: core/validators.py:94 +msgid "Enter only digits separated by commas." +msgstr "Skriv inn bare tall, adskilt med komma." + +#: core/validators.py:106 +msgid "Enter valid e-mail addresses separated by commas." +msgstr "Skriv inn e-postadresser, adskilt med komma." + +#: core/validators.py:110 +msgid "Please enter a valid IP address." +msgstr "Vennligst skriv inn en gyldig IP-adresse." + +#: core/validators.py:114 +msgid "Empty values are not allowed here." +msgstr "Dette felte kan ikke være tomt." + +#: core/validators.py:118 +msgid "Non-numeric characters aren't allowed here." +msgstr "Dette feltet kan kun bestå av tall." + +#: core/validators.py:122 +msgid "This value can't be comprised solely of digits." +msgstr "Dette feltet kan ikke bare bestå av nummer." + +#: core/validators.py:127 newforms/fields.py:142 +msgid "Enter a whole number." +msgstr "Skriv inn et helt nummer." + +#: core/validators.py:131 +msgid "Only alphabetical characters are allowed here." +msgstr "Bare alfabetiske tegn er tillatt her." + +#: core/validators.py:146 +msgid "Year must be 1900 or later." +msgstr "År må være 1900 eller senere." + +#: core/validators.py:150 +#, python-format +msgid "Invalid date: %s" +msgstr "Ugyldig dato: %s" + +#: core/validators.py:160 +msgid "Enter a valid time in HH:MM format." +msgstr "Skriv inn tiden i TT:MM format." + +#: core/validators.py:169 newforms/fields.py:336 +msgid "Enter a valid e-mail address." +msgstr "Skriv inn en godkjent e-postadresse." + +#: core/validators.py:181 core/validators.py:461 oldforms/__init__.py:686 +#: newforms/fields.py:376 +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Ingen fil ble " + +#: core/validators.py:185 newforms/fields.py:397 +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Last opp et gyldig bilde. Filen du lastet opp var ikke et bilde, eller så var" +" det det ødelagt." + +#: core/validators.py:192 +#, python-format +msgid "The URL %s does not point to a valid image." +msgstr "Internettadressen %s peker ikke til et gyldig bilde." + +#: core/validators.py:196 +#, python-format +msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid." +msgstr "" +"Telefonnummeret må være i XXX-XXX-XXXX format. \"%s\" er ugyldig." + +#: core/validators.py:204 +#, python-format +msgid "The URL %s does not point to a valid QuickTime video." +msgstr "Internettadressen %s peker ikke til en gyldig QuickTime-video." + +#: core/validators.py:208 +msgid "A valid URL is required." +msgstr "En gyldig internettadresse er påkrevd." + +#: core/validators.py:222 +#, python-format +msgid "" +"Valid HTML is required. Specific errors are:\n" +"%s" +msgstr "" +"Gyldig HTML er påkrevd. Feilene var:\n" +"%s" + +#: core/validators.py:229 +#, python-format +msgid "Badly formed XML: %s" +msgstr "Ikke velformet XML: %s" + +#: core/validators.py:246 +#, python-format +msgid "Invalid URL: %s" +msgstr "Ugyldig URL: %s" + +#: core/validators.py:251 core/validators.py:253 +#, python-format +msgid "The URL %s is a broken link." +msgstr "Internettadresse %s fører til en side som ikke eksisterer." + +#: core/validators.py:259 +msgid "Enter a valid U.S. state abbreviation." +msgstr "Skriv inn en godkjent amerikansk delstatsforkortelse." + +#: core/validators.py:273 +#, python-format +msgid "Watch your mouth! The word %s is not allowed here." +msgid_plural "Watch your mouth! The words %s are not allowed here." +msgstr[0] "Pass munnen din! Ordet %s er ikke tillatt her." +msgstr[1] "Pass munnen din! Ordene %s er ikke tillatt her." + +#: core/validators.py:280 +#, python-format +msgid "This field must match the '%s' field." +msgstr "Dette feltet må være det samme som i '%s'-feltet." + +#: core/validators.py:299 +msgid "Please enter something for at least one field." +msgstr "Vennligst skriv inn noe i minst et felt." + +#: core/validators.py:308 core/validators.py:319 +msgid "Please enter both fields or leave them both empty." +msgstr "Vennligst skriv inn noe i begge felta, eller la dem stå blanke." + +#: core/validators.py:327 +#, python-format +msgid "This field must be given if %(field)s is %(value)s" +msgstr "Dette feltet må bare brukes hvis %(field)s er lik %(value)s" + +#: core/validators.py:340 +#, python-format +msgid "This field must be given if %(field)s is not %(value)s" +msgstr "Dette feltet må bare brukes hvis %(field)s ikke er lik %(value)s" + +#: core/validators.py:359 +msgid "Duplicate values are not allowed." +msgstr "Like verdier er ikke tillatt." + +#: core/validators.py:374 +#, python-format +msgid "This value must be between %(lower)s and %(upper)s." +msgstr "Denne verdien må være mellom %(lower)s og %(upper)s." + +#: core/validators.py:376 +#, python-format +msgid "This value must be at least %s." +msgstr "Denne verdien må minst være %s." + +#: core/validators.py:378 +#, python-format +msgid "This value must be no more than %s." +msgstr "Denne verdien kan ikke være mer enn %s." + +#: core/validators.py:414 +#, python-format +msgid "This value must be a power of %s." +msgstr "Denne verdien må være et kvadrat av %s." + +#: core/validators.py:424 +msgid "Please enter a valid decimal number." +msgstr "Vennligst skriv inn et gyldig desimaltall." + +#: core/validators.py:431 +#, python-format +msgid "Please enter a valid decimal number with at most %s total digit." +msgid_plural "" +"Please enter a valid decimal number with at most %s total digits." +msgstr[0] "Skriv inn et desimaltall med maks %s siffer." +msgstr[1] "Skriv inn et desimaltall med maks %s siffer." + +#: core/validators.py:434 +#, python-format +msgid "" +"Please enter a valid decimal number with a whole part of at most %s digit." +msgid_plural "" +"Please enter a valid decimal number with a whole part of at most %s digits." +msgstr[0] "Skriv inn et desimaltall hvor heltallsdelen er maks %s siffer." +msgstr[1] "Skriv inn et desimaltall hvor heltallsdelen er maks %s siffer." + +#: core/validators.py:437 +#, python-format +msgid "Please enter a valid decimal number with at most %s decimal place." +msgid_plural "" +"Please enter a valid decimal number with at most %s decimal places." +msgstr[0] "Skriv inn et desimaltall med maks %s siffer bak komma." +msgstr[1] "Skriv inn et desimaltall med maks %s siffer bak komma." + +#: core/validators.py:445 +msgid "Please enter a valid floating point number." +msgstr "Vennligst skriv inn et gyldig flyttall." + +#: core/validators.py:454 +#, python-format +msgid "Make sure your uploaded file is at least %s bytes big." +msgstr "Vær sikker på at fila du prøver å laste opp minst er %s bytes stor." + +#: core/validators.py:455 +#, python-format +msgid "Make sure your uploaded file is at most %s bytes big." +msgstr "Vær sikker på at fila du prøver å laste opp ikke er mer enn %s bytes" +" stor." + +#: core/validators.py:472 +msgid "The format for this field is wrong." +msgstr "Formatet i dette feltet er feil." + +#: core/validators.py:487 +msgid "This field is invalid." +msgstr "Dette feltet er ugyldig." + +#: core/validators.py:523 +#, python-format +msgid "Could not retrieve anything from %s." +msgstr "Klarte ikke å hente noe fra %s." + +#: core/validators.py:526 +#, python-format +msgid "" +"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'." +msgstr "" +"Internettadressen %(url)s returnerte den ugyldige Content-Type-headeren " +"'%(contenttype)s'." + +#: core/validators.py:559 +#, python-format +msgid "" +"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with " +"\"%(start)s\".)" +msgstr "" +"Vennligst lukk taggen %(tag)s på linje %(line)s. (Linjen starer med " +"\"%(start)s\".)" + +#: core/validators.py:563 +#, python-format +msgid "" +"Some text starting on line %(line)s is not allowed in that context. (Line " +"starts with \"%(start)s\".)" +msgstr "" +"Noe av teksten som starter på linje %(line)s er ikke tillatt. (Linjen " +"starter med \"%(start)s\".)" + +#: core/validators.py:568 +#, python-format +msgid "" +"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%" +"(start)s\".)" +msgstr "" +"\"%(attr)s\" på linje %(line)s er et ugyldig attributt. (Linjen starter " +"med \"%(start)s\".)" + +#: core/validators.py:573 +#, python-format +msgid "" +"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%" +"(start)s\".)" +msgstr "" +"\"<%(tag)s>\" på linje %(line)s er et ugyldig element. (Linjen starter med " +"\"%(start)s\".)" + +#: core/validators.py:577 +#, python-format +msgid "" +"A tag on line %(line)s is missing one or more required attributes. (Line " +"starts with \"%(start)s\".)" +msgstr "" +"Et element på linje %(line)s mangler et av de påkrevde attributtene. (Linjen " +"starter med \"%(start)s\".)" + +#: core/validators.py:582 +#, python-format +msgid "" +"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line " +"starts with \"%(start)s\".)" +msgstr "" +"\"%(attr)s\"-attributtet på linje %(line)s har en ugyldig verdi. (Linjen " +"starter med \"%(start)s\".)" + +#: views/generic/create_update.py:43 +#, python-format +msgid "The %(verbose_name)s was created successfully." +msgstr "%(verbose_name)s ble opprettet." + +#: views/generic/create_update.py:117 +#, python-format +msgid "The %(verbose_name)s was updated successfully." +msgstr "%(verbose_name)s ble oppdatert." + +#: views/generic/create_update.py:184 +#, python-format +msgid "The %(verbose_name)s was deleted." +msgstr "%(verbose_name)s ble slettet." + +#: utils/dates.py:6 +msgid "Monday" +msgstr "Mandag" + +#: utils/dates.py:6 +msgid "Tuesday" +msgstr "Tirsdag" + +#: utils/dates.py:6 +msgid "Wednesday" +msgstr "Onsdag" + +#: utils/dates.py:6 +msgid "Thursday" +msgstr "Torsdag" + +#: utils/dates.py:6 +msgid "Friday" +msgstr "Fredag" + +#: utils/dates.py:7 +msgid "Saturday" +msgstr "Lørdag" + +#: utils/dates.py:7 +msgid "Sunday" +msgstr "Søndag" + +#: utils/dates.py:10 +msgid "Mon" +msgstr "Man" + +#: utils/dates.py:10 +msgid "Tue" +msgstr "Tirs" + +#: utils/dates.py:10 +msgid "Wed" +msgstr "Ons" + +#: utils/dates.py:10 +msgid "Thu" +msgstr "Tors" + +#: utils/dates.py:10 +msgid "Fri" +msgstr "Fre" + +#: utils/dates.py:11 +msgid "Sat" +msgstr "Lør" + +#: utils/dates.py:11 +msgid "Sun" +msgstr "Søn" + +#: utils/dates.py:18 +msgid "January" +msgstr "Januar" + +#: utils/dates.py:18 +msgid "February" +msgstr "Februar" + +#: utils/dates.py:18 utils/dates.py:31 +msgid "March" +msgstr "Mars" + +#: utils/dates.py:18 utils/dates.py:31 +msgid "April" +msgstr "April" + +#: utils/dates.py:18 utils/dates.py:31 +msgid "May" +msgstr "Mai" + +#: utils/dates.py:18 utils/dates.py:31 +msgid "June" +msgstr "Juni" + +#: utils/dates.py:19 utils/dates.py:31 +msgid "July" +msgstr "Juli" + +#: utils/dates.py:19 +msgid "August" +msgstr "August" + +#: utils/dates.py:19 +msgid "September" +msgstr "September" + +#: utils/dates.py:19 +msgid "October" +msgstr "Oktober" + +#: utils/dates.py:19 +msgid "November" +msgstr "November" + +#: utils/dates.py:20 +msgid "December" +msgstr "Desember" + +#: utils/dates.py:23 +msgid "jan" +msgstr "jan" + +#: utils/dates.py:23 +msgid "feb" +msgstr "feb" + +#: utils/dates.py:23 +msgid "mar" +msgstr "mar" + +#: utils/dates.py:23 +msgid "apr" +msgstr "apr" + +#: utils/dates.py:23 +msgid "may" +msgstr "mai" + +#: utils/dates.py:23 +msgid "jun" +msgstr "jun" + +#: utils/dates.py:24 +msgid "jul" +msgstr "jul" + +#: utils/dates.py:24 +msgid "aug" +msgstr "aug" + +#: utils/dates.py:24 +msgid "sep" +msgstr "sep" + +#: utils/dates.py:24 +msgid "oct" +msgstr "okt" + +#: utils/dates.py:24 +msgid "nov" +msgstr "nov" + +#: utils/dates.py:24 +msgid "dec" +msgstr "des" + +#: utils/dates.py:31 +msgid "Jan." +msgstr "Jan." + +#: utils/dates.py:31 +msgid "Feb." +msgstr "Feb." + +#: utils/dates.py:32 +msgid "Aug." +msgstr "Aug." + +#: utils/dates.py:32 +msgid "Sept." +msgstr "Sept." + +#: utils/dates.py:32 +msgid "Oct." +msgstr "Okt." + +#: utils/dates.py:32 +msgid "Nov." +msgstr "Nov." + +#: utils/dates.py:32 +msgid "Dec." +msgstr "Des." + +#: utils/timesince.py:12 +msgid "year" +msgid_plural "years" +msgstr[0] "år" +msgstr[1] "år" + +#: utils/timesince.py:13 +msgid "month" +msgid_plural "months" +msgstr[0] "måned" +msgstr[1] "måndeder" + +#: utils/timesince.py:14 +msgid "week" +msgid_plural "weeks" +msgstr[0] "uke" +msgstr[1] "uker" + +#: utils/timesince.py:15 +msgid "day" +msgid_plural "days" +msgstr[0] "dag" +msgstr[1] "dager" + +#: utils/timesince.py:16 +msgid "hour" +msgid_plural "hours" +msgstr[0] "time" +msgstr[1] "timer" + +#: utils/timesince.py:17 +msgid "minute" +msgid_plural "minutes" +msgstr[0] "minutt" +msgstr[1] "minutter" + +#: utils/timesince.py:39 +#, python-format +msgid "%(number)d %(type)s" +msgstr "" + +#: utils/timesince.py:45 +#, python-format +msgid ", %(number)d %(type)s" +msgstr "" + +#: utils/text.py:127 +msgid "or" +msgstr "eller" + +#: utils/dateformat.py:41 +msgid "p.m." +msgstr "" + +#: utils/dateformat.py:42 +msgid "a.m." +msgstr "" + +#: utils/dateformat.py:47 +msgid "PM" +msgstr "" + +#: utils/dateformat.py:48 +msgid "AM" +msgstr "" + +#: utils/dateformat.py:97 +msgid "midnight" +msgstr "midnatt" + +#: utils/dateformat.py:99 +msgid "noon" +msgstr "middag" + +#: utils/translation/trans_real.py:391 +msgid "DATE_FORMAT" +msgstr "j. M Y" + +#: utils/translation/trans_real.py:392 +msgid "DATETIME_FORMAT" +msgstr "h:i, j. M Y" + +#: utils/translation/trans_real.py:393 +msgid "TIME_FORMAT" +msgstr "h:i" + +#: utils/translation/trans_real.py:409 +msgid "YEAR_MONTH_FORMAT" +msgstr "Y M" + +#: utils/translation/trans_real.py:410 +msgid "MONTH_DAY_FORMAT" +msgstr "j. M" + +#: contrib/contenttypes/models.py:37 +msgid "python model class name" +msgstr "python modell klasse navn" + +#: contrib/contenttypes/models.py:40 +msgid "content type" +msgstr "innholdstype" + +#: contrib/contenttypes/models.py:41 +msgid "content types" +msgstr "innholdstyper" + +#: contrib/humanize/templatetags/humanize.py:20 +msgid "th" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:20 +msgid "st" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:20 +msgid "nd" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:20 +msgid "rd" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:50 +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f million" +msgstr[1] "%(value).1f millioner" + +#: contrib/humanize/templatetags/humanize.py:53 +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f milliard" +msgstr[1] "%(value).1f milliarder" + +#: contrib/humanize/templatetags/humanize.py:56 +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f billion" +msgstr[1] "%(value).1f billioner" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "one" +msgstr "en" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "two" +msgstr "to" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "three" +msgstr "tre" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "four" +msgstr "fire" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "five" +msgstr "fem" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "six" +msgstr "seks" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "seven" +msgstr "sju" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "eight" +msgstr "åtte" + +#: contrib/humanize/templatetags/humanize.py:71 +msgid "nine" +msgstr "ni" + +#: contrib/humanize/templatetags/humanize.py:90 +msgid "today" +msgstr "i dag" + +#: contrib/humanize/templatetags/humanize.py:92 +msgid "tomorrow" +msgstr "i morgen" + +#: contrib/humanize/templatetags/humanize.py:94 +msgid "yesterday" +msgstr "i går" + +#: contrib/auth/views.py:47 +msgid "Logged out" +msgstr "Logget ut" + +#: contrib/auth/models.py:53 contrib/auth/models.py:73 +msgid "name" +msgstr "navn" + +#: contrib/auth/models.py:55 +msgid "codename" +msgstr "kodenavn" + +#: contrib/auth/models.py:58 +msgid "permission" +msgstr "rettighet" + +#: contrib/auth/models.py:59 contrib/auth/models.py:74 +msgid "permissions" +msgstr "rettigheter" + +#: contrib/auth/models.py:77 +msgid "group" +msgstr "gruppe" + +#: contrib/auth/models.py:78 contrib/auth/models.py:121 +msgid "groups" +msgstr "grupper" + +#: contrib/auth/models.py:111 +msgid "username" +msgstr "brukernavn" + +#: contrib/auth/models.py:111 +msgid "" +"Required. 30 characters or fewer. Alphanumeric characters only (letters, " +"digits and underscores)." +msgstr "Påkrevd. 30 tegn eller færre. Kun alfanumeriske tegn (bokstaver, " +"tall og understreker)." + +#: contrib/auth/models.py:112 +msgid "first name" +msgstr "fornavn" + +#: contrib/auth/models.py:113 +msgid "last name" +msgstr "etternavn" + +#: contrib/auth/models.py:114 +msgid "e-mail address" +msgstr "e-postadresse" + +#: contrib/auth/models.py:115 +msgid "password" +msgstr "passord" + +#: contrib/auth/models.py:115 +msgid "" +"Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change " +"password form</a>." +msgstr "Bruk '[algo]$[salt]$[hexdigest]' eller <a href=\"password/\">endre " +"passord-skjemaet</a>." + +#: contrib/auth/models.py:116 +msgid "staff status" +msgstr "administrasjonsstatus" + +#: contrib/auth/models.py:116 +msgid "Designates whether the user can log into this admin site." +msgstr "Bestemmer om brukeren kan logge inn på disse administrasjonssidene." + +#: contrib/auth/models.py:117 +msgid "active" +msgstr "aktiv" + +#: contrib/auth/models.py:117 +msgid "" +"Designates whether this user can log into the Django admin. Unselect this " +"instead of deleting accounts." +msgstr "Bestemmer om brukeren kan logge inn på disse sidene. Huk av denne " +"i stedet for å slette kontoen." + +#: contrib/auth/models.py:118 +msgid "superuser status" +msgstr "superbruker" + +#: contrib/auth/models.py:118 +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "Bestemmer om denne brukeren har alle rettigheter, uten å sette de " +"eksplisitt." + +#: contrib/auth/models.py:119 +msgid "last login" +msgstr "siste innlogging" + +#: contrib/auth/models.py:120 +msgid "date joined" +msgstr "registreringsdato" + +#: contrib/auth/models.py:122 +msgid "" +"In addition to the permissions manually assigned, this user will also get " +"all permissions granted to each group he/she is in." +msgstr "" +"I tillegg til rettighetene som blir gitt manuelt, får brukeren også full " +"tilgang til rettighetene til gruppene han/hun er i." + +#: contrib/auth/models.py:123 +msgid "user permissions" +msgstr "Brukerrettigheter" + +#: contrib/auth/models.py:127 +msgid "user" +msgstr "bruker" + +#: contrib/auth/models.py:128 +msgid "users" +msgstr "brukere" + +#: contrib/auth/models.py:134 +msgid "Personal info" +msgstr "Personlig informasjon" + +#: contrib/auth/models.py:135 +msgid "Permissions" +msgstr "Rettigheter" + +#: contrib/auth/models.py:136 +msgid "Important dates" +msgstr "Viktige datoer" + +#: contrib/auth/models.py:137 +msgid "Groups" +msgstr "Grupper" + +#: contrib/auth/models.py:288 +msgid "message" +msgstr "melding" + +#: contrib/auth/forms.py:17 contrib/auth/forms.py:138 +msgid "The two password fields didn't match." +msgstr "De to passordfeltene er ikke like." + +#: contrib/auth/forms.py:25 +msgid "A user with that username already exists." +msgstr "Det eksisterer en bruker med dette brukernavnet." + +#: contrib/auth/forms.py:53 +msgid "" +"Your Web browser doesn't appear to have cookies enabled. Cookies are " +"required for logging in." +msgstr "" +"Din nettleser ser ikke ut til å støtte informasjonskapsler (cookies). " +"Informasjonskapsler er påkrevd for å logge inn." + +#: contrib/auth/forms.py:60 contrib/admin/views/decorators.py:10 +msgid "" +"Please enter a correct username and password. Note that both fields are case-" +"sensitive." +msgstr "" +"Vennligst angi korrekt brukernavn og passord. Merk at det er forskjell på " +"små og store bokstaver." + +#: contrib/auth/forms.py:62 +msgid "This account is inactive." +msgstr "Denne kontoen er inaktiv." + +#: contrib/auth/forms.py:84 +msgid "" +"That e-mail address doesn't have an associated user account. Are you sure " +"you've registered?" +msgstr "Den oppgitte e-postadressen er ikke registrert hos oss. Er du sikker" +"på at du har en konto her?" + +#: contrib/auth/forms.py:117 +msgid "The two 'new password' fields didn't match." +msgstr "De to feltene for nytt passord er ikke like." + +#: contrib/auth/forms.py:124 +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Ditt gamle passord er feil. Vennligst prøv igjen." + +#: contrib/redirects/models.py:7 +msgid "redirect from" +msgstr "omadresser fra" + +#: contrib/redirects/models.py:8 +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" +"Dette burde vært en fullstendig sti, uten domenenavnet. Eksempel: '/" +"nyheter/les/" + +#: contrib/redirects/models.py:9 +msgid "redirect to" +msgstr "omadresser til" + +#: contrib/redirects/models.py:10 +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"Dette kan enten være en fullstendig sti (som over), eller en hel " +"internettadresse som starter med 'http://'" + +#: contrib/redirects/models.py:13 +msgid "redirect" +msgstr "omadressering" + +#: contrib/redirects/models.py:14 +msgid "redirects" +msgstr "omadresserelser" + +#: contrib/comments/models.py:67 contrib/comments/models.py:169 msgid "object ID" -msgstr "objekt ID" +msgstr "objekt-ID" #: contrib/comments/models.py:68 msgid "headline" msgstr "overskrift" #: contrib/comments/models.py:69 contrib/comments/models.py:90 -#: contrib/comments/models.py:167 +#: contrib/comments/models.py:170 msgid "comment" msgstr "kommentar" @@ -66,17 +1224,17 @@ msgstr "rangering #8" msgid "is valid rating" msgstr "er gyldig rangering" -#: contrib/comments/models.py:83 contrib/comments/models.py:169 +#: contrib/comments/models.py:83 contrib/comments/models.py:172 msgid "date/time submitted" msgstr "dato/tid for innsendelse" -#: contrib/comments/models.py:84 contrib/comments/models.py:170 +#: contrib/comments/models.py:84 contrib/comments/models.py:173 msgid "is public" msgstr "er tilgjengelig for alle" -#: contrib/comments/models.py:85 contrib/admin/views/doc.py:289 +#: contrib/comments/models.py:85 contrib/admin/views/doc.py:306 msgid "IP address" -msgstr "IP adresse" +msgstr "IP-adresse" #: contrib/comments/models.py:86 msgid "is removed" @@ -86,17 +1244,19 @@ msgstr "er fjernet" msgid "" "Check this box if the comment is inappropriate. A \"This comment has been " "removed\" message will be displayed instead." -msgstr "Aktiver denne avkryssningsboksen hvis kommentaren er upasende. Beskjeden \"Denne kommentaren er blitt fjernet\" vil bli vist istedet." +msgstr "" +"Huk av denne avkryssningsboksen hvis kommentaren er upasende. Beskjeden " +"\"Denne kommentaren er blitt fjernet\" vil bli vist istedet." #: contrib/comments/models.py:91 msgid "comments" msgstr "kommentarer" -#: contrib/comments/models.py:131 contrib/comments/models.py:207 +#: contrib/comments/models.py:134 contrib/comments/models.py:213 msgid "Content object" msgstr "innholdsobjekt" -#: contrib/comments/models.py:159 +#: contrib/comments/models.py:162 #, python-format msgid "" "Posted by %(user)s at %(date)s\n" @@ -111,48 +1271,48 @@ msgstr "" "\n" "http://%(domain)s%(url)s" -#: contrib/comments/models.py:168 +#: contrib/comments/models.py:171 msgid "person's name" msgstr "personens navn" -#: contrib/comments/models.py:171 +#: contrib/comments/models.py:174 msgid "ip address" -msgstr "IP adresse" +msgstr "IP-adresse" -#: contrib/comments/models.py:173 +#: contrib/comments/models.py:176 msgid "approved by staff" msgstr "godkjent av moderator" -#: contrib/comments/models.py:176 +#: contrib/comments/models.py:179 msgid "free comment" msgstr "åpen kommentar" -#: contrib/comments/models.py:177 +#: contrib/comments/models.py:180 msgid "free comments" msgstr "åpne kommentarer" -#: contrib/comments/models.py:233 +#: contrib/comments/models.py:239 msgid "score" msgstr "poeng" -#: contrib/comments/models.py:234 +#: contrib/comments/models.py:240 msgid "score date" -msgstr "poeng dato" +msgstr "poengdato" -#: contrib/comments/models.py:237 +#: contrib/comments/models.py:243 msgid "karma score" -msgstr "karma poeng" +msgstr "karmapoeng" -#: contrib/comments/models.py:238 +#: contrib/comments/models.py:244 msgid "karma scores" -msgstr "karma poeng" +msgstr "karmapoeng" -#: contrib/comments/models.py:242 +#: contrib/comments/models.py:248 #, python-format msgid "%(score)d rating by %(user)s" msgstr "%(score)d rangering av %(user)s" -#: contrib/comments/models.py:258 +#: contrib/comments/models.py:264 #, python-format msgid "" "This comment was flagged by %(user)s:\n" @@ -163,55 +1323,58 @@ msgstr "" "\n" "%(text)s" -#: contrib/comments/models.py:265 +#: contrib/comments/models.py:271 msgid "flag date" -msgstr "flagg dato" +msgstr "flaggdato" -#: contrib/comments/models.py:268 +#: contrib/comments/models.py:274 msgid "user flag" msgstr "brukerflag" -#: contrib/comments/models.py:269 +#: contrib/comments/models.py:275 msgid "user flags" msgstr "brukerflag" -#: contrib/comments/models.py:273 +#: contrib/comments/models.py:279 #, python-format msgid "Flag by %r" msgstr "Flagg med %r" -#: contrib/comments/models.py:278 +#: contrib/comments/models.py:284 msgid "deletion date" -msgstr "fjernet dato" +msgstr "dato fjernet" -#: contrib/comments/models.py:280 +#: contrib/comments/models.py:286 msgid "moderator deletion" msgstr "fjernet av moderator" -#: contrib/comments/models.py:281 +#: contrib/comments/models.py:287 msgid "moderator deletions" msgstr "fjernet av moderator" -#: contrib/comments/models.py:285 +#: contrib/comments/models.py:291 #, python-format msgid "Moderator deletion by %r" msgstr "Fjernet av moderator med %r" -#: contrib/comments/views/karma.py:19 +#: contrib/comments/views/karma.py:20 msgid "Anonymous users cannot vote" msgstr "Anonyme brukere kan ikke stemme" -#: contrib/comments/views/karma.py:23 +#: contrib/comments/views/karma.py:24 msgid "Invalid comment ID" -msgstr "Ikke gyldig kommentar ID" +msgstr "Ikke gyldig kommentar-ID" -#: contrib/comments/views/karma.py:25 +#: contrib/comments/views/karma.py:26 msgid "No voting for yourself" msgstr "Du kan ikke stemme på deg selv" #: contrib/comments/views/comments.py:28 -msgid "This rating is required because you've entered at least one other rating." -msgstr "Denne rangeringen er påkrevd fordi du har rangert en eller flere ting fra før " +msgid "" +"This rating is required because you've entered at least one other rating." +msgstr "" +"Denne rangeringen er påkrevd, fordi du har rangert en eller flere ting fra " +"før " #: contrib/comments/views/comments.py:112 #, python-format @@ -248,31 +1411,45 @@ msgstr "" "%(text)s" #: contrib/comments/views/comments.py:189 -#: contrib/comments/views/comments.py:280 +#: contrib/comments/views/comments.py:281 msgid "Only POSTs are allowed" -msgstr "Bare POST er tillatt" +msgstr "Kun POST er tillatt" #: contrib/comments/views/comments.py:193 -#: contrib/comments/views/comments.py:284 +#: contrib/comments/views/comments.py:285 msgid "One or more of the required fields wasn't submitted" msgstr "En eller flere av feltene som er påkrevd ble ikke sendt." #: contrib/comments/views/comments.py:197 -#: contrib/comments/views/comments.py:286 +#: contrib/comments/views/comments.py:287 msgid "Somebody tampered with the comment form (security violation)" -msgstr "Noen har endret på komentar feltene (sikkerhets advarsel)" +msgstr "Noen har endret på komentarfeltene (sikkerhetsadvarsel)" #: contrib/comments/views/comments.py:207 -#: contrib/comments/views/comments.py:292 +#: contrib/comments/views/comments.py:293 msgid "" "The comment form had an invalid 'target' parameter -- the object ID was " "invalid" -msgstr "Skjemaet hadde en ugyldig verdi - objekt IDen var ugyldig" +msgstr "Skjemaet hadde en ugyldig 'target'-verdi - objekt-IDen var ugyldig" -#: contrib/comments/views/comments.py:257 -#: contrib/comments/views/comments.py:321 +#: contrib/comments/views/comments.py:258 +#: contrib/comments/views/comments.py:322 msgid "The comment form didn't provide either 'preview' or 'post'" -msgstr "Kommentar skjemaet returnerte ikke et 'forhåndsvisning' eller 'post' objekt" +msgstr "Kommentarskjemaet la ikke ved 'preview'- eller 'post'-element" + +#: contrib/comments/templates/comments/freeform.html:4 +msgid "Your name:" +msgstr "Ditt navn:" + +#: contrib/comments/templates/comments/freeform.html:5 +#: contrib/comments/templates/comments/form.html:28 +msgid "Comment:" +msgstr "Kommentar:" + +#: contrib/comments/templates/comments/freeform.html:10 +#: contrib/comments/templates/comments/form.html:35 +msgid "Preview comment" +msgstr "Forhåndvis kommentar" #: contrib/comments/templates/comments/form.html:6 #: contrib/comments/templates/comments/form.html:8 @@ -281,20 +1458,12 @@ msgid "Username:" msgstr "Brukernavn:" #: contrib/comments/templates/comments/form.html:6 -#: contrib/admin/templates/admin/login.html:20 -msgid "Password:" -msgstr "Passord:" - -#: contrib/comments/templates/comments/form.html:6 -msgid "Forgotten your password?" -msgstr "Har du glemt passordet ditt ?" - -#: contrib/comments/templates/comments/form.html:8 #: contrib/admin/templates/admin/object_history.html:3 #: contrib/admin/templates/admin/change_list.html:5 -#: contrib/admin/templates/admin/base.html:23 -#: contrib/admin/templates/admin/delete_confirmation.html:3 #: contrib/admin/templates/admin/change_form.html:10 +#: contrib/admin/templates/admin/base.html:25 +#: contrib/admin/templates/admin/delete_confirmation.html:3 +#: contrib/admin/templates/admin/auth/user/change_password.html:9 #: contrib/admin/templates/registration/password_change_done.html:3 #: contrib/admin/templates/registration/password_change_form.html:3 #: contrib/admin/templates/admin_doc/bookmarklets.html:4 @@ -308,7 +1477,16 @@ msgstr "Har du glemt passordet ditt ?" #: contrib/admin/templates/admin_doc/index.html:4 #: contrib/admin/templates/admin_doc/model_index.html:5 msgid "Log out" -msgstr "Log ut" +msgstr "Logg ut" + +#: contrib/comments/templates/comments/form.html:8 +#: contrib/admin/templates/admin/login.html:20 +msgid "Password:" +msgstr "Passord:" + +#: contrib/comments/templates/comments/form.html:8 +msgid "Forgotten your password?" +msgstr "Har du glemt passordet ditt?" #: contrib/comments/templates/comments/form.html:12 msgid "Ratings" @@ -326,23 +1504,96 @@ msgstr "Valgfri" #: contrib/comments/templates/comments/form.html:23 msgid "Post a photo" -msgstr "Send et foto" +msgstr "Send et bilde" -#: contrib/comments/templates/comments/form.html:27 -#: contrib/comments/templates/comments/freeform.html:5 -msgid "Comment:" -msgstr "Kommentar:" +#: contrib/flatpages/models.py:7 contrib/admin/views/doc.py:317 +msgid "URL" +msgstr "URL" -#: contrib/comments/templates/comments/form.html:32 -#: contrib/comments/templates/comments/freeform.html:9 -msgid "Preview comment" -msgstr "Forhåndvis kommentar" +#: contrib/flatpages/models.py:8 +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" +"Eksempel: '/om/kontakt/'. Vær sikker på at det er en skråstrek foran og bak." -#: contrib/comments/templates/comments/freeform.html:4 -msgid "Your name:" -msgstr "Ditt navn:" +#: contrib/flatpages/models.py:9 +msgid "title" +msgstr "tittel" + +#: contrib/flatpages/models.py:10 +msgid "content" +msgstr "innhold" + +#: contrib/flatpages/models.py:11 +msgid "enable comments" +msgstr "tillat kommentarer" + +#: contrib/flatpages/models.py:12 +msgid "template name" +msgstr "navn på mal" + +#: contrib/flatpages/models.py:13 +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"Eksempel: 'flatpages/kontakt_side.html'. Hvis denne ikke denne er gitt, vil " +"'flatpages/default.html' bli brukt." + +#: contrib/flatpages/models.py:14 +msgid "registration required" +msgstr "registrering kreves" + +#: contrib/flatpages/models.py:14 +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Hvis denne er krysset av, er det kun innloggede brukere som kan se siden." -#: contrib/admin/filterspecs.py:40 +#: contrib/flatpages/models.py:18 +msgid "flat page" +msgstr "flatside" + +#: contrib/flatpages/models.py:19 +msgid "flat pages" +msgstr "flatsider" + +#: contrib/sessions/models.py:68 +msgid "session key" +msgstr "sesjonsnøkkel" + +#: contrib/sessions/models.py:69 +msgid "session data" +msgstr "sesjonsdata" + +#: contrib/sessions/models.py:70 +msgid "expire date" +msgstr "utløpsdato" + +#: contrib/sessions/models.py:74 +msgid "session" +msgstr "sesjon" + +#: contrib/sessions/models.py:75 +msgid "sessions" +msgstr "sesjoner" + +#: contrib/sites/models.py:15 +msgid "domain name" +msgstr "domenenavn" + +#: contrib/sites/models.py:16 +msgid "display name" +msgstr "visningsnavn" + +#: contrib/sites/models.py:20 +msgid "site" +msgstr "nettsted" + +#: contrib/sites/models.py:21 +msgid "sites" +msgstr "nettsteder" + +#: contrib/admin/filterspecs.py:42 #, python-format msgid "" "<h3>By %s:</h3>\n" @@ -351,96 +1602,92 @@ msgstr "" "<h3>Av %s:</h3>\n" "<ul>\n" -#: contrib/admin/filterspecs.py:70 contrib/admin/filterspecs.py:88 -#: contrib/admin/filterspecs.py:143 +#: contrib/admin/filterspecs.py:72 contrib/admin/filterspecs.py:90 +#: contrib/admin/filterspecs.py:145 contrib/admin/filterspecs.py:171 msgid "All" msgstr "Alle" -#: contrib/admin/filterspecs.py:109 +#: contrib/admin/filterspecs.py:111 msgid "Any date" msgstr "Når som helst" -#: contrib/admin/filterspecs.py:110 +#: contrib/admin/filterspecs.py:112 msgid "Today" msgstr "I dag" -#: contrib/admin/filterspecs.py:113 +#: contrib/admin/filterspecs.py:115 msgid "Past 7 days" msgstr "Siste 7 dager" -#: contrib/admin/filterspecs.py:115 +#: contrib/admin/filterspecs.py:117 msgid "This month" msgstr "Denne måneden" -#: contrib/admin/filterspecs.py:117 +#: contrib/admin/filterspecs.py:119 msgid "This year" msgstr "I år" -#: contrib/admin/filterspecs.py:143 +#: contrib/admin/filterspecs.py:145 oldforms/__init__.py:591 +#: newforms/widgets.py:188 msgid "Yes" msgstr "Ja" -#: contrib/admin/filterspecs.py:143 +#: contrib/admin/filterspecs.py:145 oldforms/__init__.py:591 +#: newforms/widgets.py:188 msgid "No" msgstr "Nei" -#: contrib/admin/filterspecs.py:150 +#: contrib/admin/filterspecs.py:152 oldforms/__init__.py:591 +#: newforms/widgets.py:188 msgid "Unknown" msgstr "Ukjent" -#: contrib/admin/models.py:16 +#: contrib/admin/models.py:17 msgid "action time" msgstr "tid for handling" -#: contrib/admin/models.py:19 +#: contrib/admin/models.py:20 msgid "object id" -msgstr "objekt id" +msgstr "objekt-ID" -#: contrib/admin/models.py:20 +#: contrib/admin/models.py:21 msgid "object repr" msgstr "objekt repr" -#: contrib/admin/models.py:21 +#: contrib/admin/models.py:22 msgid "action flag" msgstr "handlingsflagg" -#: contrib/admin/models.py:22 +#: contrib/admin/models.py:23 msgid "change message" msgstr "endre melding" -#: contrib/admin/models.py:25 +#: contrib/admin/models.py:26 msgid "log entry" -msgstr "logg post" +msgstr "logginnlegg" -#: contrib/admin/models.py:26 +#: contrib/admin/models.py:27 msgid "log entries" -msgstr "logg poster" +msgstr "logginnlegg" -#: contrib/admin/templatetags/admin_list.py:228 +#: contrib/admin/templatetags/admin_list.py:254 msgid "All dates" msgstr "Alle datoer" -#: contrib/admin/views/decorators.py:9 contrib/auth/forms.py:36 -#: contrib/auth/forms.py:41 -msgid "" -"Please enter a correct username and password. Note that both fields are case-" -"sensitive." -msgstr "" -"Vennligst angi korrekt brukernavn og passord. Merk at små og " -"store bokstaver er betraktet ulikt." - -#: contrib/admin/views/decorators.py:23 +#: contrib/admin/views/decorators.py:24 #: contrib/admin/templates/admin/login.html:25 msgid "Log in" msgstr "Logg inn" -#: contrib/admin/views/decorators.py:61 +#: contrib/admin/views/decorators.py:62 msgid "" "Please log in again, because your session has expired. Don't worry: Your " "submission has been saved." -msgstr "Du må logge inn igjen, fordi økten din har gått ut, men innlegget ditt ble lagret." +msgstr "" +"Du må logge inn igjen, fordi økten din har gått ut. Slapp av, innlegget ditt " +"ble lagret." -#: contrib/admin/views/decorators.py:68 +#: contrib/admin/views/decorators.py:69 msgid "" "Looks like your browser isn't configured to accept cookies. Please enable " "cookies, reload this page, and try again." @@ -448,187 +1695,279 @@ msgstr "" "Det ser ut som om nettleseren din ikke støtter informasjonskapsler " "('cookies'). Vennligst konfigurer nettleseren din, og prøv igjen." -#: contrib/admin/views/decorators.py:82 +#: contrib/admin/views/decorators.py:83 msgid "Usernames cannot contain the '@' character." msgstr "Brukernavnet kan ikke inneholde '@'" -#: contrib/admin/views/decorators.py:84 +#: contrib/admin/views/decorators.py:85 #, python-format msgid "Your e-mail address is not your username. Try '%s' instead." -msgstr "E-post adressen din er ikke brukernavnet ditt, prøv '%s' i stede." - -#: contrib/admin/views/main.py:226 -msgid "Site administration" -msgstr "Nettsted administrasjon" +msgstr "E-postadressen din er ikke brukernavnet ditt, prøv '%s' i stede." -#: contrib/admin/views/main.py:260 +#: contrib/admin/views/auth.py:20 contrib/admin/views/main.py:264 #, python-format msgid "The %(name)s \"%(obj)s\" was added successfully." msgstr "%(name)s \"%(obj)s\" ble lagt inn i databasen." -#: contrib/admin/views/main.py:264 contrib/admin/views/main.py:348 +#: contrib/admin/views/auth.py:25 contrib/admin/views/main.py:268 +#: contrib/admin/views/main.py:354 msgid "You may edit it again below." msgstr "Du kan endre under" -#: contrib/admin/views/main.py:272 contrib/admin/views/main.py:357 +#: contrib/admin/views/auth.py:31 +msgid "Add user" +msgstr "Ny bruker" + +#: contrib/admin/views/auth.py:58 +msgid "Password changed successfully." +msgstr "Passordet er endret." + +#: contrib/admin/views/auth.py:65 +#, python-format +msgid "Change password: %s" +msgstr "Endre passord: %s" + +#: contrib/admin/views/main.py:230 +msgid "Site administration" +msgstr "Nettstedsadministrasjon" + +#: contrib/admin/views/main.py:278 contrib/admin/views/main.py:363 #, python-format msgid "You may add another %s below." msgstr "Du kan legge til en ny %s under." -#: contrib/admin/views/main.py:290 +#: contrib/admin/views/main.py:296 #, python-format msgid "Add %s" msgstr "Ny %s" -#: contrib/admin/views/main.py:336 +#: contrib/admin/views/main.py:342 #, python-format msgid "Added %s." msgstr "La til %s" -#: contrib/admin/views/main.py:336 contrib/admin/views/main.py:338 -#: contrib/admin/views/main.py:340 -msgid "and" -msgstr "og" - -#: contrib/admin/views/main.py:338 +#: contrib/admin/views/main.py:344 #, python-format msgid "Changed %s." msgstr "Endret %s." -#: contrib/admin/views/main.py:340 +#: contrib/admin/views/main.py:346 #, python-format msgid "Deleted %s." msgstr "Slettet %s." -#: contrib/admin/views/main.py:343 +#: contrib/admin/views/main.py:349 msgid "No fields changed." msgstr "Ingen felt endret." -#: contrib/admin/views/main.py:346 +#: contrib/admin/views/main.py:352 #, python-format msgid "The %(name)s \"%(obj)s\" was changed successfully." msgstr "%(name)s \"%(obj)s\" ble endret." -#: contrib/admin/views/main.py:354 +#: contrib/admin/views/main.py:360 #, python-format -msgid "The %(name)s \"%(obj)s\" was added successfully. You may edit it again below." +msgid "" +"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below." msgstr "%(name)s \"%(obj)s\" ble endret. Du kan endre det igjen under." -#: contrib/admin/views/main.py:392 +#: contrib/admin/views/main.py:398 #, python-format msgid "Change %s" msgstr "Endre %s" -#: contrib/admin/views/main.py:470 +#: contrib/admin/views/main.py:483 #, python-format msgid "One or more %(fieldname)s in %(name)s: %(obj)s" msgstr "En eller flere %(fieldname)s i %(name)s: %(obj)s" -#: contrib/admin/views/main.py:475 +#: contrib/admin/views/main.py:488 #, python-format msgid "One or more %(fieldname)s in %(name)s:" msgstr "En eller flere %(fieldname)s i %(name)s:" -#: contrib/admin/views/main.py:508 +#: contrib/admin/views/main.py:520 #, python-format msgid "The %(name)s \"%(obj)s\" was deleted successfully." msgstr "%(name)s \"%(obj)s\" ble slettet." -#: contrib/admin/views/main.py:511 +#: contrib/admin/views/main.py:523 msgid "Are you sure?" msgstr "Er du sikker?" -#: contrib/admin/views/main.py:533 +#: contrib/admin/views/main.py:545 #, python-format msgid "Change history: %s" -msgstr "Endre historien: %s" +msgstr "Endringshistorikk: %s" -#: contrib/admin/views/main.py:565 +#: contrib/admin/views/main.py:579 #, python-format msgid "Select %s" msgstr "Velg %s" -#: contrib/admin/views/main.py:565 +#: contrib/admin/views/main.py:579 #, python-format msgid "Select %s to change" msgstr "Velg %s for å endre" -#: contrib/admin/views/doc.py:277 contrib/admin/views/doc.py:286 -#: contrib/admin/views/doc.py:288 contrib/admin/views/doc.py:294 -#: contrib/admin/views/doc.py:295 contrib/admin/views/doc.py:297 +#: contrib/admin/views/main.py:780 +msgid "Database error" +msgstr "Databasefeil" + +#: contrib/admin/views/doc.py:47 contrib/admin/views/doc.py:49 +#: contrib/admin/views/doc.py:51 +msgid "tag:" +msgstr "" + +#: contrib/admin/views/doc.py:78 contrib/admin/views/doc.py:80 +#: contrib/admin/views/doc.py:82 +msgid "filter:" +msgstr "" + +#: contrib/admin/views/doc.py:136 contrib/admin/views/doc.py:138 +#: contrib/admin/views/doc.py:140 +msgid "view:" +msgstr "" + +#: contrib/admin/views/doc.py:165 +#, python-format +msgid "App %r not found" +msgstr "Fan ikke applikasjonen %r" + +#: contrib/admin/views/doc.py:172 +#, python-format +msgid "Model %(name)r not found in app %(label)r" +msgstr "Fant ikke %(name)r-modellen i applikasjonen %(label)r" + +#: contrib/admin/views/doc.py:184 +#, python-format +msgid "the related `%(label)s.%(type)s` object" +msgstr "det relaterte `%(label)s.%(type)s`-objektet" + +#: contrib/admin/views/doc.py:184 contrib/admin/views/doc.py:206 +#: contrib/admin/views/doc.py:220 contrib/admin/views/doc.py:225 +msgid "model:" +msgstr "" + +#: contrib/admin/views/doc.py:215 +#, python-format +msgid "related `%(label)s.%(name)s` objects" +msgstr "relaterte `%(label)s.%(name)s`-objekter" + +#: contrib/admin/views/doc.py:220 +#, python-format +msgid "all %s" +msgstr "alle %s" + +#: contrib/admin/views/doc.py:225 +#, python-format +msgid "number of %s" +msgstr "antall %s" + +#: contrib/admin/views/doc.py:230 +#, python-format +msgid "Fields on %s objects" +msgstr "Felter på %s objekter" + +#: contrib/admin/views/doc.py:292 contrib/admin/views/doc.py:303 +#: contrib/admin/views/doc.py:305 contrib/admin/views/doc.py:311 +#: contrib/admin/views/doc.py:312 contrib/admin/views/doc.py:314 msgid "Integer" msgstr "Heltall" -#: contrib/admin/views/doc.py:278 +#: contrib/admin/views/doc.py:293 msgid "Boolean (Either True or False)" -msgstr "Boolean (Enten \"True\" eller \"False\")" +msgstr "Boolean (enten \"True\" eller \"False\")" -#: contrib/admin/views/doc.py:279 contrib/admin/views/doc.py:296 +#: contrib/admin/views/doc.py:294 contrib/admin/views/doc.py:313 #, python-format -msgid "String (up to %(maxlength)s)" -msgstr "Tekst (opp til %(maxlength)s tegn)" +msgid "String (up to %(max_length)s)" +msgstr "Tekst (opp til %(max_length)s tegn)" -#: contrib/admin/views/doc.py:280 +#: contrib/admin/views/doc.py:295 msgid "Comma-separated integers" -msgstr "Heltall skilt med kommaer" +msgstr "Heltall adskilt med komma" -#: contrib/admin/views/doc.py:281 +#: contrib/admin/views/doc.py:296 msgid "Date (without time)" msgstr "Dato (uten tid)" -#: contrib/admin/views/doc.py:282 +#: contrib/admin/views/doc.py:297 msgid "Date (with time)" msgstr "Dato/tid" -#: contrib/admin/views/doc.py:283 +#: contrib/admin/views/doc.py:298 +msgid "Decimal number" +msgstr "Desimaltall" + +#: contrib/admin/views/doc.py:299 msgid "E-mail address" -msgstr "E-post adresse" +msgstr "E-postadresse" -#: contrib/admin/views/doc.py:284 contrib/admin/views/doc.py:287 +#: contrib/admin/views/doc.py:300 contrib/admin/views/doc.py:301 +#: contrib/admin/views/doc.py:304 msgid "File path" -msgstr "Sti til fil" +msgstr "Filsti" -#: contrib/admin/views/doc.py:285 -msgid "Decimal number" -msgstr "Desimal tall" +#: contrib/admin/views/doc.py:302 +msgid "Floating point number" +msgstr "Flyttall" -#: contrib/admin/views/doc.py:291 +#: contrib/admin/views/doc.py:308 msgid "Boolean (Either True, False or None)" msgstr "Boolean (enten \"True\", \"False\" eller \"None\")" -#: contrib/admin/views/doc.py:292 +#: contrib/admin/views/doc.py:309 msgid "Relation to parent model" -msgstr "Relasjon til forelder modell" +msgstr "Relasjon til foreldermodell" -#: contrib/admin/views/doc.py:293 +#: contrib/admin/views/doc.py:310 msgid "Phone number" msgstr "Telefonnummer" -#: contrib/admin/views/doc.py:298 +#: contrib/admin/views/doc.py:315 msgid "Text" msgstr "Tekst" -#: contrib/admin/views/doc.py:299 +#: contrib/admin/views/doc.py:316 msgid "Time" msgstr "Tid" -#: contrib/admin/views/doc.py:300 contrib/flatpages/models.py:7 -msgid "URL" -msgstr "URL" - -#: contrib/admin/views/doc.py:301 +#: contrib/admin/views/doc.py:318 msgid "U.S. state (two uppercase letters)" msgstr "Stat (i USA, to store bokstaver)" -#: contrib/admin/views/doc.py:302 +#: contrib/admin/views/doc.py:319 msgid "XML text" -msgstr "XML tekst" +msgstr "XML-tekst" + +#: contrib/admin/views/doc.py:345 +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s ser ikke ut til å være et urlpattern-objekt" + +#: contrib/admin/templates/widget/file.html:2 +msgid "Currently:" +msgstr "Nå:" + +#: contrib/admin/templates/widget/file.html:3 +msgid "Change:" +msgstr "Endre:" + +#: contrib/admin/templates/widget/date_time.html:3 +msgid "Date:" +msgstr "Dato:" + +#: contrib/admin/templates/widget/date_time.html:4 +msgid "Time:" +msgstr "Tid:" #: contrib/admin/templates/admin/object_history.html:3 #: contrib/admin/templates/admin/change_list.html:5 -#: contrib/admin/templates/admin/base.html:23 -#: contrib/admin/templates/admin/delete_confirmation.html:3 #: contrib/admin/templates/admin/change_form.html:10 +#: contrib/admin/templates/admin/base.html:25 +#: contrib/admin/templates/admin/delete_confirmation.html:3 +#: contrib/admin/templates/admin/auth/user/change_password.html:9 #: contrib/admin/templates/registration/password_change_done.html:3 #: contrib/admin/templates/registration/password_change_form.html:3 #: contrib/admin/templates/admin_doc/bookmarklets.html:3 @@ -637,9 +1976,12 @@ msgstr "Dokumentasjon" #: contrib/admin/templates/admin/object_history.html:3 #: contrib/admin/templates/admin/change_list.html:5 -#: contrib/admin/templates/admin/base.html:23 -#: contrib/admin/templates/admin/delete_confirmation.html:3 #: contrib/admin/templates/admin/change_form.html:10 +#: contrib/admin/templates/admin/base.html:25 +#: contrib/admin/templates/admin/delete_confirmation.html:3 +#: contrib/admin/templates/admin/auth/user/change_password.html:9 +#: contrib/admin/templates/admin/auth/user/change_password.html:15 +#: contrib/admin/templates/admin/auth/user/change_password.html:46 #: contrib/admin/templates/registration/password_change_done.html:3 #: contrib/admin/templates/registration/password_change_form.html:3 #: contrib/admin/templates/admin_doc/bookmarklets.html:4 @@ -656,11 +1998,13 @@ msgid "Change password" msgstr "Endre passord" #: contrib/admin/templates/admin/object_history.html:5 -#: contrib/admin/templates/admin/500.html:4 #: contrib/admin/templates/admin/change_list.html:6 -#: contrib/admin/templates/admin/base.html:28 -#: contrib/admin/templates/admin/delete_confirmation.html:6 +#: contrib/admin/templates/admin/500.html:4 +#: contrib/admin/templates/admin/invalid_setup.html:4 #: contrib/admin/templates/admin/change_form.html:13 +#: contrib/admin/templates/admin/base.html:30 +#: contrib/admin/templates/admin/delete_confirmation.html:6 +#: contrib/admin/templates/admin/auth/user/change_password.html:12 #: contrib/admin/templates/registration/password_change_done.html:4 #: contrib/admin/templates/registration/password_reset_form.html:4 #: contrib/admin/templates/registration/logged_out.html:4 @@ -671,9 +2015,9 @@ msgid "Home" msgstr "Hjem" #: contrib/admin/templates/admin/object_history.html:5 -#: contrib/admin/templates/admin/change_form.html:20 +#: contrib/admin/templates/admin/change_form.html:21 msgid "History" -msgstr "Historie" +msgstr "Historikk" #: contrib/admin/templates/admin/object_history.html:18 msgid "Date/time" @@ -685,39 +2029,41 @@ msgstr "Bruker" #: contrib/admin/templates/admin/object_history.html:20 msgid "Action" -msgstr "Funksjon" +msgstr "Handling" #: contrib/admin/templates/admin/object_history.html:26 msgid "DATE_WITH_TIME_FULL" -msgstr "j. M U - h:i" +msgstr "h:i, j. M Y" #: contrib/admin/templates/admin/object_history.html:36 msgid "" "This object doesn't have a change history. It probably wasn't added via this " "admin site." msgstr "" -"Dette objektet har ingen endrings historie. Den var sannsynligvis ikke laget " -"via denne siden" +"Dette objektet har ingen endringshistorikk. Det var sannsynligvis ikke lagt " +"til via denne siden." -#: contrib/admin/templates/admin/base_site.html:4 -msgid "Django site admin" -msgstr "Django administrasjonsside" +#: contrib/admin/templates/admin/change_list.html:12 +#, python-format +msgid "Add %(name)s" +msgstr "Legg til %(name)s" -#: contrib/admin/templates/admin/base_site.html:7 -msgid "Django administration" -msgstr "Django administrasjon" +#: contrib/admin/templates/admin/filter.html:2 +#, python-format +msgid " By %(filter_title)s " +msgstr "Av %(filter_title)s " #: contrib/admin/templates/admin/500.html:4 msgid "Server error" -msgstr "Tjener feil" +msgstr "Tjenerfeil" #: contrib/admin/templates/admin/500.html:6 msgid "Server error (500)" -msgstr "Tjener feil (500)" +msgstr "Tjenerfeil (500)" #: contrib/admin/templates/admin/500.html:9 msgid "Server Error <em>(500)</em>" -msgstr "Tjener feil <em>(500)</em>" +msgstr "Tjenerfeil <em>(500)</em>" #: contrib/admin/templates/admin/500.html:10 msgid "" @@ -727,6 +2073,46 @@ msgstr "" "Det har oppstått en feil. Feilen er blitt rapportert til administrator via e-" "post, og vil bli fikset snart. Takk for din tålmodighet." +#: contrib/admin/templates/admin/invalid_setup.html:8 +msgid "" +"Something's wrong with your database installation. Make sure the appropriate " +"database tables have been created, and make sure the database is readable by " +"the appropriate user." +msgstr "Noe er galt med databaseinstallasjonen din. Sørg for at " +"databasetabellene er opprett, og at brukeren har de nødvendige rettigheter." + +#: contrib/admin/templates/admin/search_form.html:8 +msgid "Go" +msgstr "Gå" + +#: contrib/admin/templates/admin/search_form.html:10 +#, python-format +msgid "1 result" +msgid_plural "%(counter)s results" +msgstr[0] "Ett resultat" +msgstr[1] "(counter)s resultat" + +#: contrib/admin/templates/admin/search_form.html:10 +#, python-format +msgid "%(full_result_count)s total" +msgstr "%(full_result_count)s totalt" + +#: contrib/admin/templates/admin/pagination.html:10 +msgid "Show all" +msgstr "Vis alle" + +#: contrib/admin/templates/admin/base_site.html:4 +msgid "Django site admin" +msgstr "Django administrasjonsside" + +#: contrib/admin/templates/admin/base_site.html:7 +msgid "Django administration" +msgstr "Django-administrasjon" + +#: contrib/admin/templates/admin/filters.html:4 +msgid "Filter" +msgstr "Filter" + #: contrib/admin/templates/admin/404.html:4 #: contrib/admin/templates/admin/404.html:8 msgid "Page not found" @@ -739,7 +2125,12 @@ msgstr "Beklager, men siden du spør etter finnes ikke." #: contrib/admin/templates/admin/index.html:17 #, python-format msgid "Models available in the %(name)s application." -msgstr "Modeller fra applikasjonen %(name)s." +msgstr "Modeller tilgjengelig i %(name)s-applikasjonen." + +#: contrib/admin/templates/admin/index.html:18 +#, python-format +msgid "%(name)s" +msgstr "" #: contrib/admin/templates/admin/index.html:28 #: contrib/admin/templates/admin/change_form.html:15 @@ -752,7 +2143,7 @@ msgstr "Endre" #: contrib/admin/templates/admin/index.html:44 msgid "You don't have permission to edit anything." -msgstr "Du har ikke rettigheter til å endre." +msgstr "Du har ikke rettigheter til å endre noe." #: contrib/admin/templates/admin/index.html:52 msgid "Recent Actions" @@ -766,18 +2157,28 @@ msgstr "Mine handlinger" msgid "None available" msgstr "Ingen tilgjengelige" -#: contrib/admin/templates/admin/change_list.html:11 -#, python-format -msgid "Add %(name)s" -msgstr "Legg til %(name)s" +#: contrib/admin/templates/admin/change_form.html:22 +msgid "View on site" +msgstr "Vis på nettsted" -#: contrib/admin/templates/admin/login.html:22 -msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?" -msgstr "Har du <a href=\"/password_reset/\">glemt passordet ditt</a>?" +#: contrib/admin/templates/admin/change_form.html:32 +#: contrib/admin/templates/admin/auth/user/change_password.html:24 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "Vennligst fiks feilen under." +msgstr[1] "Vennligst fiks feilene under." -#: contrib/admin/templates/admin/base.html:23 +#: contrib/admin/templates/admin/change_form.html:50 +msgid "Ordering" +msgstr "Rekkefølge" + +#: contrib/admin/templates/admin/change_form.html:53 +msgid "Order:" +msgstr "Rekkefølge:" + +#: contrib/admin/templates/admin/base.html:25 msgid "Welcome," -msgstr "Velkommen" +msgstr "Velkommen," #: contrib/admin/templates/admin/delete_confirmation.html:9 #: contrib/admin/templates/admin/submit_line.html:3 @@ -787,60 +2188,34 @@ msgstr "Slett" #: contrib/admin/templates/admin/delete_confirmation.html:14 #, python-format msgid "" -"Deleting the %(object_name)s '%(object)s' would result in deleting related " -"objects, but your account doesn't have permission to delete the following " -"types of objects:" +"Deleting the %(object_name)s '%(escaped_object)s' would result in deleting " +"related objects, but your account doesn't have permission to delete the " +"following types of objects:" msgstr "" -"Hivs du sletter %(object_name)s '%(object)s' vil du også slette relaterte " -"objekter, men du har ikke tillatelse til å slette de følgende objektene:" +"Hivs du sletter %(object_name)s '%(escaped_object)s', vil du også slette " +"relaterte objekter, men du har ikke tillatelse til å slette følgende " +"objektene:" #: contrib/admin/templates/admin/delete_confirmation.html:21 #, python-format msgid "" -"Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of " -"the following related items will be deleted:" +"Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? " +"All of the following related items will be deleted:" msgstr "" -"Er du sikker på at du vill slette %(object_name)s \"%(object)s\"? Alle de " -"følgende relaterte objektene vill bli slettet:" +"Er du sikker på at du vill slette %(object_name)s \"%(escaped_object)s\"? " +"Alle de følgende relaterte objektene vil bli slettet:" #: contrib/admin/templates/admin/delete_confirmation.html:26 msgid "Yes, I'm sure" msgstr "Ja, jeg er sikker" -#: contrib/admin/templates/admin/filter.html:2 -#, python-format -msgid " By %(title)s " -msgstr "Av %(title)s " - -#: contrib/admin/templates/admin/search_form.html:8 -msgid "Go" -msgstr "Gå" - -#: contrib/admin/templates/admin/change_form.html:21 -msgid "View on site" -msgstr "Vis på nettsted" - -#: contrib/admin/templates/admin/change_form.html:30 -msgid "Please correct the error below." -msgid_plural "Please correct the errors below." -msgstr[0] "Vennligst fiks feilen under." -msgstr[1] "Vennligst fiks feilene under." - -#: contrib/admin/templates/admin/change_form.html:48 -msgid "Ordering" -msgstr "Rekkefølge" - -#: contrib/admin/templates/admin/change_form.html:51 -msgid "Order:" -msgstr "Rekkefølge:" - #: contrib/admin/templates/admin/submit_line.html:4 msgid "Save as new" msgstr "Lagre som ny" #: contrib/admin/templates/admin/submit_line.html:5 msgid "Save and add another" -msgstr "Lagre og legg til en ny" +msgstr "Lagre og legg til ny" #: contrib/admin/templates/admin/submit_line.html:6 msgid "Save and continue editing" @@ -850,6 +2225,37 @@ msgstr "Lagre og fortsett å endre" msgid "Save" msgstr "Lagre" +#: contrib/admin/templates/admin/auth/user/change_password.html:28 +#, python-format +msgid "Enter a new password for the user <strong>%(username)s</strong>." +msgstr "Skriv inn et nytt passord for brukeren <strong>%(username)s</strong>." + +#: contrib/admin/templates/admin/auth/user/change_password.html:34 +#: contrib/admin/templates/admin/auth/user/add_form.html:18 +msgid "Password" +msgstr "Passord" + +#: contrib/admin/templates/admin/auth/user/change_password.html:39 +#: contrib/admin/templates/admin/auth/user/add_form.html:23 +msgid "Password (again)" +msgstr "Passord (gjenta)" + +#: contrib/admin/templates/admin/auth/user/change_password.html:40 +#: contrib/admin/templates/admin/auth/user/add_form.html:24 +msgid "Enter the same password as above, for verification." +msgstr "Skriv inn det samme passordet som ovenfor, for verifisering." + +#: contrib/admin/templates/admin/auth/user/add_form.html:6 +msgid "" +"First, enter a username and password. Then, you'll be able to edit more user " +"options." +msgstr "Skriv først inn brukernavn og passord. Deretter vil du få mulighet " +"til å endre flere brukerinnstillinger." + +#: contrib/admin/templates/admin/auth/user/add_form.html:12 +msgid "Username" +msgstr "Brukernavn" + #: contrib/admin/templates/registration/password_change_done.html:4 #: contrib/admin/templates/registration/password_change_form.html:4 #: contrib/admin/templates/registration/password_change_form.html:6 @@ -878,12 +2284,12 @@ msgid "" "Forgotten your password? Enter your e-mail address below, and we'll reset " "your password and e-mail the new one to you." msgstr "" -"Har du glemt passordet ditt? Skriv inn e-post adressen din under, så sender " -"vi deg et nytt passord via e-post." +"Har du glemt passordet ditt? Skriv inn e-postadressen din under, så sender " +"vi deg et nytt passord til deg." #: contrib/admin/templates/registration/password_reset_form.html:16 msgid "E-mail address:" -msgstr "E-post adresse:" +msgstr "E-postadresse:" #: contrib/admin/templates/registration/password_reset_form.html:16 msgid "Reset my password" @@ -891,7 +2297,7 @@ msgstr "Tilbakestill mitt passord" #: contrib/admin/templates/registration/logged_out.html:8 msgid "Thanks for spending some quality time with the Web site today." -msgstr "Takk for at du valgte å bruke kvalitetstid på nettstedet idag." +msgstr "Takk for at du valgte å bruke kvalitetstid på nettstedet i dag." #: contrib/admin/templates/registration/logged_out.html:10 msgid "Log in again" @@ -907,16 +2313,16 @@ msgid "" "We've e-mailed a new password to the e-mail address you submitted. You " "should be receiving it shortly." msgstr "" -"Vi sender deg et nytt passord til e-post adressen du oppgav. Du villmotta det " -"snart." +"Vi har sendt deg et nytt passord til e-postadressen du oppgav. Du vil " +"forhåpentligvis motta det snart." #: contrib/admin/templates/registration/password_change_form.html:12 msgid "" "Please enter your old password, for security's sake, and then enter your new " "password twice so we can verify you typed it in correctly." msgstr "" -"Venligst skriv inn ditt gamle passord, for sikkerthets grunner, så skriv inn " -"ditt nye passord to ganger slik at vi kan kontrollere at det er rett." +"Venligst skriv inn ditt gamle passord, av sikkerthetsårsaker. Skriv deretter " +"inn ditt nye passord to ganger, slik at vi kan kontrollere at det er rett." #: contrib/admin/templates/registration/password_change_form.html:17 msgid "Old password:" @@ -936,7 +2342,8 @@ msgstr "Endre passord" #: contrib/admin/templates/registration/password_reset_email.html:2 msgid "You're receiving this e-mail because you requested a password reset" -msgstr "Du har mottatt denne e-posten fordi du ba om å tilbakestille passordet ditt" +msgstr "" +"Du har mottatt denne e-posten fordi du ba om å tilbakestille passordet ditt" #: contrib/admin/templates/registration/password_reset_email.html:3 #, python-format @@ -958,7 +2365,7 @@ msgstr "I tilfellet du har glemt brukernavnet ditt, så er det:" #: contrib/admin/templates/registration/password_reset_email.html:13 msgid "Thanks for using our site!" -msgstr "Takk for at du bruker vår side!" +msgstr "Takk for at du bruker siden vår!" #: contrib/admin/templates/registration/password_reset_email.html:15 #, python-format @@ -971,7 +2378,7 @@ msgstr "Bokmerker" #: contrib/admin/templates/admin_doc/bookmarklets.html:5 msgid "Documentation bookmarklets" -msgstr "Dokumentasjon bokmerker" +msgstr "Dokumentasjonsbokmerker" #: contrib/admin/templates/admin_doc/bookmarklets.html:9 msgid "" @@ -988,7 +2395,8 @@ msgstr "" "for bokmerker, eller høyreklikk og legg til i bokmerker. Nå kan du du velge\n" "bokmerket fra hvilken som helst side på nettstedet. Noen av disse\n" "bokmerkene krever at datamaskinen du bruker er markert som \"intern\"\n" -"(kontakt din systemadministrator hvis du er usikker på om maskinen din er \"intern\").</p>\n" +"(kontakt din systemadministrator hvis du er usikker på om maskinen din er " +"\"intern\").</p>\n" #: contrib/admin/templates/admin_doc/bookmarklets.html:19 msgid "Documentation for this page" @@ -1004,7 +2412,7 @@ msgstr "" #: contrib/admin/templates/admin_doc/bookmarklets.html:22 msgid "Show object ID" -msgstr "Vis objekt ID" +msgstr "Vis objekt-ID" #: contrib/admin/templates/admin_doc/bookmarklets.html:23 msgid "" @@ -1016,962 +2424,164 @@ msgstr "" #: contrib/admin/templates/admin_doc/bookmarklets.html:25 msgid "Edit this object (current window)" -msgstr "Endre dette objektet (åpnes i dette vinduet)" +msgstr "Endre dette objektet (nåværende vindu)" #: contrib/admin/templates/admin_doc/bookmarklets.html:26 msgid "Jumps to the admin page for pages that represent a single object." -msgstr "Hopp til administrasjonsiden for sidene som representerer et enkelt objekt." +msgstr "" +"Hopper til administrasjonsiden for sider som representerer et enkelt objekt." #: contrib/admin/templates/admin_doc/bookmarklets.html:28 msgid "Edit this object (new window)" -msgstr "Endre dette objektet (åpnes i et nytt vindu)" +msgstr "Endre dette objektet (nytt vindu)" #: contrib/admin/templates/admin_doc/bookmarklets.html:29 msgid "As above, but opens the admin page in a new window." msgstr "Samme som over, men åpner administrasjonsiden i et nytt vindu." -#: contrib/admin/templates/widget/date_time.html:3 -msgid "Date:" -msgstr "Dato:" - -#: contrib/admin/templates/widget/date_time.html:4 -msgid "Time:" -msgstr "Tid:" - -#: contrib/admin/templates/widget/file.html:2 -msgid "Currently:" -msgstr "Nå:" - -#: contrib/admin/templates/widget/file.html:3 -msgid "Change:" -msgstr "Endre:" - -#: contrib/redirects/models.py:7 -msgid "redirect from" -msgstr "omadresser fra" - -#: contrib/redirects/models.py:8 -msgid "" -"This should be an absolute path, excluding the domain name. Example: '/" -"events/search/'." -msgstr "" -"Dette burde vært en fullstendig sti, uten domene navnet. Foreksempel: '/" -"nyheter/les/" - -#: contrib/redirects/models.py:9 -msgid "redirect to" -msgstr "omadresser til" - -#: contrib/redirects/models.py:10 -msgid "" -"This can be either an absolute path (as above) or a full URL starting with " -"'http://'." -msgstr "" -"Dette kan enten være en fullstendig sti (som over), eller en hel " -"internettadresse som starter med 'http://'" - -#: contrib/redirects/models.py:12 -msgid "redirect" -msgstr "omadressering" - -#: contrib/redirects/models.py:13 -msgid "redirects" -msgstr "omadresserelser" - -#: contrib/flatpages/models.py:8 -msgid "Example: '/about/contact/'. Make sure to have leading and trailing slashes." -msgstr "Eksempel: '/om/kontakt/'. Vær sikker på at du har en skråstrek forran og bak." - -#: contrib/flatpages/models.py:9 -msgid "title" -msgstr "tittel" - -#: contrib/flatpages/models.py:10 -msgid "content" -msgstr "innhold" - -#: contrib/flatpages/models.py:11 -msgid "enable comments" -msgstr "tillat kommentarer" - -#: contrib/flatpages/models.py:12 -msgid "template name" -msgstr "mal navn" - -#: contrib/flatpages/models.py:13 -msgid "" -"Example: 'flatpages/contact_page'. If this isn't provided, the system will " -"use 'flatpages/default'." -msgstr "" -"Eksempel: 'flatfiler/kontakt_side'. Hvis denne ikke denne er gitt, vill " -"'flatfiles/default' bli brukt." - -#: contrib/flatpages/models.py:14 -msgid "registration required" -msgstr "registrering kreves" - -#: contrib/flatpages/models.py:14 -msgid "If this is checked, only logged-in users will be able to view the page." -msgstr "" -"Hvis denne er krysset av er det bare brukere som er logget inn som kan se " -"siden." - -#: contrib/flatpages/models.py:18 -msgid "flat page" -msgstr "flatside" - -#: contrib/flatpages/models.py:19 -msgid "flat pages" -msgstr "flatsider" - -#: contrib/auth/models.py:13 contrib/auth/models.py:26 -msgid "name" -msgstr "navn" - -#: contrib/auth/models.py:15 -msgid "codename" -msgstr "kodenavn" - -#: contrib/auth/models.py:17 -msgid "permission" -msgstr "rettighet" - -#: contrib/auth/models.py:18 contrib/auth/models.py:27 -msgid "permissions" -msgstr "rettigheter" - -#: contrib/auth/models.py:29 -msgid "group" -msgstr "gruppe" - -#: contrib/auth/models.py:30 contrib/auth/models.py:65 -msgid "groups" -msgstr "grupper" - -#: contrib/auth/models.py:55 -msgid "username" -msgstr "brukernavn" - -#: contrib/auth/models.py:56 -msgid "first name" -msgstr "fornavn" - -#: contrib/auth/models.py:57 -msgid "last name" -msgstr "etternavn" - -#: contrib/auth/models.py:58 -msgid "e-mail address" -msgstr "e-post adresse" - -#: contrib/auth/models.py:59 -msgid "password" -msgstr "passord" - -#: contrib/auth/models.py:59 -msgid "Use '[algo]$[salt]$[hexdigest]'" -msgstr "Bruk '[algo]$[salt]$[hexdigest]'" - -#: contrib/auth/models.py:60 -msgid "staff status" -msgstr "administrasjons status" - -#: contrib/auth/models.py:60 -msgid "Designates whether the user can log into this admin site." -msgstr "Bestemmer om brukeren kan logge inn på dette administrasjons sted." - -#: contrib/auth/models.py:61 -msgid "active" -msgstr "aktiv" - -#: contrib/auth/models.py:62 -msgid "superuser status" -msgstr "super bruker" - -#: contrib/auth/models.py:63 -msgid "last login" -msgstr "siste logg inn" - -#: contrib/auth/models.py:64 -msgid "date joined" -msgstr "registrerings dato" - -#: contrib/auth/models.py:66 -msgid "" -"In addition to the permissions manually assigned, this user will also get " -"all permissions granted to each group he/she is in." -msgstr "" -"I tillegg til rettighetene som blir gitt manuelt, får også brukeren full " -"tilgang til gruppene han/hun er i." - -#: contrib/auth/models.py:67 -msgid "user permissions" -msgstr "Rettigheter" - -#: contrib/auth/models.py:70 -msgid "user" -msgstr "bruker" - -#: contrib/auth/models.py:71 -msgid "users" -msgstr "brukere" - -#: contrib/auth/models.py:76 -msgid "Personal info" -msgstr "Personlig informasjon" - -#: contrib/auth/models.py:77 -msgid "Permissions" -msgstr "Rettigheter" - -#: contrib/auth/models.py:78 -msgid "Important dates" -msgstr "Viktige datoer" - -#: contrib/auth/models.py:79 -msgid "Groups" -msgstr "Grupper" - -#: contrib/auth/models.py:219 -msgid "message" -msgstr "Melding" - -#: contrib/auth/forms.py:30 -msgid "" -"Your Web browser doesn't appear to have cookies enabled. Cookies are " -"required for logging in." -msgstr "Din nettleser ser ikkeut til å støtte informasjonskapsler (cookies). Informasjonskapsler er påkrevd for å logge inn." - -#: contrib/contenttypes/models.py:25 -msgid "python model class name" -msgstr "python modell klasse navn" - -#: contrib/contenttypes/models.py:28 -msgid "content type" -msgstr "innholds type" - -#: contrib/contenttypes/models.py:29 -msgid "content types" -msgstr "innholds typer" - -#: contrib/sessions/models.py:35 -msgid "session key" -msgstr "sesjon nøkkel" - -#: contrib/sessions/models.py:36 -msgid "session data" -msgstr "sesjon data" - -#: contrib/sessions/models.py:37 -msgid "expire date" -msgstr "utløpsdato" - -#: contrib/sessions/models.py:41 -msgid "session" -msgstr "sesjon" - -#: contrib/sessions/models.py:42 -msgid "sessions" -msgstr "sesjoner" - -#: contrib/sites/models.py:10 -msgid "domain name" -msgstr "domene navn" - -#: contrib/sites/models.py:11 -msgid "display name" -msgstr "vise navn" - -#: contrib/sites/models.py:15 -msgid "site" -msgstr "nettsted" - -#: contrib/sites/models.py:16 -msgid "sites" -msgstr "nettsteder" - -#: utils/translation.py:360 -msgid "DATE_FORMAT" -msgstr "j. M Y" - -#: utils/translation.py:361 -msgid "DATETIME_FORMAT" -msgstr "j. M Y - h:i" - -#: utils/translation.py:362 -msgid "TIME_FORMAT" -msgstr "h:i" - -#: utils/dates.py:6 -msgid "Monday" -msgstr "Mandag" - -#: utils/dates.py:6 -msgid "Tuesday" -msgstr "Tirsdag" - -#: utils/dates.py:6 -msgid "Wednesday" -msgstr "Onsdag" - -#: utils/dates.py:6 -msgid "Thursday" -msgstr "Torsdag" - -#: utils/dates.py:6 -msgid "Friday" -msgstr "Fredag" - -#: utils/dates.py:7 -msgid "Saturday" -msgstr "Lørdag" - -#: utils/dates.py:7 -msgid "Sunday" -msgstr "Søndag" - -#: utils/dates.py:14 -msgid "January" -msgstr "Januar" - -#: utils/dates.py:14 -msgid "February" -msgstr "Februar" - -#: utils/dates.py:14 utils/dates.py:27 -msgid "March" -msgstr "Mars" - -#: utils/dates.py:14 utils/dates.py:27 -msgid "April" -msgstr "April" - -#: utils/dates.py:14 utils/dates.py:27 -msgid "May" -msgstr "Mai" - -#: utils/dates.py:14 utils/dates.py:27 -msgid "June" -msgstr "Juni" - -#: utils/dates.py:15 utils/dates.py:27 -msgid "July" -msgstr "Juli" - -#: utils/dates.py:15 -msgid "August" -msgstr "August" - -#: utils/dates.py:15 -msgid "September" -msgstr "September" - -#: utils/dates.py:15 -msgid "October" -msgstr "Oktober" - -#: utils/dates.py:15 -msgid "November" -msgstr "November" - -#: utils/dates.py:16 -msgid "December" -msgstr "Desember" - -#: utils/dates.py:19 -msgid "jan" -msgstr "jan" - -#: utils/dates.py:19 -msgid "feb" -msgstr "feb" - -#: utils/dates.py:19 -msgid "mar" -msgstr "mar" - -#: utils/dates.py:19 -msgid "apr" -msgstr "apr" - -#: utils/dates.py:19 -msgid "may" -msgstr "mai" - -#: utils/dates.py:19 -msgid "jun" -msgstr "jun" - -#: utils/dates.py:20 -msgid "jul" -msgstr "jul" +#: contrib/localflavor/no/forms.py:14 contrib/localflavor/ch/forms.py:18 +msgid "Enter a zip code in the format XXXX." +msgstr "Skriv inn et postnummer som XXXX." -#: utils/dates.py:20 -msgid "aug" -msgstr "aug" - -#: utils/dates.py:20 -msgid "sep" -msgstr "sep" +#: contrib/localflavor/no/forms.py:35 +msgid "Enter a valid Norwegian social security number." +msgstr "Skriv et gyldig norsk personnummer." -#: utils/dates.py:20 -msgid "oct" -msgstr "okt" - -#: utils/dates.py:20 -msgid "nov" -msgstr "nov" - -#: utils/dates.py:20 -msgid "dec" -msgstr "des" - -#: utils/dates.py:27 -msgid "Jan." -msgstr "Jan." - -#: utils/dates.py:27 -msgid "Feb." -msgstr "Feb." - -#: utils/dates.py:28 -msgid "Aug." -msgstr "Aug." - -#: utils/dates.py:28 -msgid "Sept." -msgstr "Sept." - -#: utils/dates.py:28 -msgid "Oct." -msgstr "Okt." - -#: utils/dates.py:28 -msgid "Nov." -msgstr "Nov." - -#: utils/dates.py:28 -msgid "Dec." -msgstr "Des." - -#: utils/timesince.py:12 -msgid "year" -msgid_plural "years" -msgstr[0] "år" -msgstr[1] "år" - -#: utils/timesince.py:13 -msgid "month" -msgid_plural "months" -msgstr[0] "måned" -msgstr[1] "måndeder" - -#: utils/timesince.py:14 -msgid "week" -msgid_plural "weeks" -msgstr[0] "uke" -msgstr[1] "uker" - -#: utils/timesince.py:15 -msgid "day" -msgid_plural "days" -msgstr[0] "dag" -msgstr[1] "dager" - -#: utils/timesince.py:16 -msgid "hour" -msgid_plural "hours" -msgstr[0] "time" -msgstr[1] "timer" - -#: utils/timesince.py:17 -msgid "minute" -msgid_plural "minutes" -msgstr[0] "minutt" -msgstr[1] "minutter" - -#: conf/global_settings.py:37 -msgid "Bengali" -msgstr "Bengalsk" - -#: conf/global_settings.py:38 -msgid "Czech" -msgstr "Tsjekkisk" - -#: conf/global_settings.py:39 -msgid "Welsh" -msgstr "Walisisk" - -#: conf/global_settings.py:40 -msgid "Danish" -msgstr "Dansk" - -#: conf/global_settings.py:41 -msgid "German" -msgstr "Tysk" - -#: conf/global_settings.py:42 -msgid "Greek" -msgstr "Gresk" - -#: conf/global_settings.py:43 -msgid "English" -msgstr "Engelsk" - -#: conf/global_settings.py:44 -msgid "Spanish" -msgstr "Spansk" - -#: conf/global_settings.py:45 -msgid "French" -msgstr "Fransk" - -#: conf/global_settings.py:46 -msgid "Galician" -msgstr "Galisisk" - -#: conf/global_settings.py:47 -msgid "Hungarian" -msgstr "Ungarsk" - -#: conf/global_settings.py:48 -msgid "Hebrew" -msgstr "Hebraiske" - -#: conf/global_settings.py:49 -msgid "Icelandic" -msgstr "Islandsk" - -#: conf/global_settings.py:50 -msgid "Italian" -msgstr "Italiensk" - -#: conf/global_settings.py:51 -msgid "Japanese" -msgstr "Japansk" - -#: conf/global_settings.py:52 -msgid "Dutch" -msgstr "Nederlandsk" - -#: conf/global_settings.py:53 -msgid "Norwegian" -msgstr "Norsk" - -#: conf/global_settings.py:54 -msgid "Brazilian" -msgstr "Brasiliansk" - -#: conf/global_settings.py:55 -msgid "Romanian" -msgstr "Rumensk" - -#: conf/global_settings.py:56 -msgid "Russian" -msgstr "Russisk" - -#: conf/global_settings.py:57 -msgid "Slovak" -msgstr "Slovakisk" - -#: conf/global_settings.py:58 -msgid "Slovenian" -msgstr "Slovensk" - -#: conf/global_settings.py:59 -msgid "Serbian" -msgstr "Serbisk" - -#: conf/global_settings.py:60 -msgid "Swedish" -msgstr "Svensk" - -#: conf/global_settings.py:61 -msgid "Ukrainian" -msgstr "Ukrainsk" - -#: conf/global_settings.py:62 -msgid "Simplified Chinese" -msgstr "Simplifisert Kinesisk" - -#: conf/global_settings.py:63 -msgid "Traditional Chinese" -msgstr "Tradisjonell Kinesisk" - -#: core/validators.py:60 -msgid "This value must contain only letters, numbers and underscores." -msgstr "Dette feltet må bare inneholde bokstaver, nummer og understreker." - -#: core/validators.py:64 -msgid "" -"This value must contain only letters, numbers, underscores, dashes or " -"slashes." -msgstr "" -"Dette feltet må bare inneholde bokstaver, nummer, understreker og " -"skråstreker." - -#: core/validators.py:72 -msgid "Uppercase letters are not allowed here." -msgstr "Stor bokstaver er ikke tillatt her." - -#: core/validators.py:76 -msgid "Lowercase letters are not allowed here." -msgstr "Små bokstaver er ikke tillatt her." - -#: core/validators.py:83 -msgid "Enter only digits separated by commas." -msgstr "Skriv inn bare tall, skilt med kommaer." - -#: core/validators.py:95 -msgid "Enter valid e-mail addresses separated by commas." -msgstr "Skriv inn e-post adresser skilt med kommaer." - -#: core/validators.py:99 -msgid "Please enter a valid IP address." -msgstr "Vennligst skriv inn en godkjent IP adresse." - -#: core/validators.py:103 -msgid "Empty values are not allowed here." -msgstr "Dette felte kan ikke være tomt." - -#: core/validators.py:107 -msgid "Non-numeric characters aren't allowed here." -msgstr "Det er bare tall som kan stå i dette feltet." - -#: core/validators.py:111 -msgid "This value can't be comprised solely of digits." -msgstr "Dette feltet kan ikke bare bestå av nummer." - -#: core/validators.py:116 -msgid "Enter a whole number." -msgstr "Skriv inn et helt nummer." - -#: core/validators.py:120 -msgid "Only alphabetical characters are allowed here." -msgstr "Bare alfabetiske bokstaver er tillatt her." - -#: core/validators.py:124 -msgid "Enter a valid date in YYYY-MM-DD format." -msgstr "Skriv inn en dato i ÅÅÅÅ-MM-DD format." - -#: core/validators.py:128 -msgid "Enter a valid time in HH:MM format." -msgstr "Skriv inn tiden i TT:MM format." - -#: core/validators.py:132 db/models/fields/__init__.py:468 -msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format." -msgstr "Skriv inn dato og tid i ÅÅÅÅ-MM-DD TT:MM format." - -#: core/validators.py:136 -msgid "Enter a valid e-mail address." -msgstr "Skriv inn en godkjent e-post adresse." - -#: core/validators.py:148 -msgid "" -"Upload a valid image. The file you uploaded was either not an image or a " -"corrupted image." -msgstr "" -"Lastopp et bilde. Filen du lastet opp var ikke et bilde, eller så var det et " -"ødelagt bilde" - -#: core/validators.py:155 -#, python-format -msgid "The URL %s does not point to a valid image." -msgstr "Internettadressen %s peker ikke til et godkjent bilde." - -#: core/validators.py:159 -#, python-format -msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid." -msgstr "Telefon nummeret må være i XXX-XXX-XXXX format. \"%s\" er ikke godkjent." +#: template/defaultfilters.py:485 +msgid "yes,no,maybe" +msgstr "ja,nei,kanskje" -#: core/validators.py:167 +#: template/defaultfilters.py:514 #, python-format -msgid "The URL %s does not point to a valid QuickTime video." -msgstr "Internettadressen %s peker ikke til en godkjent QuickTime film." - -#: core/validators.py:171 -msgid "A valid URL is required." -msgstr "En godkjent internettadresse er påkrevd." +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "" +msgstr[1] "" -#: core/validators.py:185 +#: template/defaultfilters.py:516 #, python-format -msgid "" -"Valid HTML is required. Specific errors are:\n" -"%s" +msgid "%.1f KB" msgstr "" -"Godkjent HTML er påkrevd. Feilene var:\n" -"%s" -#: core/validators.py:192 +#: template/defaultfilters.py:518 #, python-format -msgid "Badly formed XML: %s" -msgstr "Ikke godkjent XML: %s" - -#: core/validators.py:202 -#, python-format -msgid "Invalid URL: %s" -msgstr "Ikke godkjent URL: %s" - -#: core/validators.py:206 core/validators.py:208 -#, python-format -msgid "The URL %s is a broken link." -msgstr "Internettadresse %s fører til en side som ikke virker." - -#: core/validators.py:214 -msgid "Enter a valid U.S. state abbreviation." -msgstr "Skriv inn en godkjent amerikansk delstat forkortelse." - -#: core/validators.py:229 -#, python-format -msgid "Watch your mouth! The word %s is not allowed here." -msgid_plural "Watch your mouth! The words %s are not allowed here." -msgstr[0] "Pass munnen din! Ordet %s er ikke tillatt her." -msgstr[1] "Pass munnen din! Ordene %s er ikke tillatt her." - -#: core/validators.py:236 -#, python-format -msgid "This field must match the '%s' field." -msgstr "Dette feltet må være det samme som i '%s' feltet." - -#: core/validators.py:255 -msgid "Please enter something for at least one field." -msgstr "Vennligst skriv inn noe i minst et felt." - -#: core/validators.py:264 core/validators.py:275 -msgid "Please enter both fields or leave them both empty." -msgstr "Vennligst skriv inn noe i begge felta, eller la dem stå blanke." - -#: core/validators.py:282 -#, python-format -msgid "This field must be given if %(field)s is %(value)s" -msgstr "Dette feltet må bare brukes hvis %(field)s er lik %(value)s" - -#: core/validators.py:294 -#, python-format -msgid "This field must be given if %(field)s is not %(value)s" -msgstr "Dette feltet må bare brukes hvis %(field)s ikke er lik %(value)s" - -#: core/validators.py:313 -msgid "Duplicate values are not allowed." -msgstr "Like verdier er ikke tillatt." - -#: core/validators.py:336 -#, python-format -msgid "This value must be a power of %s." -msgstr "Denne verdien må være 'power' av %s." - -#: core/validators.py:347 -msgid "Please enter a valid decimal number." -msgstr "Vennligst skriv inn et godkjent desimal tall." +msgid "%.1f MB" +msgstr "" -#: core/validators.py:349 +#: template/defaultfilters.py:519 #, python-format -msgid "Please enter a valid decimal number with at most %s total digit." -msgid_plural "Please enter a valid decimal number with at most %s total digits." -msgstr[0] "Skriv inn et desimal tall med maksimum %s total antall tall." -msgstr[1] "Skriv inn et desimal tall med maksimum %s total antall tall." +msgid "%.1f GB" +msgstr "" -#: core/validators.py:352 +#: oldforms/__init__.py:408 #, python-format -msgid "Please enter a valid decimal number with at most %s decimal place." -msgid_plural "Please enter a valid decimal number with at most %s decimal places." -msgstr[0] "Skriv inn et desimal tall med maksimum %s tall bak komma. " -msgstr[1] "Skriv inn et desimal tall med maksimum %s tall bak komma. " +msgid "Ensure your text is less than %s character." +msgid_plural "Ensure your text is less than %s characters." +msgstr[0] "Sjekk at teksten er kortere enn %s tegn." +msgstr[1] "Sjekk at teksten er kortere enn %s tegn." -#: core/validators.py:362 -#, python-format -msgid "Make sure your uploaded file is at least %s bytes big." -msgstr "Vær sikker på at fila du prøver å laste opp er minimum %s bytes stor." +#: oldforms/__init__.py:413 +msgid "Line breaks are not allowed here." +msgstr "Det er ikke tillatt med linjeskift her." -#: core/validators.py:363 +#: oldforms/__init__.py:511 oldforms/__init__.py:585 oldforms/__init__.py:624 #, python-format -msgid "Make sure your uploaded file is at most %s bytes big." -msgstr "Vær sikker på at fila du prøver å laste opp er maksimum %s bytes stor." - -#: core/validators.py:376 -msgid "The format for this field is wrong." -msgstr "Formatet i dette feltet er feil." - -#: core/validators.py:391 -msgid "This field is invalid." -msgstr "Dette feltet er feil." +msgid "Select a valid choice; '%(data)s' is not in %(choices)s." +msgstr "Velg et gyldig valg; '%(data)s' er ikke i %(choices)s." -#: core/validators.py:426 -#, python-format -msgid "Could not retrieve anything from %s." -msgstr "Klarte ikke å motta noe fra %s." +#: oldforms/__init__.py:688 newforms/fields.py:380 +msgid "The submitted file is empty." +msgstr "Filen er tom." -#: core/validators.py:429 -#, python-format -msgid "The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'." -msgstr "" -"Internettadressen %(url)s returnerte en ikke godkjent Content-Type '%" -"(contenttype)s'." +#: oldforms/__init__.py:744 +msgid "Enter a whole number between -32,768 and 32,767." +msgstr "Skriv inn et heltall mellom -32768 og 32767." -#: core/validators.py:462 -#, python-format -msgid "" -"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with " -"\"%(start)s\".)" -msgstr "" -"Vennligst lukk taggen %(tag)s på linje %(line)s. (Linjen starer med \"%(start)" -"s\".)" +#: oldforms/__init__.py:754 +msgid "Enter a positive number." +msgstr "Skriv inn et positivt heltall." -#: core/validators.py:466 -#, python-format -msgid "" -"Some text starting on line %(line)s is not allowed in that context. (Line " -"starts with \"%(start)s\".)" -msgstr "" -"Noe av teksten som starter på linje %(line)s er ikke tillatt. (Linjen starter " -"med \"%(start)s\".)" +#: oldforms/__init__.py:764 +msgid "Enter a whole number between 0 and 32,767." +msgstr "Skriv inn et heltall mellom 0 og 32767." -#: core/validators.py:471 -#, python-format -msgid "" -"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%" -"(start)s\".)" -msgstr "" -"\"%(attr)s\" på linje %(line)s er ikke en godkjent tillegg. (Linjen starter " -"med \"%(start)s\".)" +#: newforms/models.py:180 newforms/fields.py:478 +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Velg et gyldig valg. Ditt valg er ikke et av de gyldige valgene." -#: core/validators.py:476 -#, python-format -msgid "" -"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%" -"(start)s\".)" -msgstr "" -"\"<%(tag)s>\" på linje %(line)s er ikke en godkjent tag. (linjen starter med " -"\"%(start)s\".)" +#: newforms/models.py:197 newforms/fields.py:494 newforms/fields.py:570 +msgid "Enter a list of values." +msgstr "Skriv inn en liste med verdier." -#: core/validators.py:480 +#: newforms/models.py:203 newforms/fields.py:500 #, python-format -msgid "" -"A tag on line %(line)s is missing one or more required attributes. (Line " -"starts with \"%(start)s\".)" -msgstr "" -"En tag på linje %(line)s mangler en av de påkrevde attributtene. (linjen starter " -"med \"%(start)s\".)" +msgid "Select a valid choice. %s is not one of the available choices." +msgstr "Velg et gyldig valg; %s er ikke et av de tilgjengelige valgene." -#: core/validators.py:485 +#: newforms/fields.py:116 #, python-format -msgid "" -"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line " -"starts with \"%(start)s\".)" -msgstr "" -"\"%(attr)s\" tillegg på linje %(line)s har en ikke godkjent verdi. (Linjen " -"starter med \"%(start)s\".)" +msgid "Ensure this value has at most %(max)d characters (it has %(length)d)." +msgstr "Pass på at denne er på maks %(max)d tegn (den er %(length)d)." -#: db/models/manipulators.py:302 +#: newforms/fields.py:118 #, python-format -msgid "%(object)s with this %(type)s already exists for the given %(field)s." -msgstr "%(object)s med %(type)s finnes allerede for angitt %(field)s." +msgid "Ensure this value has at least %(min)d characters (it has %(length)d)." +msgstr "Pass på at denne er på minst %(min)d tegn (den er %(length)d)." -#: db/models/fields/__init__.py:40 +#: newforms/fields.py:144 newforms/fields.py:167 newforms/fields.py:197 #, python-format -msgid "%(optname)s with this %(fieldname)s already exists." -msgstr "%(optname)s med %(fieldname)s finnes allerede." +msgid "Ensure this value is less than or equal to %s." +msgstr "Pass på at denne er mindre eller lik %s." -#: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265 -#: db/models/fields/__init__.py:542 db/models/fields/__init__.py:553 -#: forms/__init__.py:346 -msgid "This field is required." -msgstr "Dette feltet er påkrevd." - -#: db/models/fields/__init__.py:337 -msgid "This value must be an integer." -msgstr "Denne verdien må være et heltall." - -#: db/models/fields/__init__.py:369 -msgid "This value must be either True or False." -msgstr "Denne verdien må være enten \"True\" eller \"False\"." - -#: db/models/fields/__init__.py:385 -msgid "This field cannot be null." -msgstr "Dette feltet kan ikke være null/tom." - -#: db/models/fields/__init__.py:562 -msgid "Enter a valid filename." -msgstr "Skriv inn et godkjent fil navn." - -#: db/models/fields/related.py:43 +#: newforms/fields.py:146 newforms/fields.py:169 newforms/fields.py:199 #, python-format -msgid "Please enter a valid %s." -msgstr "Vennligst skriv inn en/et gyldig %s." +msgid "Ensure this value is greater than or equal to %s." +msgstr "Pass på at denne er større eller lik %s." -#: db/models/fields/related.py:579 -msgid "Separate multiple IDs with commas." -msgstr "Separer Id-ene med kommaer." +#: newforms/fields.py:165 newforms/fields.py:192 +msgid "Enter a number." +msgstr "Skriv inn et tall." -#: db/models/fields/related.py:581 -msgid "Hold down \"Control\", or \"Command\" on a Mac, to select more than one." -msgstr "Hold nede \"Control\", eller \"Command\" på en Mac, for å velge mere enn en." - -#: db/models/fields/related.py:625 +#: newforms/fields.py:201 #, python-format -msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid." -msgid_plural "Please enter valid %(self)s IDs. The values %(value)r are invalid." -msgstr[0] "Skriv inn gyldige %(self)s ID-er. Verdien %(value)r er ikke gyldig." -msgstr[1] "Skriv inn gyldige %(self)s ID-er. Verdiene %(value)r er ikke gyldige." +msgid "Ensure that there are no more than %s digits in total." +msgstr "Pass på at det ikke er mer enn %s siffer totalt." -#: forms/__init__.py:380 +#: newforms/fields.py:203 #, python-format -msgid "Ensure your text is less than %s character." -msgid_plural "Ensure your text is less than %s characters." -msgstr[0] "Sjekk at teksten er kortere enn %s bokstav" -msgstr[1] "Sjekk at teksten er kortere enn %s bokstaver" - -#: forms/__init__.py:385 -msgid "Line breaks are not allowed here." -msgstr "Det er ikke tillatt med flere linjer her." +msgid "Ensure that there are no more than %s decimal places." +msgstr "Pass på at ikke er mer enn %s desimaler." -#: forms/__init__.py:480 forms/__init__.py:551 forms/__init__.py:589 +#: newforms/fields.py:205 #, python-format -msgid "Select a valid choice; '%(data)s' is not in %(choices)s." -msgstr "Velg et gyldig valg; '%(data)s' er ikke i %(choices)s." +msgid "Ensure that there are no more than %s digits before the decimal point." +msgstr "Pass på at det ikke er mer enn %s siffer foran komma." -#: forms/__init__.py:645 -msgid "The submitted file is empty." -msgstr "Filen er tom." - -#: forms/__init__.py:699 -msgid "Enter a whole number between -32,768 and 32,767." -msgstr "Skriv inn et heltall mellom -31768 og 32767." - -#: forms/__init__.py:708 -msgid "Enter a positive number." -msgstr "Skriv inn et positivt heltall." - -#: forms/__init__.py:717 -msgid "Enter a whole number between 0 and 32,767." -msgstr "Skriv inn et heltall mellom 0 og 32767." - -#: template/defaultfilters.py:379 -msgid "yes,no,maybe" -msgstr "ja,nei,kanskje" +#: newforms/fields.py:238 newforms/fields.py:610 +msgid "Enter a valid date." +msgstr "Skriv inn en gyldig dato." -#, fuzzy -#~ msgid "Comments" -#~ msgstr "tillat kommentarer" +#: newforms/fields.py:265 newforms/fields.py:612 +msgid "Enter a valid time." +msgstr "Skriv inn et gyldig tidspunkt." -#~ msgid "String (up to 50)" -#~ msgstr "Tekst (opp til 50 tegn)" +#: newforms/fields.py:301 +msgid "Enter a valid date/time." +msgstr "Skriv inn et gyldig tidspunkt." -#~ msgid "label" -#~ msgstr "merkelapp" +#: newforms/fields.py:314 +msgid "Enter a valid value." +msgstr "Skriv inn en gyldig verdi." -#~ msgid "package" -#~ msgstr "pakke" +#: newforms/fields.py:378 +msgid "No file was submitted." +msgstr "Ingen fil ble sendt." -#~ msgid "packages" -#~ msgstr "pakker" +#: newforms/fields.py:403 newforms/fields.py:425 +msgid "Enter a valid URL." +msgstr "Skriv inn en gyldig URL." -#~ msgid "Error in Template" -#~ msgstr "Feil i mal" +#: newforms/fields.py:427 +msgid "This URL appears to be a broken link." +msgstr "Denne URL'en fører til en side som ikke eksisterer." -#~ msgid "" -#~ "\n" -#~ "In template %(name)s, error at line %(line)s:\n" -#~ msgstr "" -#~ "\n" -#~ "I mal %(name)s, var det en feil på linje %(line)s:\n" diff --git a/django/conf/locale/no/LC_MESSAGES/djangojs.mo b/django/conf/locale/no/LC_MESSAGES/djangojs.mo Binary files differindex da2854f72e..4321934ca6 100644 --- a/django/conf/locale/no/LC_MESSAGES/djangojs.mo +++ b/django/conf/locale/no/LC_MESSAGES/djangojs.mo diff --git a/django/conf/locale/no/LC_MESSAGES/djangojs.po b/django/conf/locale/no/LC_MESSAGES/djangojs.po index ab3d3b965d..035c1bc5bf 100644 --- a/django/conf/locale/no/LC_MESSAGES/djangojs.po +++ b/django/conf/locale/no/LC_MESSAGES/djangojs.po @@ -1,6 +1,6 @@ -# translation of djangojs.po to -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. +# translation of djangojs.po to norwegian +# Copyright (C) 2005 and beyond +# This file is distributed under the same license as the Django package. # Espen Grindhaug <espen.grindhaug@mail.com>, 2006. # msgid "" @@ -8,16 +8,14 @@ msgstr "" "Project-Id-Version: djangojs\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2005-12-09 11:51+0100\n" -"PO-Revision-Date: 2007-04-27 06:51+0200\n" -"Last-Translator: \n" -"Language-Team: <en@li.org>\n" +"PO-Revision-Date: 2007-08-29 18:22+0200\n" +"Last-Translator: jonklo\n" +"Language-Team: Norsk <no@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: KBabel 1.11.4\n" #: contrib/admin/media/js/SelectFilter2.js:33 -#, perl-format msgid "Available %s" msgstr "%s er tilgjengelige" @@ -34,13 +32,12 @@ msgid "Remove" msgstr "Slett" #: contrib/admin/media/js/SelectFilter2.js:53 -#, perl-format msgid "Chosen %s" msgstr "%s er valgt" #: contrib/admin/media/js/SelectFilter2.js:54 msgid "Select your choice(s) and click " -msgstr "Velg ditt svaralternativ(er) og klikk" +msgstr "Velg ditt svaralternativ(er) og klikk " #: contrib/admin/media/js/SelectFilter2.js:59 msgid "Clear all" @@ -85,15 +82,15 @@ msgstr "Velg et klokkeslett" #: contrib/admin/media/js/admin/DateTimeShortcuts.js:81 msgid "Midnight" -msgstr "24.00" +msgstr "Midnatt" #: contrib/admin/media/js/admin/DateTimeShortcuts.js:82 msgid "6 a.m." -msgstr "06.00" +msgstr "06:00" #: contrib/admin/media/js/admin/DateTimeShortcuts.js:83 msgid "Noon" -msgstr "12.00" +msgstr "12:00" #: contrib/admin/media/js/admin/DateTimeShortcuts.js:87 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:168 diff --git a/django/conf/locale/te/LC_MESSAGES/django.mo b/django/conf/locale/te/LC_MESSAGES/django.mo Binary files differindex 8823b2015c..e86df1c91c 100644 --- a/django/conf/locale/te/LC_MESSAGES/django.mo +++ b/django/conf/locale/te/LC_MESSAGES/django.mo diff --git a/django/conf/locale/te/LC_MESSAGES/django.po b/django/conf/locale/te/LC_MESSAGES/django.po index 248baf2249..e0c600ba3e 100644 --- a/django/conf/locale/te/LC_MESSAGES/django.po +++ b/django/conf/locale/te/LC_MESSAGES/django.po @@ -14,7 +14,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: KBabel 1.11.4\n" -"Plural-Forms: nplurals=2; nplurals=n>1;" +"Plural-Forms: nplurals=2; plural=n>1;" #: contrib/comments/models.py:67 contrib/comments/models.py:166 msgid "object ID" diff --git a/django/conf/locale/tr/LC_MESSAGES/djangojs.mo b/django/conf/locale/tr/LC_MESSAGES/djangojs.mo Binary files differindex 1119203925..9d5b8e2f51 100644 --- a/django/conf/locale/tr/LC_MESSAGES/djangojs.mo +++ b/django/conf/locale/tr/LC_MESSAGES/djangojs.mo diff --git a/django/conf/locale/tr/LC_MESSAGES/djangojs.po b/django/conf/locale/tr/LC_MESSAGES/djangojs.po index 35928b9c03..037fcd337d 100644 --- a/django/conf/locale/tr/LC_MESSAGES/djangojs.po +++ b/django/conf/locale/tr/LC_MESSAGES/djangojs.po @@ -107,3 +107,9 @@ msgstr "Dün" #: contrib/admin/media/js/admin/DateTimeShortcuts.js:164 msgid "Tomorrow" msgstr "Yarın" + +msgid "Show" +msgstr "Göster" + +msgid "Hide" +msgstr "Gizle" diff --git a/django/conf/project_template/settings.py b/django/conf/project_template/settings.py index ecd716b50d..d5748d7cc3 100644 --- a/django/conf/project_template/settings.py +++ b/django/conf/project_template/settings.py @@ -24,7 +24,7 @@ DATABASE_PORT = '' # Set to empty string for default. Not used with TIME_ZONE = 'America/Chicago' # Language code for this installation. All choices can be found here: -# http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes +# http://www.i18nguy.com/unicode/language-identifiers.html LANGUAGE_CODE = 'en-us' SITE_ID = 1 diff --git a/django/contrib/admin/media/css/null.css b/django/contrib/admin/media/css/null.css new file mode 100644 index 0000000000..1a93f22058 --- /dev/null +++ b/django/contrib/admin/media/css/null.css @@ -0,0 +1 @@ +/* Nothing to see here. Dummy file to feed to the high pass filter which hides CSS from IE5/win. Details: http://tantek.com/CSS/Examples/highpass.html */
\ No newline at end of file diff --git a/django/contrib/admin/media/css/widgets.css b/django/contrib/admin/media/css/widgets.css index bf526bfd66..67d9662f3e 100644 --- a/django/contrib/admin/media/css/widgets.css +++ b/django/contrib/admin/media/css/widgets.css @@ -43,7 +43,7 @@ p.file-upload { line-height:20px; margin:0; padding:0; color:#666; font-size:11p /* CALENDARS & CLOCKS */ .calendarbox, .clockbox { margin:5px auto; font-size:11px; width:16em; text-align:center; background:white; position:relative; } -.clockbox { width:9em; } +.clockbox { width:auto; } .calendar { margin:0; padding: 0; } .calendar table { margin:0; padding:0; border-collapse:collapse; background:white; width:99%; } .calendar caption, .calendarbox h2 { margin: 0; font-size:11px; text-align:center; border-top:none; } diff --git a/django/contrib/admin/media/js/SelectFilter2.js b/django/contrib/admin/media/js/SelectFilter2.js index 8f6079e0b3..db946a6f6f 100644 --- a/django/contrib/admin/media/js/SelectFilter2.js +++ b/django/contrib/admin/media/js/SelectFilter2.js @@ -58,7 +58,7 @@ var SelectFilter = { quickElement('h2', selector_chosen, interpolate(gettext('Chosen %s'), [field_name])); var selector_filter = quickElement('p', selector_chosen, gettext('Select your choice(s) and click ')); selector_filter.className = 'selector-filter'; - quickElement('img', selector_filter, '', 'src', admin_media_prefix + 'img/admin/selector-add.gif', 'alt', 'Add'); + quickElement('img', selector_filter, '', 'src', admin_media_prefix + (is_stacked ? 'img/admin/selector_stacked-add.gif':'img/admin/selector-add.gif'), 'alt', 'Add'); var to_box = quickElement('select', selector_chosen, '', 'id', field_id + '_to', 'multiple', 'multiple', 'size', from_box.size, 'name', from_box.getAttribute('name')); to_box.className = 'filtered'; var clear_all = quickElement('a', selector_chosen, gettext('Clear all'), 'href', 'javascript: (function() { SelectBox.move_all("' + field_id + '_to", "' + field_id + '_from");})()'); diff --git a/django/contrib/admin/media/js/admin/DateTimeShortcuts.js b/django/contrib/admin/media/js/admin/DateTimeShortcuts.js index b1504fc819..4682a6841a 100644 --- a/django/contrib/admin/media/js/admin/DateTimeShortcuts.js +++ b/django/contrib/admin/media/js/admin/DateTimeShortcuts.js @@ -195,6 +195,19 @@ var DateTimeShortcuts = { openCalendar: function(num) { var cal_box = document.getElementById(DateTimeShortcuts.calendarDivName1+num) var cal_link = document.getElementById(DateTimeShortcuts.calendarLinkName+num) + var inp = DateTimeShortcuts.calendarInputs[num]; + + // Determine if the current value in the input has a valid date. + // If so, draw the calendar with that date's year and month. + if (inp.value) { + var date_parts = inp.value.split('-'); + var year = date_parts[0]; + var month = parseFloat(date_parts[1]); + if (year.match(/\d\d\d\d/) && month >= 1 && month <= 12) { + DateTimeShortcuts.calendars[num].drawDate(month, year); + } + } + // Recalculate the clockbox position // is it left-to-right or right-to-left layout ? diff --git a/django/contrib/admin/media/js/core.js b/django/contrib/admin/media/js/core.js index a17ac8a4d2..c8d0db6a8d 100644 --- a/django/contrib/admin/media/js/core.js +++ b/django/contrib/admin/media/js/core.js @@ -1,5 +1,9 @@ // Core javascript helper functions +// basic browser identification & version +var isOpera = (navigator.userAgent.indexOf("Opera")>=0) && parseFloat(navigator.appVersion); +var isIE = ((document.all) && (!isOpera)) && parseFloat(navigator.appVersion.split("MSIE ")[1].split(";")[0]); + // Cross-browser event handlers. function addEvent(obj, evType, fn) { if (obj.addEventListener) { @@ -71,9 +75,13 @@ function findPosX(obj) { var curleft = 0; if (obj.offsetParent) { while (obj.offsetParent) { - curleft += obj.offsetLeft; + curleft += obj.offsetLeft - ((isOpera) ? 0 : obj.scrollLeft); obj = obj.offsetParent; } + // IE offsetParent does not include the top-level + if (isIE && obj.parentElement){ + curleft += obj.offsetLeft - obj.scrollLeft; + } } else if (obj.x) { curleft += obj.x; } @@ -84,9 +92,13 @@ function findPosY(obj) { var curtop = 0; if (obj.offsetParent) { while (obj.offsetParent) { - curtop += obj.offsetTop; + curtop += obj.offsetTop - ((isOpera) ? 0 : obj.scrollTop); obj = obj.offsetParent; } + // IE offsetParent does not include the top-level + if (isIE && obj.parentElement){ + curtop += obj.offsetTop - obj.scrollTop; + } } else if (obj.y) { curtop += obj.y; } diff --git a/django/contrib/admin/media/js/urlify.js b/django/contrib/admin/media/js/urlify.js index 1545d80ec9..40320979be 100644 --- a/django/contrib/admin/media/js/urlify.js +++ b/django/contrib/admin/media/js/urlify.js @@ -40,6 +40,9 @@ var RUSSIAN_MAP = { 'Ч':'Ch', 'Ш':'Sh', 'Щ':'Sh', 'Ъ':'', 'Ы':'Y', 'Ь':'', 'Э':'E', 'Ю':'Yu', 'Я':'Ya' } +var UKRAINIAN_MAP = { + 'Є':'Ye', 'І':'I', 'Ї':'Yi', 'Ґ':'G', 'є':'ye', 'і':'i', 'ї':'yi', 'ґ':'g' +} var CZECH_MAP = { 'č':'c', 'ď':'d', 'ě':'e', 'ň': 'n', 'ř':'r', 'š':'s', 'ť':'t', 'ů':'u', 'ž':'z' @@ -51,7 +54,8 @@ ALL_DOWNCODE_MAPS[1]=LATIN_SYMBOLS_MAP ALL_DOWNCODE_MAPS[2]=GREEK_MAP ALL_DOWNCODE_MAPS[3]=TURKISH_MAP ALL_DOWNCODE_MAPS[4]=RUSSIAN_MAP -ALL_DOWNCODE_MAPS[5]=CZECH_MAP +ALL_DOWNCODE_MAPS[5]=UKRAINIAN_MAP +ALL_DOWNCODE_MAPS[6]=CZECH_MAP var Downcoder = new Object(); Downcoder.Initialize = function() diff --git a/django/contrib/admin/templates/admin/auth/user/change_password.html b/django/contrib/admin/templates/admin/auth/user/change_password.html index d9c1eae637..28e342da86 100644 --- a/django/contrib/admin/templates/admin/auth/user/change_password.html +++ b/django/contrib/admin/templates/admin/auth/user/change_password.html @@ -6,7 +6,6 @@ {% endblock %} {% block stylesheet %}{% admin_media_prefix %}css/forms.css{% endblock %} {% block bodyclass %}{{ opts.app_label }}-{{ opts.object_name.lower }} change-form{% endblock %} -{% block userlinks %}<a href="../../../../doc/">{% trans 'Documentation' %}</a> / <a href="../../../../password_change/">{% trans 'Change password' %}</a> / <a href="../../../../logout/">{% trans 'Log out' %}</a>{% endblock %} {% block breadcrumbs %}{% if not is_popup %} <div class="breadcrumbs"> <a href="../../../../">{% trans "Home" %}</a> › diff --git a/django/contrib/admin/templates/admin/base.html b/django/contrib/admin/templates/admin/base.html index d3e8c96b91..cdd3561ab9 100644 --- a/django/contrib/admin/templates/admin/base.html +++ b/django/contrib/admin/templates/admin/base.html @@ -22,7 +22,14 @@ {% block branding %}{% endblock %} </div> {% if user.is_authenticated and user.is_staff %} - <div id="user-tools">{% trans 'Welcome,' %} <strong>{% if user.first_name %}{{ user.first_name|escape }}{% else %}{{ user.username }}{% endif %}</strong>. {% block userlinks %}<a href="doc/">{% trans 'Documentation' %}</a> / <a href="password_change/">{% trans 'Change password' %}</a> / <a href="logout/">{% trans 'Log out' %}</a>{% endblock %}</div> + <div id="user-tools"> + {% trans 'Welcome,' %} <strong>{% if user.first_name %}{{ user.first_name|escape }}{% else %}{{ user.username }}{% endif %}</strong>. + {% block userlinks %} + <a href="{% url django.contrib.admin.views.doc.doc_index %}">{% trans 'Documentation' %}</a> + / <a href="{% url django.contrib.auth.views.password_change %}">{% trans 'Change password' %}</a> + / <a href="{% url django.contrib.auth.views.logout %}">{% trans 'Log out' %}</a> + {% endblock %} + </div> {% endif %} {% block nav-global %}{% endblock %} </div> diff --git a/django/contrib/admin/templates/admin/change_form.html b/django/contrib/admin/templates/admin/change_form.html index 7e7b639139..49e709caf6 100644 --- a/django/contrib/admin/templates/admin/change_form.html +++ b/django/contrib/admin/templates/admin/change_form.html @@ -7,7 +7,6 @@ {% block stylesheet %}{% admin_media_prefix %}css/forms.css{% endblock %} {% block coltype %}{% if ordered_objects %}colMS{% else %}colM{% endif %}{% endblock %} {% block bodyclass %}{{ opts.app_label }}-{{ opts.object_name.lower }} change-form{% endblock %} -{% block userlinks %}<a href="../../../doc/">{% trans 'Documentation' %}</a> / <a href="../../../password_change/">{% trans 'Change password' %}</a> / <a href="../../../logout/">{% trans 'Log out' %}</a>{% endblock %} {% block breadcrumbs %}{% if not is_popup %} <div class="breadcrumbs"> <a href="../../../">{% trans "Home" %}</a> › diff --git a/django/contrib/admin/templates/admin/change_list.html b/django/contrib/admin/templates/admin/change_list.html index f50a73c934..611c5ff8fc 100644 --- a/django/contrib/admin/templates/admin/change_list.html +++ b/django/contrib/admin/templates/admin/change_list.html @@ -2,7 +2,6 @@ {% load adminmedia admin_list i18n %} {% block stylesheet %}{% admin_media_prefix %}css/changelists.css{% endblock %} {% block bodyclass %}change-list{% endblock %} -{% block userlinks %}<a href="../../doc/">{% trans 'Documentation' %}</a> / <a href="../../password_change/">{% trans 'Change password' %}</a> / <a href="../../logout/">{% trans 'Log out' %}</a>{% endblock %} {% if not is_popup %}{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans "Home" %}</a> › {{ cl.opts.verbose_name_plural|capfirst|escape }}</div>{% endblock %}{% endif %} {% block coltype %}flex{% endblock %} {% block content %} diff --git a/django/contrib/admin/templates/admin/change_list_results.html b/django/contrib/admin/templates/admin/change_list_results.html index 3f755783dc..381dcb5d5d 100644 --- a/django/contrib/admin/templates/admin/change_list_results.html +++ b/django/contrib/admin/templates/admin/change_list_results.html @@ -10,7 +10,7 @@ </thead> <tbody> {% for result in results %} -<tr class="{% cycle row1,row2 %}">{% for item in result %}{{ item }}{% endfor %}</tr> +<tr class="{% cycle 'row1' 'row2' %}">{% for item in result %}{{ item }}{% endfor %}</tr> {% endfor %} </tbody> </table> diff --git a/django/contrib/admin/templates/admin/delete_confirmation.html b/django/contrib/admin/templates/admin/delete_confirmation.html index 3921ab69e3..ac9634a9e9 100644 --- a/django/contrib/admin/templates/admin/delete_confirmation.html +++ b/django/contrib/admin/templates/admin/delete_confirmation.html @@ -1,6 +1,5 @@ {% extends "admin/base_site.html" %} {% load i18n %} -{% block userlinks %}<a href="../../../../doc/">{% trans 'Documentation' %}</a> / <a href="../../../../password_change/">{% trans 'Change password' %}</a> / <a href="../../../../logout/">{% trans 'Log out' %}</a>{% endblock %} {% block breadcrumbs %} <div class="breadcrumbs"> <a href="../../../../">{% trans "Home" %}</a> › diff --git a/django/contrib/admin/templates/admin/object_history.html b/django/contrib/admin/templates/admin/object_history.html index 14a77b8a31..34529f69db 100644 --- a/django/contrib/admin/templates/admin/object_history.html +++ b/django/contrib/admin/templates/admin/object_history.html @@ -1,6 +1,5 @@ {% extends "admin/base_site.html" %} {% load i18n %} -{% block userlinks %}<a href="../../../../doc/">{% trans 'Documentation' %}</a> / <a href="../../../../password_change/">{% trans 'Change password' %}</a> / <a href="../../../../logout/">{% trans 'Log out' %}</a>{% endblock %} {% block breadcrumbs %} <div class="breadcrumbs"><a href="../../../../">{% trans 'Home' %}</a> › <a href="../../">{{ module_name|escape }}</a> › <a href="../">{{ object|escape|truncatewords:"18" }}</a> › {% trans 'History' %}</div> {% endblock %} diff --git a/django/contrib/admin/templates/admin_doc/bookmarklets.html b/django/contrib/admin/templates/admin_doc/bookmarklets.html index fa5942926f..64475299c2 100644 --- a/django/contrib/admin/templates/admin_doc/bookmarklets.html +++ b/django/contrib/admin/templates/admin_doc/bookmarklets.html @@ -1,7 +1,6 @@ {% extends "admin/base_site.html" %} {% block breadcrumbs %}{% load i18n %}<div class="breadcrumbs"><a href="../../">{% trans "Home" %}</a> › <a href="../">{% trans "Documentation" %}</a> › {% trans "Bookmarklets" %}</div>{% endblock %} -{% block userlinks %}<a href="../../password_change/">{% trans 'Change password' %}</a> / <a href="../../logout/">{% trans 'Log out' %}</a>{% endblock %} {% block title %}{% trans "Documentation bookmarklets" %}{% endblock %} {% block content %} diff --git a/django/contrib/admin/templates/admin_doc/index.html b/django/contrib/admin/templates/admin_doc/index.html index 74f9f20916..64766fb46f 100644 --- a/django/contrib/admin/templates/admin_doc/index.html +++ b/django/contrib/admin/templates/admin_doc/index.html @@ -1,7 +1,6 @@ {% extends "admin/base_site.html" %}
{% load i18n %}
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../">Home</a> › Documentation</div>{% endblock %}
-{% block userlinks %}<a href="../password_change/">{% trans 'Change password' %}</a> / <a href="../logout/">{% trans 'Log out' %}</a>{% endblock %}
{% block title %}Documentation{% endblock %}
{% block content %}
diff --git a/django/contrib/admin/templates/admin_doc/missing_docutils.html b/django/contrib/admin/templates/admin_doc/missing_docutils.html index cdeab0cdd8..97c9d4711c 100644 --- a/django/contrib/admin/templates/admin_doc/missing_docutils.html +++ b/django/contrib/admin/templates/admin_doc/missing_docutils.html @@ -1,7 +1,6 @@ {% extends "admin/base_site.html" %} {% load i18n %} {% block breadcrumbs %}<div class="breadcrumbs"><a href="../">Home</a> › Documentation</div>{% endblock %} -{% block userlinks %}<a href="../password_change/">{% trans 'Change password' %}</a> / <a href="../logout/">{% trans 'Log out' %}</a>{% endblock %} {% block title %}Please install docutils{% endblock %} {% block content %} diff --git a/django/contrib/admin/templates/admin_doc/model_detail.html b/django/contrib/admin/templates/admin_doc/model_detail.html index 70133e26dd..e19e31d891 100644 --- a/django/contrib/admin/templates/admin_doc/model_detail.html +++ b/django/contrib/admin/templates/admin_doc/model_detail.html @@ -1,6 +1,5 @@ {% extends "admin/base_site.html" %} {% load i18n %} -{% block userlinks %}<a href="../../../password_change/">{% trans 'Change password' %}</a> / <a href="../../../logout/">{% trans 'Log out' %}</a>{% endblock %} {% block extrahead %} {{ block.super }} <style type="text/css"> diff --git a/django/contrib/admin/templates/admin_doc/model_index.html b/django/contrib/admin/templates/admin_doc/model_index.html index c681da75c9..702fdff329 100644 --- a/django/contrib/admin/templates/admin_doc/model_index.html +++ b/django/contrib/admin/templates/admin_doc/model_index.html @@ -2,7 +2,6 @@ {% load i18n %} {% block coltype %}colSM{% endblock %} {% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">Home</a> › <a href="../">Documentation</a> › Models</div>{% endblock %} -{% block userlinks %}<a href="../../password_change/">{% trans 'Change password' %}</a> / <a href="../../logout/">{% trans 'Log out' %}</a>{% endblock %} {% block title %}Models{% endblock %} diff --git a/django/contrib/admin/templates/admin_doc/template_detail.html b/django/contrib/admin/templates/admin_doc/template_detail.html index 280ea912d0..a8b02bd189 100644 --- a/django/contrib/admin/templates/admin_doc/template_detail.html +++ b/django/contrib/admin/templates/admin_doc/template_detail.html @@ -1,7 +1,6 @@ {% extends "admin/base_site.html" %} {% load i18n %} {% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Home</a> › <a href="../../">Documentation</a> › Templates › {{ name|escape }}</div>{% endblock %} -{% block userlinks %}<a href="../../../password_change/">{% trans 'Change password' %}</a> / <a href="../../../logout/">{% trans 'Log out' %}</a>{% endblock %} {% block title %}Template: {{ name|escape }}{% endblock %} diff --git a/django/contrib/admin/templates/admin_doc/template_filter_index.html b/django/contrib/admin/templates/admin_doc/template_filter_index.html index 72344c16cb..f67f14eb35 100644 --- a/django/contrib/admin/templates/admin_doc/template_filter_index.html +++ b/django/contrib/admin/templates/admin_doc/template_filter_index.html @@ -2,7 +2,6 @@ {% load i18n %} {% block coltype %}colSM{% endblock %} {% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">Home</a> › <a href="../">Documentation</a> › filters</div>{% endblock %} -{% block userlinks %}<a href="../../password_change/">{% trans 'Change password' %}</a> / <a href="../../logout/">{% trans 'Log out' %}</a>{% endblock %} {% block title %}Template filters{% endblock %} {% block content %} diff --git a/django/contrib/admin/templates/admin_doc/template_tag_index.html b/django/contrib/admin/templates/admin_doc/template_tag_index.html index 287475ab09..9bd66b70e7 100644 --- a/django/contrib/admin/templates/admin_doc/template_tag_index.html +++ b/django/contrib/admin/templates/admin_doc/template_tag_index.html @@ -2,7 +2,6 @@ {% load i18n %} {% block coltype %}colSM{% endblock %} {% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">Home</a> › <a href="../">Documentation</a> › Tags</div>{% endblock %} -{% block userlinks %}<a href="../../password_change/">{% trans 'Change password' %}</a> / <a href="../../logout/">{% trans 'Log out' %}</a>{% endblock %} {% block title %}Template tags{% endblock %} {% block content %} diff --git a/django/contrib/admin/templates/admin_doc/view_detail.html b/django/contrib/admin/templates/admin_doc/view_detail.html index ba90399358..d7415ab74f 100644 --- a/django/contrib/admin/templates/admin_doc/view_detail.html +++ b/django/contrib/admin/templates/admin_doc/view_detail.html @@ -1,7 +1,6 @@ {% extends "admin/base_site.html" %} {% load i18n %} {% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Home</a> › <a href="../../">Documentation</a> › <a href="../">Views</a> › {{ name }}</div>{% endblock %} -{% block userlinks %}<a href="../../../password_change/">{% trans 'Change password' %}</a> / <a href="../../../logout/">{% trans 'Log out' %}</a>{% endblock %} {% block title %}View: {{ name }}{% endblock %} {% block content %} diff --git a/django/contrib/admin/templates/admin_doc/view_index.html b/django/contrib/admin/templates/admin_doc/view_index.html index caab8a2e71..47f99350a3 100644 --- a/django/contrib/admin/templates/admin_doc/view_index.html +++ b/django/contrib/admin/templates/admin_doc/view_index.html @@ -2,7 +2,6 @@ {% load i18n %}
{% block coltype %}colSM{% endblock %}
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">Home</a> › <a href="../">Documentation</a> › Views</div>{% endblock %}
-{% block userlinks %}<a href="../../password_change/">{% trans 'Change password' %}</a> / <a href="../../logout/">{% trans 'Log out' %}</a>{% endblock %}
{% block title %}Views{% endblock %}
{% block content %}
diff --git a/django/contrib/admin/templates/registration/password_change_done.html b/django/contrib/admin/templates/registration/password_change_done.html index 252572001d..4498c63a37 100644 --- a/django/contrib/admin/templates/registration/password_change_done.html +++ b/django/contrib/admin/templates/registration/password_change_done.html @@ -1,6 +1,5 @@ {% extends "admin/base_site.html" %} {% load i18n %} -{% block userlinks %}<a href="../../doc/">{% trans 'Documentation' %}</a> / {% trans 'Change password' %} / <a href="../../logout/">{% trans 'Log out' %}</a>{% endblock %} {% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans 'Home' %}</a> › {% trans 'Password change' %}</div>{% endblock %} {% block title %}{% trans 'Password change successful' %}{% endblock %} diff --git a/django/contrib/admin/templates/registration/password_change_form.html b/django/contrib/admin/templates/registration/password_change_form.html index 036d56212c..cd2b1e0c8a 100644 --- a/django/contrib/admin/templates/registration/password_change_form.html +++ b/django/contrib/admin/templates/registration/password_change_form.html @@ -1,6 +1,5 @@ {% extends "admin/base_site.html" %} {% load i18n %} -{% block userlinks %}<a href="../doc/">{% trans 'Documentation' %}</a> / {% trans 'Change password' %} / <a href="../logout/">{% trans 'Log out' %}</a>{% endblock %} {% block breadcrumbs %}<div class="breadcrumbs"><a href="../">{% trans 'Home' %}</a> › {% trans 'Password change' %}</div>{% endblock %} {% block title %}{% trans 'Password change' %}{% endblock %} diff --git a/django/contrib/admin/views/doc.py b/django/contrib/admin/views/doc.py index 37caa0f43b..2ebd0cd282 100644 --- a/django/contrib/admin/views/doc.py +++ b/django/contrib/admin/views/doc.py @@ -5,7 +5,7 @@ from django.contrib.admin.views.decorators import staff_member_required from django.db import models from django.shortcuts import render_to_response from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist -from django.http import Http404, get_host +from django.http import Http404 from django.core import urlresolvers from django.contrib.admin import utils from django.contrib.sites.models import Site @@ -29,7 +29,7 @@ def bookmarklets(request): # Hack! This couples this view to the URL it lives at. admin_root = request.path[:-len('doc/bookmarklets/')] return render_to_response('admin_doc/bookmarklets.html', { - 'admin_url': "%s://%s%s" % (request.is_secure() and 'https' or 'http', get_host(request), admin_root), + 'admin_url': "%s://%s%s" % (request.is_secure() and 'https' or 'http', request.get_host(), admin_root), }, context_instance=RequestContext(request)) bookmarklets = staff_member_required(bookmarklets) diff --git a/django/contrib/admin/views/main.py b/django/contrib/admin/views/main.py index cfbe9a1f95..7fa870e222 100644 --- a/django/contrib/admin/views/main.py +++ b/django/contrib/admin/views/main.py @@ -140,7 +140,7 @@ class AdminBoundField(object): def original_value(self): if self.original: - return self.original.__dict__[self.field.column] + return self.original.__dict__[self.field.attname] def existing_display(self): try: diff --git a/django/contrib/auth/backends.py b/django/contrib/auth/backends.py index 4b8efcca46..be6cfede11 100644 --- a/django/contrib/auth/backends.py +++ b/django/contrib/auth/backends.py @@ -1,3 +1,4 @@ +from django.db import connection from django.contrib.auth.models import User class ModelBackend: @@ -14,6 +15,49 @@ class ModelBackend: except User.DoesNotExist: return None + def get_group_permissions(self, user_obj): + "Returns a list of permission strings that this user has through his/her groups." + if not hasattr(user_obj, '_group_perm_cache'): + cursor = connection.cursor() + # The SQL below works out to the following, after DB quoting: + # cursor.execute(""" + # SELECT ct."app_label", p."codename" + # FROM "auth_permission" p, "auth_group_permissions" gp, "auth_user_groups" ug, "django_content_type" ct + # WHERE p."id" = gp."permission_id" + # AND gp."group_id" = ug."group_id" + # AND ct."id" = p."content_type_id" + # AND ug."user_id" = %s, [self.id]) + qn = connection.ops.quote_name + sql = """ + SELECT ct.%s, p.%s + FROM %s p, %s gp, %s ug, %s ct + WHERE p.%s = gp.%s + AND gp.%s = ug.%s + AND ct.%s = p.%s + AND ug.%s = %%s""" % ( + qn('app_label'), qn('codename'), + qn('auth_permission'), qn('auth_group_permissions'), + qn('auth_user_groups'), qn('django_content_type'), + qn('id'), qn('permission_id'), + qn('group_id'), qn('group_id'), + qn('id'), qn('content_type_id'), + qn('user_id'),) + cursor.execute(sql, [user_obj.id]) + user_obj._group_perm_cache = set(["%s.%s" % (row[0], row[1]) for row in cursor.fetchall()]) + return user_obj._group_perm_cache + + def get_all_permissions(self, user_obj): + if not hasattr(user_obj, '_perm_cache'): + user_obj._perm_cache = set([u"%s.%s" % (p.content_type.app_label, p.codename) for p in user_obj.user_permissions.select_related()]) + user_obj._perm_cache.update(self.get_group_permissions(user_obj)) + return user_obj._perm_cache + + def has_perm(self, user_obj, perm): + return perm in self.get_all_permissions(user_obj) + + def has_module_perms(self, user_obj, app_label): + return bool(len([p for p in self.get_all_permissions(user_obj) if p[:p.index('.')] == app_label])) + def get_user(self, user_id): try: return User.objects.get(pk=user_id) diff --git a/django/contrib/auth/decorators.py b/django/contrib/auth/decorators.py index 2fb4a6f510..b6481ea52c 100644 --- a/django/contrib/auth/decorators.py +++ b/django/contrib/auth/decorators.py @@ -1,8 +1,8 @@ from django.contrib.auth import REDIRECT_FIELD_NAME from django.http import HttpResponseRedirect -from urllib import quote +from django.utils.http import urlquote -def user_passes_test(test_func, login_url=None): +def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME): """ Decorator for views that checks that the user passes the given test, redirecting to the log-in page if necessary. The test should be a callable @@ -15,20 +15,25 @@ def user_passes_test(test_func, login_url=None): def _checklogin(request, *args, **kwargs): if test_func(request.user): return view_func(request, *args, **kwargs) - return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, quote(request.get_full_path()))) + return HttpResponseRedirect('%s?%s=%s' % (login_url, redirect_field_name, urlquote(request.get_full_path()))) _checklogin.__doc__ = view_func.__doc__ _checklogin.__dict__ = view_func.__dict__ return _checklogin return _dec -login_required = user_passes_test(lambda u: u.is_authenticated()) -login_required.__doc__ = ( +def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME): """ Decorator for views that checks that the user is logged in, redirecting to the log-in page if necessary. """ + actual_decorator = user_passes_test( + lambda u: u.is_authenticated(), + redirect_field_name=redirect_field_name ) + if function: + return actual_decorator(function) + return actual_decorator def permission_required(perm, login_url=None): """ diff --git a/django/contrib/auth/handlers/modpython.py b/django/contrib/auth/handlers/modpython.py index c7d921313d..de961fa4dd 100644 --- a/django/contrib/auth/handlers/modpython.py +++ b/django/contrib/auth/handlers/modpython.py @@ -10,6 +10,10 @@ def authenhandler(req, **kwargs): # that so that the following import works os.environ.update(req.subprocess_env) + # apache 2.2 requires a call to req.get_basic_auth_pw() before + # req.user and friends are available. + req.get_basic_auth_pw() + # check for PythonOptions _str_to_bool = lambda s: s.lower() in ('1', 'true', 'on', 'yes') diff --git a/django/contrib/auth/models.py b/django/contrib/auth/models.py index 3584cea533..33f92dc854 100644 --- a/django/contrib/auth/models.py +++ b/django/contrib/auth/models.py @@ -1,6 +1,8 @@ +from django.contrib import auth from django.core import validators from django.core.exceptions import ImproperlyConfigured -from django.db import connection, models +from django.db import models +from django.db.models.manager import EmptyManager from django.contrib.contenttypes.models import ContentType from django.utils.encoding import smart_str from django.utils.translation import ugettext_lazy as _ @@ -14,25 +16,43 @@ try: except NameError: from sets import Set as set # Python 2.3 fallback +def get_hexdigest(algorithm, salt, raw_password): + """ + Returns a string of the hexdigest of the given plaintext password and salt + using the given algorithm ('md5', 'sha1' or 'crypt'). + """ + raw_password, salt = smart_str(raw_password), smart_str(salt) + if algorithm == 'crypt': + try: + import crypt + except ImportError: + raise ValueError('"crypt" password algorithm not supported in this environment') + return crypt.crypt(raw_password, salt) + # The rest of the supported algorithms are supported by hashlib, but + # hashlib is only available in Python 2.5. + try: + import hashlib + except ImportError: + if algorithm == 'md5': + import md5 + return md5.new(salt + raw_password).hexdigest() + elif algorithm == 'sha1': + import sha + return sha.new(salt + raw_password).hexdigest() + else: + if algorithm == 'md5': + return hashlib.md5(salt + raw_password).hexdigest() + elif algorithm == 'sha1': + return hashlib.sha1(salt + raw_password).hexdigest() + raise ValueError("Got unknown password algorithm type in password.") + def check_password(raw_password, enc_password): """ Returns a boolean of whether the raw_password was correct. Handles encryption formats behind the scenes. """ algo, salt, hsh = enc_password.split('$') - if algo == 'md5': - import md5 - return hsh == md5.new(smart_str(salt + raw_password)).hexdigest() - elif algo == 'sha1': - import sha - return hsh == sha.new(smart_str(salt + raw_password)).hexdigest() - elif algo == 'crypt': - try: - import crypt - except ImportError: - raise ValueError, "Crypt password algorithm not supported in this environment." - return hsh == crypt.crypt(smart_str(raw_password), smart_str(salt)) - raise ValueError, "Got unknown password algorithm type in password." + return hsh == get_hexdigest(algo, salt, raw_password) class SiteProfileNotAvailable(Exception): pass @@ -161,10 +181,10 @@ class User(models.Model): return full_name.strip() def set_password(self, raw_password): - import sha, random + import random algo = 'sha1' - salt = sha.new(str(random.random())).hexdigest()[:5] - hsh = sha.new(salt + smart_str(raw_password)).hexdigest() + salt = get_hexdigest(algo, str(random.random()), str(random.random()))[:5] + hsh = get_hexdigest(algo, salt, raw_password) self.password = '%s$%s$%s' % (algo, salt, hsh) def check_password(self, raw_password): @@ -175,8 +195,7 @@ class User(models.Model): # Backwards-compatibility check. Older passwords won't include the # algorithm or salt. if '$' not in self.password: - import md5 - is_correct = (self.password == md5.new(smart_str(raw_password)).hexdigest()) + is_correct = (self.password == get_hexdigest('md5', '', raw_password)) if is_correct: # Convert the password to the new, more secure format. self.set_password(raw_password) @@ -192,64 +211,68 @@ class User(models.Model): return self.password != UNUSABLE_PASSWORD def get_group_permissions(self): - "Returns a list of permission strings that this user has through his/her groups." - if not hasattr(self, '_group_perm_cache'): - cursor = connection.cursor() - # The SQL below works out to the following, after DB quoting: - # cursor.execute(""" - # SELECT ct."app_label", p."codename" - # FROM "auth_permission" p, "auth_group_permissions" gp, "auth_user_groups" ug, "django_content_type" ct - # WHERE p."id" = gp."permission_id" - # AND gp."group_id" = ug."group_id" - # AND ct."id" = p."content_type_id" - # AND ug."user_id" = %s, [self.id]) - qn = connection.ops.quote_name - sql = """ - SELECT ct.%s, p.%s - FROM %s p, %s gp, %s ug, %s ct - WHERE p.%s = gp.%s - AND gp.%s = ug.%s - AND ct.%s = p.%s - AND ug.%s = %%s""" % ( - qn('app_label'), qn('codename'), - qn('auth_permission'), qn('auth_group_permissions'), - qn('auth_user_groups'), qn('django_content_type'), - qn('id'), qn('permission_id'), - qn('group_id'), qn('group_id'), - qn('id'), qn('content_type_id'), - qn('user_id'),) - cursor.execute(sql, [self.id]) - self._group_perm_cache = set(["%s.%s" % (row[0], row[1]) for row in cursor.fetchall()]) - return self._group_perm_cache + """ + Returns a list of permission strings that this user has through + his/her groups. This method queries all available auth backends. + """ + permissions = set() + for backend in auth.get_backends(): + if hasattr(backend, "get_group_permissions"): + permissions.update(backend.get_group_permissions(self)) + return permissions def get_all_permissions(self): - if not hasattr(self, '_perm_cache'): - self._perm_cache = set([u"%s.%s" % (p.content_type.app_label, p.codename) for p in self.user_permissions.select_related()]) - self._perm_cache.update(self.get_group_permissions()) - return self._perm_cache + permissions = set() + for backend in auth.get_backends(): + if hasattr(backend, "get_all_permissions"): + permissions.update(backend.get_all_permissions(self)) + return permissions def has_perm(self, perm): - "Returns True if the user has the specified permission." + """ + Returns True if the user has the specified permission. This method + queries all available auth backends, but returns immediately if any + backend returns True. Thus, a user who has permission from a single + auth backend is assumed to have permission in general. + """ + # Inactive users have no permissions. if not self.is_active: return False + + # Superusers have all permissions. if self.is_superuser: return True - return perm in self.get_all_permissions() + + # Otherwise we need to check the backends. + for backend in auth.get_backends(): + if hasattr(backend, "has_perm"): + if backend.has_perm(self, perm): + return True + return False def has_perms(self, perm_list): - "Returns True if the user has each of the specified permissions." + """Returns True if the user has each of the specified permissions.""" for perm in perm_list: if not self.has_perm(perm): return False return True def has_module_perms(self, app_label): - "Returns True if the user has any permissions in the given app label." + """ + Returns True if the user has any permissions in the given app + label. Uses pretty much the same logic as has_perm, above. + """ if not self.is_active: return False + if self.is_superuser: return True - return bool(len([p for p in self.get_all_permissions() if p[:p.index('.')] == app_label])) + + for backend in auth.get_backends(): + if hasattr(backend, "has_module_perms"): + if backend.has_module_perms(self, app_label): + return True + return False def get_and_delete_messages(self): messages = [] @@ -282,7 +305,12 @@ class User(models.Model): class Message(models.Model): """ - The message system is a lightweight way to queue messages for given users. A message is associated with a User instance (so it is only applicable for registered users). There's no concept of expiration or timestamps. Messages are created by the Django admin after successful actions. For example, "The poll Foo was created successfully." is a message. + The message system is a lightweight way to queue messages for given + users. A message is associated with a User instance (so it is only + applicable for registered users). There's no concept of expiration or + timestamps. Messages are created by the Django admin after successful + actions. For example, "The poll Foo was created successfully." is a + message. """ user = models.ForeignKey(User) message = models.TextField(_('message')) @@ -293,6 +321,11 @@ class Message(models.Model): class AnonymousUser(object): id = None username = '' + is_staff = False + is_active = True + is_superuser = False + _groups = EmptyManager() + _user_permissions = EmptyManager() def __init__(self): pass @@ -325,11 +358,11 @@ class AnonymousUser(object): raise NotImplementedError def _get_groups(self): - raise NotImplementedError + return self._groups groups = property(_get_groups) def _get_user_permissions(self): - raise NotImplementedError + return self._user_permissions user_permissions = property(_get_user_permissions) def has_perm(self, perm): diff --git a/django/contrib/auth/tests.py b/django/contrib/auth/tests.py index ed768aa429..329049c546 100644 --- a/django/contrib/auth/tests.py +++ b/django/contrib/auth/tests.py @@ -1,5 +1,5 @@ """ ->>> from models import User +>>> from models import User, AnonymousUser >>> u = User.objects.create_user('testuser', 'test@example.com', 'testpw') >>> u.has_usable_password() True @@ -16,4 +16,11 @@ False >>> u2 = User.objects.create_user('testuser2', 'test2@example.com') >>> u2.has_usable_password() False +>>> a = AnonymousUser() +>>> a.is_staff +False +>>> a.groups.all() +[] +>>> a.user_permissions.all() +[] """
\ No newline at end of file diff --git a/django/contrib/auth/views.py b/django/contrib/auth/views.py index f1129379d6..d3d8b4ccb7 100644 --- a/django/contrib/auth/views.py +++ b/django/contrib/auth/views.py @@ -9,10 +9,10 @@ from django.contrib.auth.decorators import login_required from django.contrib.auth import REDIRECT_FIELD_NAME from django.utils.translation import ugettext as _ -def login(request, template_name='registration/login.html'): +def login(request, template_name='registration/login.html', redirect_field_name=REDIRECT_FIELD_NAME): "Displays the login form and handles the login action." manipulator = AuthenticationForm(request) - redirect_to = request.REQUEST.get(REDIRECT_FIELD_NAME, '') + redirect_to = request.REQUEST.get(redirect_field_name, '') if request.POST: errors = manipulator.get_validation_errors(request.POST) if not errors: @@ -35,7 +35,7 @@ def login(request, template_name='registration/login.html'): return render_to_response(template_name, { 'form': oldforms.FormWrapper(manipulator, request.POST, errors), - REDIRECT_FIELD_NAME: redirect_to, + redirect_field_name: redirect_to, 'site_name': current_site.name, }, context_instance=RequestContext(request)) @@ -56,12 +56,12 @@ def logout_then_login(request, login_url=None): login_url = settings.LOGIN_URL return logout(request, login_url) -def redirect_to_login(next, login_url=None): +def redirect_to_login(next, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME): "Redirects the user to the login page, passing the given 'next' page" if not login_url: from django.conf import settings login_url = settings.LOGIN_URL - return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, next)) + return HttpResponseRedirect('%s?%s=%s' % (login_url, redirect_field_name, next)) def password_reset(request, is_admin_site=False, template_name='registration/password_reset_form.html', email_template_name='registration/password_reset_email.html'): diff --git a/django/contrib/comments/views/comments.py b/django/contrib/comments/views/comments.py index fbec04c8eb..67da5759ac 100644 --- a/django/contrib/comments/views/comments.py +++ b/django/contrib/comments/views/comments.py @@ -155,7 +155,7 @@ class PublicFreeCommentManipulator(oldforms.Manipulator): c.save() return c -def post_comment(request): +def post_comment(request, extra_context=None, context_processors=None): """ Post a comment @@ -185,6 +185,7 @@ def post_comment(request): rating_choices choice of ratings """ + if extra_context is None: extra_context = {} if not request.POST: raise Http404, _("Only POSTs are allowed") try: @@ -244,7 +245,7 @@ def post_comment(request): 'ratings_required': RATINGS_REQUIRED in option_list, 'rating_range': rating_range, 'rating_choices': rating_choices, - }, context_instance=RequestContext(request)) + }, context_instance=RequestContext(request, extra_context, context_processors)) elif 'post' in request.POST: # If the IP is banned, mail the admins, do NOT save the comment, and # serve up the "Thanks for posting" page as if the comment WAS posted. @@ -257,7 +258,7 @@ def post_comment(request): else: raise Http404, _("The comment form didn't provide either 'preview' or 'post'") -def post_free_comment(request): +def post_free_comment(request, extra_context=None, context_processors=None): """ Post a free comment (not requiring a log in) @@ -277,6 +278,7 @@ def post_free_comment(request): security hash (must be included in a posted form to succesfully post a comment). """ + if extra_context is None: extra_context = {} if not request.POST: raise Http404, _("Only POSTs are allowed") try: @@ -307,7 +309,7 @@ def post_free_comment(request): 'options': options, 'target': target, 'hash': security_hash, - }, context_instance=RequestContext(request)) + }, context_instance=RequestContext(request, extra_context, context_processors)) elif 'post' in request.POST: # If the IP is banned, mail the admins, do NOT save the comment, and # serve up the "Thanks for posting" page as if the comment WAS posted. @@ -321,7 +323,7 @@ def post_free_comment(request): else: raise Http404, _("The comment form didn't provide either 'preview' or 'post'") -def comment_was_posted(request): +def comment_was_posted(request, extra_context=None, context_processors=None): """ Display "comment was posted" success page @@ -330,6 +332,7 @@ def comment_was_posted(request): object The object the comment was posted on """ + if extra_context is None: extra_context = {} obj = None if 'c' in request.GET: content_type_id, object_id = request.GET['c'].split(':') @@ -338,4 +341,5 @@ def comment_was_posted(request): obj = content_type.get_object_for_this_type(pk=object_id) except ObjectDoesNotExist: pass - return render_to_response('comments/posted.html', {'object': obj}, context_instance=RequestContext(request)) + return render_to_response('comments/posted.html', {'object': obj}, + context_instance=RequestContext(request, extra_context, context_processors)) diff --git a/django/contrib/comments/views/karma.py b/django/contrib/comments/views/karma.py index c6ad301dee..7c0e284ae9 100644 --- a/django/contrib/comments/views/karma.py +++ b/django/contrib/comments/views/karma.py @@ -4,7 +4,7 @@ from django.template import RequestContext from django.contrib.comments.models import Comment, KarmaScore from django.utils.translation import ugettext as _ -def vote(request, comment_id, vote): +def vote(request, comment_id, vote, extra_context=None, context_processors=None): """ Rate a comment (+1 or -1) @@ -13,6 +13,7 @@ def vote(request, comment_id, vote): comment `comments.comments` object being rated """ + if extra_context is None: extra_context = {} rating = {'up': 1, 'down': -1}.get(vote, False) if not rating: raise Http404, "Invalid vote" @@ -27,4 +28,5 @@ def vote(request, comment_id, vote): KarmaScore.objects.vote(request.user.id, comment_id, rating) # Reload comment to ensure we have up to date karma count comment = Comment.objects.get(pk=comment_id) - return render_to_response('comments/karma_vote_accepted.html', {'comment': comment}, context_instance=RequestContext(request)) + return render_to_response('comments/karma_vote_accepted.html', {'comment': comment}, + context_instance=RequestContext(request, extra_context, context_processors)) diff --git a/django/contrib/comments/views/userflags.py b/django/contrib/comments/views/userflags.py index 76f14ef19c..91518dc5dd 100644 --- a/django/contrib/comments/views/userflags.py +++ b/django/contrib/comments/views/userflags.py @@ -6,7 +6,7 @@ from django.contrib.auth.decorators import login_required from django.http import HttpResponseRedirect from django.conf import settings -def flag(request, comment_id): +def flag(request, comment_id, extra_context=None, context_processors=None): """ Flags a comment. Confirmation on GET, action on POST. @@ -15,18 +15,22 @@ def flag(request, comment_id): comment the flagged `comments.comments` object """ + if extra_context is None: extra_context = {} comment = get_object_or_404(Comment,pk=comment_id, site__id__exact=settings.SITE_ID) if request.POST: UserFlag.objects.flag(comment, request.user) return HttpResponseRedirect('%sdone/' % request.path) - return render_to_response('comments/flag_verify.html', {'comment': comment}, context_instance=RequestContext(request)) + return render_to_response('comments/flag_verify.html', {'comment': comment}, + context_instance=RequestContext(request, extra_context, context_processors)) flag = login_required(flag) -def flag_done(request, comment_id): +def flag_done(request, comment_id, extra_context=None, context_processors=None): + if extra_context is None: extra_context = {} comment = get_object_or_404(Comment,pk=comment_id, site__id__exact=settings.SITE_ID) - return render_to_response('comments/flag_done.html', {'comment': comment}, context_instance=RequestContext(request)) + return render_to_response('comments/flag_done.html', {'comment': comment}, + context_instance=RequestContext(request, extra_context, context_processors)) -def delete(request, comment_id): +def delete(request, comment_id, extra_context=None, context_processors=None): """ Deletes a comment. Confirmation on GET, action on POST. @@ -35,6 +39,7 @@ def delete(request, comment_id): comment the flagged `comments.comments` object """ + if extra_context is None: extra_context = {} comment = get_object_or_404(Comment,pk=comment_id, site__id__exact=settings.SITE_ID) if not Comment.objects.user_is_moderator(request.user): raise Http404 @@ -46,9 +51,12 @@ def delete(request, comment_id): m = ModeratorDeletion(None, request.user.id, comment.id, None) m.save() return HttpResponseRedirect('%sdone/' % request.path) - return render_to_response('comments/delete_verify.html', {'comment': comment}, context_instance=RequestContext(request)) + return render_to_response('comments/delete_verify.html', {'comment': comment}, + context_instance=RequestContext(request, extra_context, context_processors)) delete = login_required(delete) -def delete_done(request, comment_id): +def delete_done(request, comment_id, extra_context=None, context_processors=None): + if extra_context is None: extra_context = {} comment = get_object_or_404(Comment,pk=comment_id, site__id__exact=settings.SITE_ID) - return render_to_response('comments/delete_done.html', {'comment': comment}, context_instance=RequestContext(request)) + return render_to_response('comments/delete_done.html', {'comment': comment}, + context_instance=RequestContext(request, extra_context, context_processors)) diff --git a/django/contrib/contenttypes/management.py b/django/contrib/contenttypes/management.py index cb52e0805e..49083d6d5c 100644 --- a/django/contrib/contenttypes/management.py +++ b/django/contrib/contenttypes/management.py @@ -1,34 +1,43 @@ -""" -Creates content types for all installed models. -""" - +from django.contrib.contenttypes.models import ContentType from django.dispatch import dispatcher from django.db.models import get_apps, get_models, signals from django.utils.encoding import smart_unicode -def create_contenttypes(app, created_models, verbosity=2): - from django.contrib.contenttypes.models import ContentType +def update_contenttypes(app, created_models, verbosity=2): + """ + Creates content types for models in the given app, removing any model + entries that no longer have a matching model class. + """ ContentType.objects.clear_cache() + content_types = list(ContentType.objects.filter(app_label=app.__name__.split('.')[-2])) app_models = get_models(app) if not app_models: return for klass in app_models: opts = klass._meta try: - ContentType.objects.get(app_label=opts.app_label, - model=opts.object_name.lower()) + ct = ContentType.objects.get(app_label=opts.app_label, + model=opts.object_name.lower()) + content_types.remove(ct) except ContentType.DoesNotExist: ct = ContentType(name=smart_unicode(opts.verbose_name_raw), app_label=opts.app_label, model=opts.object_name.lower()) ct.save() if verbosity >= 2: print "Adding content type '%s | %s'" % (ct.app_label, ct.model) + # The presence of any remaining content types means the supplied app has an + # undefined model and can safely be removed, which cascades to also remove + # related permissions. + for ct in content_types: + if verbosity >= 2: + print "Deleting stale content type '%s | %s'" % (ct.app_label, ct.model) + ct.delete() -def create_all_contenttypes(verbosity=2): +def update_all_contenttypes(verbosity=2): for app in get_apps(): - create_contenttypes(app, None, verbosity) + update_contenttypes(app, None, verbosity) -dispatcher.connect(create_contenttypes, signal=signals.post_syncdb) +dispatcher.connect(update_contenttypes, signal=signals.post_syncdb) if __name__ == "__main__": - create_all_contenttypes() + update_all_contenttypes() diff --git a/django/contrib/contenttypes/models.py b/django/contrib/contenttypes/models.py index cda47a18aa..1413586254 100644 --- a/django/contrib/contenttypes/models.py +++ b/django/contrib/contenttypes/models.py @@ -25,7 +25,7 @@ class ContentTypeManager(models.Manager): """ Clear out the content-type cache. This needs to happen during database flushes to prevent caching of "stale" content type IDs (see - django.contrib.contenttypes.management.create_contenttypes for where + django.contrib.contenttypes.management.update_contenttypes for where this gets called). """ global CONTENT_TYPE_CACHE diff --git a/django/contrib/csrf/middleware.py b/django/contrib/csrf/middleware.py index 93a9484ca6..1ef0e6cefd 100644 --- a/django/contrib/csrf/middleware.py +++ b/django/contrib/csrf/middleware.py @@ -40,7 +40,7 @@ class CsrfMiddleware(object): """ def process_request(self, request): - if request.POST: + if request.method == 'POST': try: session_id = request.COOKIES[settings.SESSION_COOKIE_NAME] except KeyError: diff --git a/django/contrib/databrowse/templates/databrowse/calendar_day.html b/django/contrib/databrowse/templates/databrowse/calendar_day.html index b0f57e1eae..bbb62cc814 100644 --- a/django/contrib/databrowse/templates/databrowse/calendar_day.html +++ b/django/contrib/databrowse/templates/databrowse/calendar_day.html @@ -10,7 +10,7 @@ <ul class="objectlist"> {% for object in object_list %} -<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li> +<li class="{% cycle 'odd' 'even' %}"><a href="{{ object.url }}">{{ object|escape }}</a></li> {% endfor %} </ul> diff --git a/django/contrib/databrowse/templates/databrowse/calendar_homepage.html b/django/contrib/databrowse/templates/databrowse/calendar_homepage.html index daf45dfdeb..85eb8af9eb 100644 --- a/django/contrib/databrowse/templates/databrowse/calendar_homepage.html +++ b/django/contrib/databrowse/templates/databrowse/calendar_homepage.html @@ -10,7 +10,7 @@ <ul class="objectlist"> {% for field in field_list %} -<li class="{% cycle odd,even %}"><a href="{{ field.name }}/">{{ model.verbose_name_plural|capfirst }} by {{ field.verbose_name }}</a></li> +<li class="{% cycle 'odd' 'even' %}"><a href="{{ field.name }}/">{{ model.verbose_name_plural|capfirst }} by {{ field.verbose_name }}</a></li> {% endfor %} </ul> diff --git a/django/contrib/databrowse/templates/databrowse/calendar_main.html b/django/contrib/databrowse/templates/databrowse/calendar_main.html index 18ee5bdc8b..b22a44d321 100644 --- a/django/contrib/databrowse/templates/databrowse/calendar_main.html +++ b/django/contrib/databrowse/templates/databrowse/calendar_main.html @@ -10,7 +10,7 @@ <ul class="objectlist"> {% for year in date_list %} -<li class="{% cycle odd,even %}"><a href="{{ year.year }}/">{{ year.year }}</a></li> +<li class="{% cycle 'odd' 'even' %}"><a href="{{ year.year }}/">{{ year.year }}</a></li> {% endfor %} </ul> diff --git a/django/contrib/databrowse/templates/databrowse/calendar_month.html b/django/contrib/databrowse/templates/databrowse/calendar_month.html index 67506f452f..70b7deb75a 100644 --- a/django/contrib/databrowse/templates/databrowse/calendar_month.html +++ b/django/contrib/databrowse/templates/databrowse/calendar_month.html @@ -10,7 +10,7 @@ <ul class="objectlist"> {% for object in object_list %} -<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li> +<li class="{% cycle 'odd' 'even' %}"><a href="{{ object.url }}">{{ object|escape }}</a></li> {% endfor %} </ul> diff --git a/django/contrib/databrowse/templates/databrowse/calendar_year.html b/django/contrib/databrowse/templates/databrowse/calendar_year.html index 729c2ddf3b..a6e6f53ba3 100644 --- a/django/contrib/databrowse/templates/databrowse/calendar_year.html +++ b/django/contrib/databrowse/templates/databrowse/calendar_year.html @@ -10,7 +10,7 @@ <ul class="objectlist"> {% for month in date_list %} -<li class="{% cycle odd,even %}"><a href="{{ month|date:"M"|lower }}/">{{ month|date:"F" }}</a></li> +<li class="{% cycle 'odd' 'even' %}"><a href="{{ month|date:"M"|lower }}/">{{ month|date:"F" }}</a></li> {% endfor %} </ul> diff --git a/django/contrib/databrowse/templates/databrowse/choice_detail.html b/django/contrib/databrowse/templates/databrowse/choice_detail.html index e6add55021..6cb73e73ec 100644 --- a/django/contrib/databrowse/templates/databrowse/choice_detail.html +++ b/django/contrib/databrowse/templates/databrowse/choice_detail.html @@ -10,7 +10,7 @@ <ul class="objectlist"> {% for object in object_list %} -<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li> +<li class="{% cycle 'odd' 'even' %}"><a href="{{ object.url }}">{{ object|escape }}</a></li> {% endfor %} </ul> diff --git a/django/contrib/databrowse/templates/databrowse/choice_list.html b/django/contrib/databrowse/templates/databrowse/choice_list.html index 07a1319459..95cd88b0bf 100644 --- a/django/contrib/databrowse/templates/databrowse/choice_list.html +++ b/django/contrib/databrowse/templates/databrowse/choice_list.html @@ -10,7 +10,7 @@ <ul class="objectlist"> {% for choice in field.choices %} -<li class="{% cycle odd,even %}"><a href="{{ choice.url }}">{{ choice.label|escape }}</a></li> +<li class="{% cycle 'odd' 'even' %}"><a href="{{ choice.url }}">{{ choice.label|escape }}</a></li> {% endfor %} </ul> diff --git a/django/contrib/databrowse/templates/databrowse/fieldchoice_detail.html b/django/contrib/databrowse/templates/databrowse/fieldchoice_detail.html index d1c8b877cb..7801f3f631 100644 --- a/django/contrib/databrowse/templates/databrowse/fieldchoice_detail.html +++ b/django/contrib/databrowse/templates/databrowse/fieldchoice_detail.html @@ -10,7 +10,7 @@ <ul class="objectlist"> {% for object in object_list %} -<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li> +<li class="{% cycle 'odd' 'even' %}"><a href="{{ object.url }}">{{ object|escape }}</a></li> {% endfor %} </ul> diff --git a/django/contrib/databrowse/templates/databrowse/fieldchoice_homepage.html b/django/contrib/databrowse/templates/databrowse/fieldchoice_homepage.html index 8760bd4ad1..3259824061 100644 --- a/django/contrib/databrowse/templates/databrowse/fieldchoice_homepage.html +++ b/django/contrib/databrowse/templates/databrowse/fieldchoice_homepage.html @@ -10,7 +10,7 @@ <ul class="objectlist"> {% for field in field_list %} -<li class="{% cycle odd,even %}"><a href="{{ field.name }}/">{{ model.verbose_name_plural|capfirst }} by {{ field.verbose_name }}</a></li> +<li class="{% cycle 'odd' 'even' %}"><a href="{{ field.name }}/">{{ model.verbose_name_plural|capfirst }} by {{ field.verbose_name }}</a></li> {% endfor %} </ul> diff --git a/django/contrib/databrowse/templates/databrowse/fieldchoice_list.html b/django/contrib/databrowse/templates/databrowse/fieldchoice_list.html index 9f41213a6f..71b906d3e7 100644 --- a/django/contrib/databrowse/templates/databrowse/fieldchoice_list.html +++ b/django/contrib/databrowse/templates/databrowse/fieldchoice_list.html @@ -10,7 +10,7 @@ <ul class="objectlist"> {% for object in object_list %} -<li class="{% cycle odd,even %}"><a href="{{ object|iriencode }}/">{{ object|escape }}</a></li> +<li class="{% cycle 'odd' 'even' %}"><a href="{{ object|iriencode }}/">{{ object|escape }}</a></li> {% endfor %} </ul> diff --git a/django/contrib/databrowse/templates/databrowse/homepage.html b/django/contrib/databrowse/templates/databrowse/homepage.html index 104a804253..718e577416 100644 --- a/django/contrib/databrowse/templates/databrowse/homepage.html +++ b/django/contrib/databrowse/templates/databrowse/homepage.html @@ -7,7 +7,7 @@ {% block content %} {% for model in model_list %} - <div class="modelgroup {% cycle even,odd %}"> + <div class="modelgroup {% cycle 'even' 'odd' %}"> <h2><a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a></h2> <p> {% for object in model.sample_objects %} diff --git a/django/contrib/databrowse/templates/databrowse/model_detail.html b/django/contrib/databrowse/templates/databrowse/model_detail.html index 2084b18ca7..b66bc093dd 100644 --- a/django/contrib/databrowse/templates/databrowse/model_detail.html +++ b/django/contrib/databrowse/templates/databrowse/model_detail.html @@ -12,7 +12,7 @@ <ul class="objectlist"> {% for object in model.objects %} - <li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li> + <li class="{% cycle 'odd' 'even' %}"><a href="{{ object.url }}">{{ object|escape }}</a></li> {% endfor %} </ul> diff --git a/django/contrib/databrowse/templates/databrowse/object_detail.html b/django/contrib/databrowse/templates/databrowse/object_detail.html index e9977743fd..7c1bd3e16d 100644 --- a/django/contrib/databrowse/templates/databrowse/object_detail.html +++ b/django/contrib/databrowse/templates/databrowse/object_detail.html @@ -10,7 +10,7 @@ <table class="objectinfo"> {% for field in object.fields %} -<tr class="{% cycle odd,even %}"> +<tr class="{% cycle 'odd' 'even' %}"> <th>{{ field.field.verbose_name|capfirst }}</th> <td> {% if field.urls %} @@ -29,7 +29,7 @@ {% if related_object.object_list %} <ul class="objectlist"> {% for object in related_object.object_list %} - <li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li> + <li class="{% cycle 'odd' 'even' %}"><a href="{{ object.url }}">{{ object|escape }}</a></li> {% endfor %} </ul> {% else %} diff --git a/django/contrib/formtools/preview.py b/django/contrib/formtools/preview.py index dcb58e85d8..2e4fb92cda 100644 --- a/django/contrib/formtools/preview.py +++ b/django/contrib/formtools/preview.py @@ -1,47 +1,5 @@ """ 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, cleaned_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 diff --git a/django/contrib/localflavor/ar/__init__.py b/django/contrib/localflavor/ar/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/django/contrib/localflavor/ar/__init__.py diff --git a/django/contrib/localflavor/ar/ar_provinces.py b/django/contrib/localflavor/ar/ar_provinces.py new file mode 100644 index 0000000000..a0efd4ba33 --- /dev/null +++ b/django/contrib/localflavor/ar/ar_provinces.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +""" +A list of Argentinean provinces and autonomous cities as `choices` in a +formfield. From +http://www.argentina.gov.ar/argentina/portal/paginas.dhtml?pagina=425 + +This exists in this standalone file so that it's only imported into memory +when explicitly needed. +""" + +PROVINCE_CHOICES = ( + ('B', u'Buenos Aires'), + ('K', u'Catamarca'), + ('H', u'Chaco'), + ('U', u'Chubut'), + ('C', u'Ciudad Autónoma de Buenos Aires'), + ('X', u'Córdoba'), + ('W', u'Corrientes'), + ('E', u'Entre Ríos'), + ('P', u'Formosa'), + ('Y', u'Jujuy'), + ('L', u'La Pampa'), + ('F', u'La Rioja'), + ('M', u'Mendoza'), + ('N', u'Misiones'), + ('Q', u'Neuquén'), + ('R', u'Río Negro'), + ('A', u'Salta'), + ('J', u'San Juan'), + ('D', u'San Luis'), + ('Z', u'Santa Cruz'), + ('S', u'Santa Fe'), + ('G', u'Santiago del Estero'), + ('V', u'Tierra del Fuego, Antártida e Islas del Atlántico Sur'), + ('T', u'Tucumán'), +) diff --git a/django/contrib/localflavor/ar/forms.py b/django/contrib/localflavor/ar/forms.py new file mode 100644 index 0000000000..6d86e4e676 --- /dev/null +++ b/django/contrib/localflavor/ar/forms.py @@ -0,0 +1,105 @@ +# -*- coding: utf-8 -*- +""" +AR-specific Form helpers. +""" + +from django.newforms import ValidationError +from django.newforms.fields import RegexField, CharField, Select, EMPTY_VALUES +from django.utils.encoding import smart_unicode +from django.utils.translation import ugettext +import re + +class ARProvinceSelect(Select): + """ + A Select widget that uses a list of Argentinean provinces/autonomous cities + as its choices. + """ + def __init__(self, attrs=None): + from ar_provinces import PROVINCE_CHOICES + super(ARProvinceSelect, self).__init__(attrs, choices=PROVINCE_CHOICES) + +class ARPostalCodeField(RegexField): + """ + A field that accepts a `classic NNNN Postal Code or a CPA. + + See http://www.correoargentino.com.ar/consulta_cpa/home.php + """ + def __init__(self, *args, **kwargs): + super(ARPostalCodeField, self).__init__(r'^\d{4}$|^[A-HJ-NP-Za-hj-np-z]\d{4}\D{3}$', + min_length=4, max_length=8, + error_message=ugettext("Enter a postal code in the format NNNN or ANNNNAAA."), + *args, **kwargs) + + def clean(self, value): + value = super(ARPostalCodeField, self).clean(value) + if value in EMPTY_VALUES: + return u'' + if len(value) not in (4, 8): + raise ValidationError(ugettext("Enter a postal code in the format NNNN or ANNNNAAA.")) + if len(value) == 8: + return u'%s%s%s' % (value[0].upper(), value[1:5], value[5:].upper()) + return value + +class ARDNIField(CharField): + """ + A field that validates `Documento Nacional de Identidad (DNI) numbers. + """ + def __init__(self, *args, **kwargs): + super(ARDNIField, self).__init__(max_length=10, min_length=7, *args, + **kwargs) + + def clean(self, value): + """ + Value can be a string either in the [X]X.XXX.XXX or [X]XXXXXXX formats. + """ + value = super(ARDNIField, self).clean(value) + if value in EMPTY_VALUES: + return u'' + if not value.isdigit(): + value = value.replace('.', '') + if not value.isdigit(): + raise ValidationError(ugettext("This field requires only numbers.")) + if len(value) not in (7, 8): + raise ValidationError( + ugettext("This field requires 7 or 8 digits.")) + + return value + +class ARCUITField(RegexField): + """ + This field validates a CUIT (Cdigo nico de Identificacin Tributaria). A + CUIT is of the form XX-XXXXXXXX-V. The last digit is a check digit. + """ + def __init__(self, *args, **kwargs): + super(ARCUITField, self).__init__(r'^\d{2}-?\d{8}-?\d$', + error_message=ugettext('Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.'), + *args, **kwargs) + + def clean(self, value): + """ + Value can be either a string in the format XX-XXXXXXXX-X or an + 11-digit number. + """ + value = super(ARCUITField, self).clean(value) + if value in EMPTY_VALUES: + return u'' + value, cd = self._canon(value) + if self._calc_cd(value) != cd: + raise ValidationError(ugettext("Invalid CUIT.")) + return self._format(value, cd) + + def _canon(self, cuit): + cuit = cuit.replace('-', '') + return cuit[:-1], cuit[-1] + + def _calc_cd(self, cuit): + mults = (5, 4, 3, 2, 7, 6, 5, 4, 3, 2) + tmp = sum([m * int(cuit[idx]) for idx, m in enumerate(mults)]) + return str(11 - tmp % 11) + + def _format(self, cuit, check_digit=None): + if check_digit == None: + check_digit = cuit[-1] + cuit = cuit[:-1] + return u'%s-%s-%s' % (cuit[:2], cuit[2:], check_digit) + diff --git a/django/contrib/localflavor/br/forms.py b/django/contrib/localflavor/br/forms.py index c7082c0f9e..58bf795292 100644 --- a/django/contrib/localflavor/br/forms.py +++ b/django/contrib/localflavor/br/forms.py @@ -6,16 +6,21 @@ BR-specific Form helpers from django.newforms import ValidationError from django.newforms.fields import Field, RegexField, CharField, Select, EMPTY_VALUES from django.utils.encoding import smart_unicode -from django.utils.translation import ugettext +from django.utils.translation import ugettext as _ import re +try: + set +except NameError: + from sets import Set as set # For Python 2.3 + phone_digits_re = re.compile(r'^(\d{2})[-\.]?(\d{4})[-\.]?(\d{4})$') class BRZipCodeField(RegexField): def __init__(self, *args, **kwargs): super(BRZipCodeField, self).__init__(r'^\d{5}-\d{3}$', max_length=None, min_length=None, - error_message=ugettext('Enter a zip code in the format XXXXX-XXX.'), + error_message=_('Enter a zip code in the format XXXXX-XXX.'), *args, **kwargs) class BRPhoneNumberField(Field): @@ -27,7 +32,7 @@ class BRPhoneNumberField(Field): m = phone_digits_re.search(value) if m: return u'%s-%s-%s' % (m.group(1), m.group(2), m.group(3)) - raise ValidationError(ugettext('Phone numbers must be in XX-XXXX-XXXX format.')) + raise ValidationError(_('Phone numbers must be in XX-XXXX-XXXX format.')) class BRStateSelect(Select): """ @@ -38,6 +43,32 @@ class BRStateSelect(Select): from br_states import STATE_CHOICES super(BRStateSelect, self).__init__(attrs, choices=STATE_CHOICES) +class BRStateChoiceField(Field): + """ + A choice field that uses a list of Brazilian states as its choices. + """ + widget = Select + + def __init__(self, required=True, widget=None, label=None, + initial=None, help_text=None): + super(BRStateChoiceField, self).__init__(required, widget, label, + initial, help_text) + from br_states import STATE_CHOICES + self.widget.choices = STATE_CHOICES + + def clean(self, value): + value = super(BRStateChoiceField, self).clean(value) + if value in EMPTY_VALUES: + value = u'' + value = smart_unicode(value) + if value == u'': + return value + valid_values = set([smart_unicode(k) for k, v in self.widget.choices]) + if value not in valid_values: + raise ValidationError(_(u'Select a valid brazilian state.' + u' That state is not one' + u' of the available states.')) + return value def DV_maker(v): if v >= 2: @@ -69,9 +100,9 @@ class BRCPFField(CharField): try: int(value) except ValueError: - raise ValidationError(ugettext("This field requires only numbers.")) + raise ValidationError(_("This field requires only numbers.")) if len(value) != 11: - raise ValidationError(ugettext("This field requires at most 11 digits or 14 characters.")) + raise ValidationError(_("This field requires at most 11 digits or 14 characters.")) orig_dv = value[-2:] new_1dv = sum([i * int(value[idx]) for idx, i in enumerate(range(10, 1, -1))]) @@ -81,7 +112,7 @@ class BRCPFField(CharField): new_2dv = DV_maker(new_2dv % 11) value = value[:-1] + str(new_2dv) if value[-2:] != orig_dv: - raise ValidationError(ugettext("Invalid CPF number.")) + raise ValidationError(_("Invalid CPF number.")) return orig_value @@ -103,7 +134,7 @@ class BRCNPJField(Field): raise ValidationError("This field requires only numbers.") if len(value) != 14: raise ValidationError( - ugettext("This field requires at least 14 digits")) + _("This field requires at least 14 digits")) orig_dv = value[-2:] new_1dv = sum([i * int(value[idx]) for idx, i in enumerate(range(5, 1, -1) + range(9, 1, -1))]) @@ -113,7 +144,7 @@ class BRCNPJField(Field): new_2dv = DV_maker(new_2dv % 11) value = value[:-1] + str(new_2dv) if value[-2:] != orig_dv: - raise ValidationError(ugettext("Invalid CNPJ number.")) + raise ValidationError(_("Invalid CNPJ number.")) return orig_value diff --git a/django/contrib/localflavor/ca/__init__.py b/django/contrib/localflavor/ca/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/django/contrib/localflavor/ca/__init__.py diff --git a/django/contrib/localflavor/ca/ca_provinces.py b/django/contrib/localflavor/ca/ca_provinces.py new file mode 100644 index 0000000000..072159ad57 --- /dev/null +++ b/django/contrib/localflavor/ca/ca_provinces.py @@ -0,0 +1,57 @@ +""" +An alphabetical list of provinces and territories for use as `choices` +in a formfield., and a mapping of province misspellings/abbreviations to +normalized abbreviations + +Source: http://www.canada.gc.ca/othergov/prov_e.html + +This exists in this standalone file so that it's only imported into memory +when explicitly needed. +""" + +PROVINCE_CHOICES = ( + ('AB', 'Alberta'), + ('BC', 'British Columbia'), + ('MB', 'Manitoba'), + ('NB', 'New Brunswick'), + ('NF', 'Newfoundland and Labrador'), + ('NT', 'Northwest Territories'), + ('NS', 'Nova Scotia'), + ('NU', 'Nunavut'), + ('ON', 'Ontario'), + ('PE', 'Prince Edward Island'), + ('QC', 'Quebec'), + ('SK', 'Saskatchewan'), + ('YK', 'Yukon') +) + +PROVINCES_NORMALIZED = { + 'ab': 'AB', + 'alberta': 'AB', + 'bc': 'BC', + 'b.c.': 'BC', + 'british columbia': 'BC', + 'mb': 'MB', + 'manitoba': 'MB', + 'nf': 'NF', + 'newfoundland': 'NF', + 'newfoundland and labrador': 'NF', + 'nt': 'NT', + 'northwest territories': 'NT', + 'ns': 'NS', + 'nova scotia': 'NS', + 'nu': 'NU', + 'nunavut': 'NU', + 'on': 'ON', + 'ontario': 'ON', + 'pe': 'PE', + 'pei': 'PE', + 'p.e.i.': 'PE', + 'prince edward island': 'PE', + 'qc': 'QC', + 'quebec': 'QC', + 'sk': 'SK', + 'saskatchewan': 'SK', + 'yk': 'YK', + 'yukon': 'YK', +}
\ No newline at end of file diff --git a/django/contrib/localflavor/ca/forms.py b/django/contrib/localflavor/ca/forms.py new file mode 100644 index 0000000000..98f65a5c6c --- /dev/null +++ b/django/contrib/localflavor/ca/forms.py @@ -0,0 +1,112 @@ +""" +Canada-specific Form helpers +""" + +from django.newforms import ValidationError +from django.newforms.fields import Field, RegexField, Select, EMPTY_VALUES +from django.newforms.util import smart_unicode +from django.utils.translation import gettext, ugettext +import re + +phone_digits_re = re.compile(r'^(?:1-?)?(\d{3})[-\.]?(\d{3})[-\.]?(\d{4})$') +sin_re = re.compile(r"^(\d{3})-(\d{3})-(\d{3})$") + +class CAPostalCodeField(RegexField): + """Canadian postal code field.""" + def __init__(self, *args, **kwargs): + super(CAPostalCodeField, self).__init__(r'^[ABCEGHJKLMNPRSTVXYZ]\d[A-Z] \d[A-Z]\d$', + max_length=None, min_length=None, + error_message=gettext(u'Enter a postal code in the format XXX XXX.'), + *args, **kwargs) + +class CAPhoneNumberField(Field): + """Canadian phone number field.""" + def clean(self, value): + """Validate a phone number. + """ + super(CAPhoneNumberField, self).clean(value) + if value in EMPTY_VALUES: + return u'' + value = re.sub('(\(|\)|\s+)', '', smart_unicode(value)) + m = phone_digits_re.search(value) + if m: + return u'%s-%s-%s' % (m.group(1), m.group(2), m.group(3)) + raise ValidationError(u'Phone numbers must be in XXX-XXX-XXXX format.') + +class CAProvinceField(Field): + """ + A form field that validates its input is a Canadian province name or abbreviation. + It normalizes the input to the standard two-leter postal service + abbreviation for the given province. + """ + def clean(self, value): + from ca_provinces import PROVINCES_NORMALIZED + super(CAProvinceField, self).clean(value) + if value in EMPTY_VALUES: + return u'' + try: + value = value.strip().lower() + except AttributeError: + pass + else: + try: + return PROVINCES_NORMALIZED[value.strip().lower()].decode('ascii') + except KeyError: + pass + raise ValidationError(u'Enter a Canadian province or territory.') + +class CAProvinceSelect(Select): + """ + A Select widget that uses a list of Canadian provinces and + territories as its choices. + """ + def __init__(self, attrs=None): + from ca_provinces import PROVINCE_CHOICES # relative import + super(CAProvinceSelect, self).__init__(attrs, choices=PROVINCE_CHOICES) + +class CASocialInsuranceNumberField(Field): + """ + A Canadian Social Insurance Number (SIN). + + Checks the following rules to determine whether the number is valid: + + * Conforms to the XXX-XXX-XXXX format. + * Passes the check digit process "Luhn Algorithm" + See: http://en.wikipedia.org/wiki/Social_Insurance_Number + """ + def clean(self, value): + super(CASocialInsuranceNumberField, self).clean(value) + if value in EMPTY_VALUES: + return u'' + msg = ugettext('Enter a valid Canadian Social Insurance number in XXX-XXX-XXXX format.') + match = re.match(sin_re, value) + if not match: + raise ValidationError(msg) + + number = u'%s-%s-%s' % (match.group(1), match.group(2), match.group(3)) + check_number = u'%s%s%s' % (match.group(1), match.group(2), match.group(3)) + if not self.luhn_checksum_is_valid(check_number): + raise ValidationError(msg) + return number + + def luhn_checksum_is_valid(self, number): + """ + Checks to make sure that the SIN passes a luhn mod-10 checksum + See: http://en.wikipedia.org/wiki/Luhn_algorithm + """ + + sum = 0 + num_digits = len(number) + oddeven = num_digits & 1 + + for count in range(0, num_digits): + digit = int(number[count]) + + if not (( count & 1 ) ^ oddeven ): + digit = digit * 2 + if digit > 9: + digit = digit - 9 + + sum = sum + digit + + return ( (sum % 10) == 0 )
\ No newline at end of file diff --git a/django/contrib/localflavor/generic/__init__.py b/django/contrib/localflavor/generic/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/django/contrib/localflavor/generic/__init__.py diff --git a/django/contrib/localflavor/generic/forms.py b/django/contrib/localflavor/generic/forms.py new file mode 100644 index 0000000000..a6d813723c --- /dev/null +++ b/django/contrib/localflavor/generic/forms.py @@ -0,0 +1,38 @@ +from django import newforms as forms
+
+DEFAULT_DATE_INPUT_FORMATS = (
+ '%Y-%m-%d', '%d/%m/%Y', '%d/%m/%y', # '2006-10-25', '25/10/2006', '25/10/06'
+ '%b %d %Y', '%b %d, %Y', # 'Oct 25 2006', 'Oct 25, 2006'
+ '%d %b %Y', '%d %b, %Y', # '25 Oct 2006', '25 Oct, 2006'
+ '%B %d %Y', '%B %d, %Y', # 'October 25 2006', 'October 25, 2006'
+ '%d %B %Y', '%d %B, %Y', # '25 October 2006', '25 October, 2006'
+)
+
+DEFAULT_DATETIME_INPUT_FORMATS = (
+ '%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59'
+ '%Y-%m-%d %H:%M', # '2006-10-25 14:30'
+ '%Y-%m-%d', # '2006-10-25'
+ '%d/%m/%Y %H:%M:%S', # '25/10/2006 14:30:59'
+ '%d/%m/%Y %H:%M', # '25/10/2006 14:30'
+ '%d/%m/%Y', # '25/10/2006'
+ '%d/%m/%y %H:%M:%S', # '25/10/06 14:30:59'
+ '%d/%m/%y %H:%M', # '25/10/06 14:30'
+ '%d/%m/%y', # '25/10/06'
+)
+
+class DateField(forms.DateField):
+ """
+ A date input field which uses non-US date input formats by default.
+ """
+ def __init__(self, input_formats=None, *args, **kwargs):
+ input_formats = input_formats or DEFAULT_DATE_INPUT_FORMATS
+ super(DateField, self).__init__(input_formats=input_formats, *args, **kwargs)
+
+class DateTimeField(forms.DateTimeField):
+ """
+ A date and time input field which uses non-US date and time input formats
+ by default.
+ """
+ def __init__(self, input_formats=None, *args, **kwargs):
+ input_formats = input_formats or DEFAULT_DATETIME_INPUT_FORMATS
+ super(DateTimeField, self).__init__(input_formats=input_formats, *args, **kwargs)
diff --git a/django/contrib/localflavor/it/it_province.py b/django/contrib/localflavor/it/it_province.py index 669ecd7f95..db041d719e 100644 --- a/django/contrib/localflavor/it/it_province.py +++ b/django/contrib/localflavor/it/it_province.py @@ -45,7 +45,7 @@ PROVINCE_CHOICES = ( ('IM', 'Imperia'), ('IS', 'Isernia'), ('SP', 'La Spezia'), - ('AQ', u'L’Acquila'), + ('AQ', u'L’Aquila'), ('LT', 'Latina'), ('LE', 'Lecce'), ('LC', 'Lecco'), diff --git a/django/contrib/localflavor/nl/__init__.py b/django/contrib/localflavor/nl/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/django/contrib/localflavor/nl/__init__.py diff --git a/django/contrib/localflavor/nl/forms.py b/django/contrib/localflavor/nl/forms.py new file mode 100644 index 0000000000..e202ab0595 --- /dev/null +++ b/django/contrib/localflavor/nl/forms.py @@ -0,0 +1,92 @@ +""" +NL-specific Form helpers +""" + +import re + +from django.newforms import ValidationError +from django.newforms.fields import Field, Select, EMPTY_VALUES +from django.utils.translation import ugettext as _ +from django.utils.encoding import smart_unicode + +pc_re = re.compile('^\d{4}[A-Z]{2}$') +sofi_re = re.compile('^\d{9}$') +numeric_re = re.compile('^\d+$') + +class NLZipCodeField(Field): + """ + A Dutch postal code field. + """ + def clean(self, value): + super(NLZipCodeField, self).clean(value) + if value in EMPTY_VALUES: + return u'' + + msg = _('Enter a valid postal code') + value = value.strip().upper().replace(' ', '') + if not pc_re.search(value): + raise ValidationError(msg) + + if int(value[:4]) < 1000: + raise ValidationError(msg) + + return u'%s %s' % (value[:4], value[4:]) + +class NLProvinceSelect(Select): + """ + A Select widget that uses a list of provinces of the Netherlands as its + choices. + """ + def __init__(self, attrs=None): + from nl_provinces import PROVINCE_CHOICES + super(NLProvinceSelect, self).__init__(attrs, choices=PROVINCE_CHOICES) + +class NLPhoneNumberField(Field): + """ + A Dutch telephone number field. + """ + def clean(self, value): + super(NLPhoneNumberField, self).clean(value) + if value in EMPTY_VALUES: + return u'' + + msg = _('Enter a valid phone number') + phone_nr = re.sub('[\-\s\(\)]', '', smart_unicode(value)) + + if len(phone_nr) == 10 and numeric_re.search(phone_nr): + return value + + if phone_nr[:3] == '+31' and len(phone_nr) == 12 and \ + numeric_re.search(phone_nr[3:]): + return value + + raise ValidationError(msg) + +class NLSoFiNumberField(Field): + """ + A Dutch social security number (SoFi/BSN) field. + + http://nl.wikipedia.org/wiki/Sofinummer + """ + def clean(self, value): + super(NLSoFiNumberField, self).clean(value) + if value in EMPTY_VALUES: + return u'' + + msg = _('Enter a valid SoFi number') + + if not sofi_re.search(value): + raise ValidationError(msg) + + if int(value) == 0: + raise ValidationError(msg) + + checksum = 0 + for i in range(9, 1, -1): + checksum += int(value[9-i]) * i + checksum -= int(value[-1]) + + if checksum % 11 != 0: + raise ValidationError(msg) + + return value diff --git a/django/contrib/localflavor/nl/nl_provinces.py b/django/contrib/localflavor/nl/nl_provinces.py new file mode 100644 index 0000000000..8964adfac0 --- /dev/null +++ b/django/contrib/localflavor/nl/nl_provinces.py @@ -0,0 +1,16 @@ +from django.utils.translation import ugettext_lazy as _ + +PROVINCE_CHOICES = ( + ('DR', _('Drente')), + ('FL', _('Flevoland')), + ('FR', _('Friesland')), + ('GL', _('Gelderland')), + ('GR', _('Groningen')), + ('LB', _('Limburg')), + ('NB', _('Noord-Brabant')), + ('NH', _('Noord-Holland')), + ('OV', _('Overijssel')), + ('UT', _('Utrecht')), + ('ZE', _('Zeeland')), + ('ZH', _('Zuid-Holland')), +) diff --git a/django/contrib/localflavor/pe/__init__.py b/django/contrib/localflavor/pe/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/django/contrib/localflavor/pe/__init__.py diff --git a/django/contrib/localflavor/pe/forms.py b/django/contrib/localflavor/pe/forms.py new file mode 100644 index 0000000000..b1ae215417 --- /dev/null +++ b/django/contrib/localflavor/pe/forms.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +""" +PE-specific Form helpers. +""" + +from django.newforms import ValidationError +from django.newforms.fields import RegexField, CharField, Select, EMPTY_VALUES +from django.utils.translation import ugettext + +class PEDepartmentSelect(Select): + """ + A Select widget that uses a list of Peruvian Departments as its choices. + """ + def __init__(self, attrs=None): + from pe_department import DEPARTMENT_CHOICES + super(PEDepartmentSelect, self).__init__(attrs, choices=DEPARTMENT_CHOICES) + +class PEDNIField(CharField): + """ + A field that validates `Documento Nacional de IdentidadŽ (DNI) numbers. + """ + def __init__(self, *args, **kwargs): + super(PEDNIField, self).__init__(max_length=8, min_length=8, *args, + **kwargs) + + def clean(self, value): + """ + Value must be a string in the XXXXXXXX formats. + """ + value = super(PEDNIField, self).clean(value) + if value in EMPTY_VALUES: + return u'' + if not value.isdigit(): + raise ValidationError(ugettext("This field requires only numbers.")) + if len(value) != 8: + raise ValidationError(ugettext("This field requires 8 digits.")) + + return value + +class PERUCField(RegexField): + """ + This field validates a RUC (Registro Unico de Contribuyentes). A RUC is of + the form XXXXXXXXXXX. + """ + def __init__(self, *args, **kwargs): + super(PERUCField, self).__init__(max_length=11, min_length=11, *args, + **kwargs) + + def clean(self, value): + """ + Value must be an 11-digit number. + """ + value = super(PERUCField, self).clean(value) + if value in EMPTY_VALUES: + return u'' + if not value.isdigit(): + raise ValidationError(ugettext("This field requires only numbers.")) + if len(value) != 11: + raise ValidationError(ugettext("This field requires 11 digits.")) + return value + diff --git a/django/contrib/localflavor/pe/pe_department.py b/django/contrib/localflavor/pe/pe_department.py new file mode 100644 index 0000000000..d7fa65f9cb --- /dev/null +++ b/django/contrib/localflavor/pe/pe_department.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +""" +A list of Peru departaments as `choices` in a +formfield. + +This exists in this standalone file so that it's only imported into memory +when explicitly needed. +""" + +DEPARTMENT_CHOICES = ( + ('AMA', u'Amazonas'), + ('ANC', u'Ancash'), + ('APU', u'Apurímac'), + ('ARE', u'Arequipa'), + ('AYA', u'Ayacucho'), + ('CAJ', u'Cajamarca'), + ('CUS', u'Cusco'), + ('HUV', u'Huancavelica'), + ('HUC', u'Huánuco'), + ('ICA', u'Ica'), + ('JUN', u'Junín'), + ('LAL', u'La Libertad'), + ('LAM', u'Lambayeque'), + ('LIM', u'Lima'), + ('LOR', u'Loreto'), + ('MDD', u'Madre de Dios'), + ('MOQ', u'Moquegua'), + ('PAS', u'Pasco'), + ('PIU', u'Piura'), + ('PUN', u'Puno'), + ('SAM', u'San Martín'), + ('TAC', u'Tacna'), + ('TUM', u'Tumbes'), + ('UCA', u'Ucayali'), +) diff --git a/django/contrib/sessions/backends/__init__.py b/django/contrib/sessions/backends/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/django/contrib/sessions/backends/__init__.py diff --git a/django/contrib/sessions/backends/base.py b/django/contrib/sessions/backends/base.py new file mode 100644 index 0000000000..e6be0482de --- /dev/null +++ b/django/contrib/sessions/backends/base.py @@ -0,0 +1,146 @@ +import base64 +import md5 +import os +import random +import sys +import time +from django.conf import settings +from django.core.exceptions import SuspiciousOperation + +try: + import cPickle as pickle +except ImportError: + import pickle + +class SessionBase(object): + """ + Base class for all Session classes. + """ + TEST_COOKIE_NAME = 'testcookie' + TEST_COOKIE_VALUE = 'worked' + + def __init__(self, session_key=None): + self._session_key = session_key + self.accessed = False + self.modified = False + + def __contains__(self, key): + return key in self._session + + def __getitem__(self, key): + return self._session[key] + + def __setitem__(self, key, value): + self._session[key] = value + self.modified = True + + def __delitem__(self, key): + del self._session[key] + self.modified = True + + def keys(self): + return self._session.keys() + + def items(self): + return self._session.items() + + def get(self, key, default=None): + return self._session.get(key, default) + + def pop(self, key, *args): + return self._session.pop(key, *args) + + def set_test_cookie(self): + self[self.TEST_COOKIE_NAME] = self.TEST_COOKIE_VALUE + + def test_cookie_worked(self): + return self.get(self.TEST_COOKIE_NAME) == self.TEST_COOKIE_VALUE + + def delete_test_cookie(self): + del self[self.TEST_COOKIE_NAME] + + def encode(self, session_dict): + "Returns the given session dictionary pickled and encoded as a string." + pickled = pickle.dumps(session_dict, pickle.HIGHEST_PROTOCOL) + pickled_md5 = md5.new(pickled + settings.SECRET_KEY).hexdigest() + return base64.encodestring(pickled + pickled_md5) + + def decode(self, session_data): + encoded_data = base64.decodestring(session_data) + pickled, tamper_check = encoded_data[:-32], encoded_data[-32:] + if md5.new(pickled + settings.SECRET_KEY).hexdigest() != tamper_check: + raise SuspiciousOperation("User tampered with session cookie.") + try: + return pickle.loads(pickled) + # Unpickling can cause a variety of exceptions. If something happens, + # just return an empty dictionary (an empty session). + except: + return {} + + def _get_new_session_key(self): + "Returns session key that isn't being used." + # The random module is seeded when this Apache child is created. + # Use settings.SECRET_KEY as added salt. + try: + pid = os.getpid() + except AttributeError: + # No getpid() in Jython, for example + pid = 1 + while 1: + session_key = md5.new("%s%s%s%s" % (random.randint(0, sys.maxint - 1), + pid, time.time(), settings.SECRET_KEY)).hexdigest() + if not self.exists(session_key): + break + return session_key + + def _get_session_key(self): + if self._session_key: + return self._session_key + else: + self._session_key = self._get_new_session_key() + return self._session_key + + def _set_session_key(self, session_key): + self._session_key = session_key + + session_key = property(_get_session_key, _set_session_key) + + def _get_session(self): + # Lazily loads session from storage. + self.accessed = True + try: + return self._session_cache + except AttributeError: + if self._session_key is None: + self._session_cache = {} + else: + self._session_cache = self.load() + return self._session_cache + + _session = property(_get_session) + + # Methods that child classes must implement. + + def exists(self, session_key): + """ + Returns True if the given session_key already exists. + """ + raise NotImplementedError + + def save(self): + """ + Saves the session data. + """ + raise NotImplementedError + + def delete(self, session_key): + """ + Clears out the session data under this key. + """ + raise NotImplementedError + + def load(self): + """ + Loads the session data and returns a dictionary. + """ + raise NotImplementedError diff --git a/django/contrib/sessions/backends/cache.py b/django/contrib/sessions/backends/cache.py new file mode 100644 index 0000000000..c3e641e691 --- /dev/null +++ b/django/contrib/sessions/backends/cache.py @@ -0,0 +1,26 @@ +from django.conf import settings +from django.contrib.sessions.backends.base import SessionBase +from django.core.cache import cache + +class SessionStore(SessionBase): + """ + A cache-based session store. + """ + def __init__(self, session_key=None): + self._cache = cache + super(SessionStore, self).__init__(session_key) + + def load(self): + session_data = self._cache.get(self.session_key) + return session_data or {} + + def save(self): + self._cache.set(self.session_key, self._session, settings.SESSION_COOKIE_AGE) + + def exists(self, session_key): + if self._cache.get(session_key): + return True + return False + + def delete(self, session_key): + self._cache.delete(session_key)
\ No newline at end of file diff --git a/django/contrib/sessions/backends/db.py b/django/contrib/sessions/backends/db.py new file mode 100644 index 0000000000..d1496d63bf --- /dev/null +++ b/django/contrib/sessions/backends/db.py @@ -0,0 +1,49 @@ +from django.conf import settings +from django.contrib.sessions.models import Session +from django.contrib.sessions.backends.base import SessionBase +from django.core.exceptions import SuspiciousOperation +import datetime + +class SessionStore(SessionBase): + """ + Implements database session store + """ + def __init__(self, session_key=None): + super(SessionStore, self).__init__(session_key) + + def load(self): + try: + s = Session.objects.get( + session_key = self.session_key, + expire_date__gt=datetime.datetime.now() + ) + return self.decode(s.session_data) + except (Session.DoesNotExist, SuspiciousOperation): + + # Create a new session_key for extra security. + self.session_key = self._get_new_session_key() + self._session_cache = {} + + # Save immediately to minimize collision + self.save() + return {} + + def exists(self, session_key): + try: + Session.objects.get(session_key=session_key) + except Session.DoesNotExist: + return False + return True + + def save(self): + Session.objects.create( + session_key = self.session_key, + session_data = self.encode(self._session), + expire_date = datetime.datetime.now() + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE) + ) + + def delete(self, session_key): + try: + Session.objects.get(session_key=session_key).delete() + except Session.DoesNotExist: + pass
\ No newline at end of file diff --git a/django/contrib/sessions/backends/file.py b/django/contrib/sessions/backends/file.py new file mode 100644 index 0000000000..221db5cc60 --- /dev/null +++ b/django/contrib/sessions/backends/file.py @@ -0,0 +1,68 @@ +import os +from django.conf import settings +from django.contrib.sessions.backends.base import SessionBase +from django.core.exceptions import SuspiciousOperation + +class SessionStore(SessionBase): + """ + Implements a file based session store. + """ + def __init__(self, session_key=None): + self.storage_path = settings.SESSION_FILE_PATH + self.file_prefix = settings.SESSION_COOKIE_NAME + super(SessionStore, self).__init__(session_key) + + def _key_to_file(self, session_key=None): + """ + Get the file associated with this session key. + """ + if session_key is None: + session_key = self.session_key + + # Make sure we're not vulnerable to directory traversal. Session keys + # should always be md5s, so they should never contain directory components. + if os.path.sep in session_key: + raise SuspiciousOperation("Invalid characters (directory components) in session key") + + return os.path.join(self.storage_path, self.file_prefix + session_key) + + def load(self): + session_data = {} + try: + session_file = open(self._key_to_file(), "rb") + try: + try: + session_data = self.decode(session_file.read()) + except(EOFError, SuspiciousOperation): + self._session_key = self._get_new_session_key() + self._session_cache = {} + self.save() + finally: + session_file.close() + except(IOError): + pass + return session_data + + def save(self): + try: + f = open(self._key_to_file(self.session_key), "wb") + try: + f.write(self.encode(self._session)) + finally: + f.close() + except(IOError, EOFError): + pass + + def exists(self, session_key): + if os.path.exists(self._key_to_file(session_key)): + return True + return False + + def delete(self, session_key): + try: + os.unlink(self._key_to_file(session_key)) + except OSError: + pass + + def clean(self): + pass diff --git a/django/contrib/sessions/middleware.py b/django/contrib/sessions/middleware.py index 2531c8e244..4c3c5acc43 100644 --- a/django/contrib/sessions/middleware.py +++ b/django/contrib/sessions/middleware.py @@ -1,6 +1,4 @@ from django.conf import settings -from django.contrib.sessions.models import Session -from django.core.exceptions import SuspiciousOperation from django.utils.cache import patch_vary_headers from email.Utils import formatdate import datetime @@ -9,73 +7,11 @@ import time TEST_COOKIE_NAME = 'testcookie' TEST_COOKIE_VALUE = 'worked' -class SessionWrapper(object): - def __init__(self, session_key): - self.session_key = session_key - self.accessed = False - self.modified = False - - def __contains__(self, key): - return key in self._session - - def __getitem__(self, key): - return self._session[key] - - def __setitem__(self, key, value): - self._session[key] = value - self.modified = True - - def __delitem__(self, key): - del self._session[key] - self.modified = True - - def keys(self): - return self._session.keys() - - def items(self): - return self._session.items() - - def get(self, key, default=None): - return self._session.get(key, default) - - def pop(self, key, *args): - self.modified = self.modified or key in self._session - return self._session.pop(key, *args) - - def set_test_cookie(self): - self[TEST_COOKIE_NAME] = TEST_COOKIE_VALUE - - def test_cookie_worked(self): - return self.get(TEST_COOKIE_NAME) == TEST_COOKIE_VALUE - - def delete_test_cookie(self): - del self[TEST_COOKIE_NAME] - - def _get_session(self): - # Lazily loads session from storage. - self.accessed = True - try: - return self._session_cache - except AttributeError: - if self.session_key is None: - self._session_cache = {} - else: - try: - s = Session.objects.get(session_key=self.session_key, - expire_date__gt=datetime.datetime.now()) - self._session_cache = s.get_decoded() - except (Session.DoesNotExist, SuspiciousOperation): - self._session_cache = {} - # Set the session_key to None to force creation of a new - # key, for extra security. - self.session_key = None - return self._session_cache - - _session = property(_get_session) - class SessionMiddleware(object): + def process_request(self, request): - request.session = SessionWrapper(request.COOKIES.get(settings.SESSION_COOKIE_NAME, None)) + engine = __import__(settings.SESSION_ENGINE, {}, {}, ['']) + request.session = engine.SessionStore(request.COOKIES.get(settings.SESSION_COOKIE_NAME, None)) def process_response(self, request, response): # If request.session was modified, or if response.session was set, save @@ -89,25 +25,22 @@ class SessionMiddleware(object): if accessed: patch_vary_headers(response, ('Cookie',)) if modified or settings.SESSION_SAVE_EVERY_REQUEST: - if request.session.session_key: - session_key = request.session.session_key - else: - obj = Session.objects.get_new_session_object() - session_key = obj.session_key - if settings.SESSION_EXPIRE_AT_BROWSER_CLOSE: max_age = None expires = None else: max_age = settings.SESSION_COOKIE_AGE rfcdate = formatdate(time.time() + settings.SESSION_COOKIE_AGE) + # Fixed length date must have '-' separation in the format # DD-MMM-YYYY for compliance with Netscape cookie standard - expires = (rfcdate[:7] + "-" + rfcdate[8:11] - + "-" + rfcdate[12:26] + "GMT") - new_session = Session.objects.save(session_key, request.session._session, - datetime.datetime.now() + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE)) - response.set_cookie(settings.SESSION_COOKIE_NAME, session_key, + expires = datetime.datetime.strftime(datetime.datetime.utcnow() + \ + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE), "%a, %d-%b-%Y %H:%M:%S GMT") + + # Save the seesion data and refresh the client cookie. + request.session.save() + response.set_cookie(settings.SESSION_COOKIE_NAME, request.session.session_key, max_age=max_age, expires=expires, domain=settings.SESSION_COOKIE_DOMAIN, secure=settings.SESSION_COOKIE_SECURE or None) + return response diff --git a/django/contrib/sessions/models.py b/django/contrib/sessions/models.py index 29adc6e30c..c086396947 100644 --- a/django/contrib/sessions/models.py +++ b/django/contrib/sessions/models.py @@ -1,4 +1,4 @@ -import base64, md5, random, sys, datetime, os, time +import base64, md5, random, sys, datetime import cPickle as pickle from django.db import models from django.utils.translation import ugettext_lazy as _ @@ -15,8 +15,13 @@ class SessionManager(models.Manager): "Returns session key that isn't being used." # The random module is seeded when this Apache child is created. # Use SECRET_KEY as added salt. + try: + pid = os.getpid() + except AttributeError: + # No getpid() in Jython, for example + pid = 1 while 1: - session_key = md5.new("%s%s%s%s" % (random.randint(0, sys.maxint - 1), os.getpid(), time.time(), settings.SECRET_KEY)).hexdigest() + session_key = md5.new("%s%s%s%s" % (random.randint(0, sys.maxint - 1), pid, time.time(), settings.SECRET_KEY)).hexdigest() try: self.get(session_key=session_key) except self.model.DoesNotExist: @@ -69,6 +74,7 @@ class Session(models.Model): session_data = models.TextField(_('session data')) expire_date = models.DateTimeField(_('expire date')) objects = SessionManager() + class Meta: db_table = 'django_session' verbose_name = _('session') diff --git a/django/contrib/sessions/tests.py b/django/contrib/sessions/tests.py index e83442123e..cfb475fc49 100644 --- a/django/contrib/sessions/tests.py +++ b/django/contrib/sessions/tests.py @@ -1,35 +1,59 @@ r""" ->>> s = SessionWrapper(None) -Inject data into the session cache. ->>> s._session_cache = {} ->>> s._session_cache['some key'] = 'exists' +>>> from django.contrib.sessions.backends.db import SessionStore as DatabaseSession +>>> from django.contrib.sessions.backends.cache import SessionStore as CacheSession +>>> from django.contrib.sessions.backends.file import SessionStore as FileSession ->>> s.accessed +>>> db_session = DatabaseSession() +>>> db_session.modified False ->>> s.modified -False - ->>> s.pop('non existant key', 'does not exist') +>>> db_session['cat'] = "dog" +>>> db_session.modified +True +>>> db_session.pop('cat') +'dog' +>>> db_session.pop('some key', 'does not exist') 'does not exist' ->>> s.accessed +>>> db_session.save() +>>> db_session.exists(db_session.session_key) True ->>> s.modified +>>> db_session.delete(db_session.session_key) +>>> db_session.exists(db_session.session_key) False ->>> s.pop('some key') -'exists' ->>> s.accessed +>>> file_session = FileSession() +>>> file_session.modified +False +>>> file_session['cat'] = "dog" +>>> file_session.modified True ->>> s.modified +>>> file_session.pop('cat') +'dog' +>>> file_session.pop('some key', 'does not exist') +'does not exist' +>>> file_session.save() +>>> file_session.exists(file_session.session_key) True +>>> file_session.delete(file_session.session_key) +>>> file_session.exists(file_session.session_key) +False ->>> s.pop('some key', 'does not exist') +>>> cache_session = CacheSession() +>>> cache_session.modified +False +>>> cache_session['cat'] = "dog" +>>> cache_session.modified +True +>>> cache_session.pop('cat') +'dog' +>>> cache_session.pop('some key', 'does not exist') 'does not exist' +>>> cache_session.save() +>>> cache_session.delete(cache_session.session_key) +>>> cache_session.exists(cache_session.session_key) +False """ -from django.contrib.sessions.middleware import SessionWrapper - if __name__ == '__main__': import doctest doctest.testmod() diff --git a/django/contrib/sites/models.py b/django/contrib/sites/models.py index 191d5d0a3e..fb6d0a2b1e 100644 --- a/django/contrib/sites/models.py +++ b/django/contrib/sites/models.py @@ -1,15 +1,32 @@ from django.db import models from django.utils.translation import ugettext_lazy as _ +SITE_CACHE = {} + class SiteManager(models.Manager): def get_current(self): + """ + Returns the current ``Site`` based on the SITE_ID in the + project's settings. The ``Site`` object is cached the first + time it's retrieved from the database. + """ from django.conf import settings try: sid = settings.SITE_ID except AttributeError: from django.core.exceptions import ImproperlyConfigured raise ImproperlyConfigured("You're using the Django \"sites framework\" without having set the SITE_ID setting. Create a site in your database and set the SITE_ID setting to fix this error.") - return self.get(pk=sid) + try: + current_site = SITE_CACHE[sid] + except KeyError: + current_site = self.get(pk=sid) + SITE_CACHE[sid] = current_site + return current_site + + def clear_cache(self): + """Clears the ``Site`` object cache.""" + global SITE_CACHE + SITE_CACHE = {} class Site(models.Model): domain = models.CharField(_('domain name'), max_length=100) @@ -36,7 +53,10 @@ class RequestSite(object): The save() and delete() methods raise NotImplementedError. """ def __init__(self, request): - self.domain = self.name = request.META['SERVER_NAME'] + self.domain = self.name = request.get_host() + + def __unicode__(self): + return self.domain def save(self): raise NotImplementedError('RequestSite cannot be saved.') diff --git a/django/contrib/webdesign/templatetags/webdesign.py b/django/contrib/webdesign/templatetags/webdesign.py index 2370659f1d..1eb1790132 100644 --- a/django/contrib/webdesign/templatetags/webdesign.py +++ b/django/contrib/webdesign/templatetags/webdesign.py @@ -62,6 +62,6 @@ def lorem(parser, token): count = '1' count = parser.compile_filter(count) if len(bits) != 1: - raise TemplateSyntaxError("Incorrect format for %r tag" % tagname) + raise template.TemplateSyntaxError("Incorrect format for %r tag" % tagname) return LoremNode(count, method, common) lorem = register.tag(lorem) diff --git a/django/contrib/webdesign/tests.py b/django/contrib/webdesign/tests.py index eeb1956a01..da9237a43b 100644 --- a/django/contrib/webdesign/tests.py +++ b/django/contrib/webdesign/tests.py @@ -7,6 +7,10 @@ u'lorem ipsum dolor sit amet consectetur adipisicing' >>> paragraphs(1) ['Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'] +>>> from django.template import loader, Context +>>> t = loader.get_template_from_string("{% load webdesign %}{% lorem 3 w %}") +>>> t.render(Context({})) +u'lorem ipsum dolor' """ from django.contrib.webdesign.lorem_ipsum import * diff --git a/django/core/context_processors.py b/django/core/context_processors.py index 3c826b1a7d..55c19c17e8 100644 --- a/django/core/context_processors.py +++ b/django/core/context_processors.py @@ -13,11 +13,19 @@ def auth(request): """ Returns context variables required by apps that use Django's authentication system. + + If there is no 'user' attribute in the request, uses AnonymousUser (from + django.contrib.auth). """ + if hasattr(request, 'user'): + user = request.user + else: + from django.contrib.auth.models import AnonymousUser + user = AnonymousUser() return { - 'user': request.user, - 'messages': request.user.get_and_delete_messages(), - 'perms': PermWrapper(request.user), + 'user': user, + 'messages': user.get_and_delete_messages(), + 'perms': PermWrapper(user), } def debug(request): diff --git a/django/core/handler.py b/django/core/handler.py deleted file mode 100644 index 039406722b..0000000000 --- a/django/core/handler.py +++ /dev/null @@ -1,11 +0,0 @@ -# This module is DEPRECATED! -# -# You should no longer be pointing your mod_python configuration -# at "django.core.handler". -# -# Use "django.core.handlers.modpython" instead. - -from django.core.handlers.modpython import ModPythonHandler - -def handler(req): - return ModPythonHandler()(req) diff --git a/django/core/handlers/base.py b/django/core/handlers/base.py index ca48b301d4..13c7f4193f 100644 --- a/django/core/handlers/base.py +++ b/django/core/handlers/base.py @@ -50,6 +50,10 @@ class BaseHandler(object): def get_response(self, request): "Returns an HttpResponse object for the given HttpRequest" + response = self._real_get_response(request) + return fix_location_header(request, response) + + def _real_get_response(self, request): from django.core import exceptions, urlresolvers from django.core.mail import mail_admins from django.conf import settings @@ -112,7 +116,7 @@ class BaseHandler(object): else: # Get the exception info now, in case another exception is thrown later. exc_info = sys.exc_info() - receivers = dispatcher.send(signal=signals.got_request_exception) + receivers = dispatcher.send(signal=signals.got_request_exception, request=request) # When DEBUG is False, send an error message to the admins. subject = 'Error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), request.path) try: @@ -129,3 +133,16 @@ class BaseHandler(object): "Helper function to return the traceback as a string" import traceback return '\n'.join(traceback.format_exception(*(exc_info or sys.exc_info()))) + +def fix_location_header(request, response): + """ + Ensure that we always use an absolute URI in any location header in the + response. This is required by RFC 2616, section 14.30. + + Code constructing response objects is free to insert relative paths and + this function converts them to absolute paths. + """ + if 'Location' in response and request.get_host(): + response['Location'] = request.build_absolute_uri(response['Location']) + return response + diff --git a/django/core/handlers/modpython.py b/django/core/handlers/modpython.py index 7c4bbb3082..d4f5e55011 100644 --- a/django/core/handlers/modpython.py +++ b/django/core/handlers/modpython.py @@ -42,8 +42,11 @@ class ModPythonRequest(http.HttpRequest): return '%s%s' % (self.path, self._req.args and ('?' + self._req.args) or '') def is_secure(self): - # Note: modpython 3.2.10+ has req.is_https(), but we need to support previous versions - return 'HTTPS' in self._req.subprocess_env and self._req.subprocess_env['HTTPS'] == 'on' + try: + return self._req.is_https() + except AttributeError: + # mod_python < 3.2.10 doesn't have req.is_https(). + return self._req.subprocess_env.get('HTTPS', '').lower() in ('on', '1') def _load_post_and_files(self): "Populates self._post and self._files" @@ -159,8 +162,8 @@ class ModPythonHandler(BaseHandler): # Convert our custom HttpResponse object back into the mod_python req. req.content_type = response['Content-Type'] - for key, value in response.headers.items(): - if key != 'Content-Type': + for key, value in response.items(): + if key != 'content-type': req.headers_out[str(key)] = str(value) for c in response.cookies.values(): req.headers_out.add('Set-Cookie', c.output(header='')) diff --git a/django/core/handlers/wsgi.py b/django/core/handlers/wsgi.py index 99d400d1bb..6fe24f5d13 100644 --- a/django/core/handlers/wsgi.py +++ b/django/core/handlers/wsgi.py @@ -208,7 +208,7 @@ class WSGIHandler(BaseHandler): except KeyError: status_text = 'UNKNOWN STATUS CODE' status = '%s %s' % (response.status_code, status_text) - response_headers = [(str(k), str(v)) for k, v in response.headers.items()] + response_headers = [(str(k), str(v)) for k, v in response.items()] for c in response.cookies.values(): response_headers.append(('Set-Cookie', str(c.output(header='')))) start_response(status, response_headers) diff --git a/django/core/mail.py b/django/core/mail.py index ff653400f9..b90752e649 100644 --- a/django/core/mail.py +++ b/django/core/mail.py @@ -50,7 +50,11 @@ def make_msgid(idstring=None): """ timeval = time.time() utcdate = time.strftime('%Y%m%d%H%M%S', time.gmtime(timeval)) - pid = os.getpid() + try: + pid = os.getpid() + except AttributeError: + # Not getpid() in Jython, for example. + pid = 1 randint = random.randrange(100000) if idstring is None: idstring = '' diff --git a/django/core/management/__init__.py b/django/core/management/__init__.py index 7a3f9ca7a5..a4731652f5 100644 --- a/django/core/management/__init__.py +++ b/django/core/management/__init__.py @@ -2,7 +2,6 @@ import django from optparse import OptionParser import os import sys -import textwrap # For backwards compatibility: get_version() used to be in this module. get_version = django.get_version @@ -18,9 +17,9 @@ def load_command_class(name): def call_command(name, *args, **options): """ Calls the given command, with the given options and args/kwargs. - + This is the primary API you should use for calling specific commands. - + Some examples: call_command('syncdb') call_command('shell', plain=True) @@ -36,7 +35,9 @@ class ManagementUtility(object): A ManagementUtility has a number of commands, which can be manipulated by editing the self.commands dictionary. """ - def __init__(self): + def __init__(self, argv=None): + self.argv = argv or sys.argv[:] + self.prog_name = os.path.basename(self.argv[0]) self.commands = self.default_commands() def default_commands(self): @@ -52,76 +53,57 @@ class ManagementUtility(object): names = [f[:-3] for f in os.listdir(command_dir) if not f.startswith('_') and f.endswith('.py')] return dict([(name, load_command_class(name)) for name in names]) - def usage(self): + def main_help_text(self): """ - Returns a usage string, for use with optparse. - - The string doesn't include the options (e.g., "--verbose"), because - optparse puts those in automatically. + Returns the script's main help text, as a string. """ - usage = ["%prog command [options]\nactions:"] - commands = self.commands.items() + usage = ['%s <subcommand> [options] [args]' % self.prog_name] + usage.append('Django command line tool, version %s' % django.get_version()) + usage.append("Type '%s help <subcommand>' for help on a specific subcommand." % self.prog_name) + usage.append('Available subcommands:') + commands = self.commands.keys() commands.sort() - for name, cmd in commands: - usage.append(' %s %s' % (name, cmd.args)) - usage.extend(textwrap.wrap(cmd.help, initial_indent=' ', subsequent_indent=' ')) - usage.append('') - return '\n'.join(usage[:-1]) # Cut off the last list element, an empty space. + for cmd in commands: + usage.append(' %s' % cmd) + return '\n'.join(usage) - def execute(self, argv=None): + def fetch_command(self, subcommand): """ - Parses the given argv from the command line, determines which command - to run and runs the command. + Tries to fetch the given subcommand, printing a message with the + appropriate command called from the command line (usually + django-admin.py or manage.py) if it can't be found. """ - if argv is None: - argv = sys.argv - - # Create the parser object and parse the command-line args. - # TODO: Ideally each Command class would register its own options for - # add_option(), but we'd need to figure out how to allow for multiple - # Commands using the same options. The optparse library gets in the way - # by checking for conflicts: - # http://docs.python.org/lib/optparse-conflicts-between-options.html - parser = OptionParser(usage=self.usage(), version=get_version()) - parser.add_option('--settings', - help='The Python path to a settings module, e.g. "myproject.settings.main". If this isn\'t provided, the DJANGO_SETTINGS_MODULE environment variable will be used.') - parser.add_option('--pythonpath', - help='A directory to add to the Python path, e.g. "/home/djangoprojects/myproject".') - parser.add_option('--plain', action='store_true', dest='plain', - help='When using "shell": Tells Django to use plain Python, not IPython.') - parser.add_option('--noinput', action='store_false', dest='interactive', default=True, - help='Tells Django to NOT prompt the user for input of any kind.') - parser.add_option('--noreload', action='store_false', dest='use_reloader', default=True, - help='When using "runserver": Tells Django to NOT use the auto-reloader.') - parser.add_option('--format', default='json', dest='format', - help='Specifies the output serialization format for fixtures') - parser.add_option('--indent', default=None, dest='indent', - type='int', help='Specifies the indent level to use when pretty-printing output') - parser.add_option('--verbosity', action='store', dest='verbosity', default='1', - type='choice', choices=['0', '1', '2'], - help='Verbosity level; 0=minimal output, 1=normal output, 2=all output') - parser.add_option('--adminmedia', dest='admin_media_path', default='', - help='When using "runserver": Specifies the directory from which to serve admin media.') - options, args = parser.parse_args(argv[1:]) - - # If the 'settings' or 'pythonpath' options were submitted, activate those. - if options.settings: - os.environ['DJANGO_SETTINGS_MODULE'] = options.settings - if options.pythonpath: - sys.path.insert(0, options.pythonpath) - - # Run the appropriate command. try: - command_name = args[0] - except IndexError: - sys.stderr.write("Type '%s --help' for usage.\n" % os.path.basename(argv[0])) + return self.commands[subcommand] + except KeyError: + sys.stderr.write("Unknown command: %r\nType '%s help' for usage.\n" % (subcommand, self.prog_name)) sys.exit(1) + + def execute(self): + """ + Given the command-line arguments, this figures out which subcommand is + being run, creates a parser appropriate to that command, and runs it. + """ try: - command = self.commands[command_name] - except KeyError: - sys.stderr.write("Unknown command: %r\nType '%s --help' for usage.\n" % (command_name, os.path.basename(argv[0]))) + subcommand = self.argv[1] + except IndexError: + sys.stderr.write("Type '%s help' for usage.\n" % self.prog_name) sys.exit(1) - command.execute(*args[1:], **options.__dict__) + + if subcommand == 'help': + if len(self.argv) > 2: + self.fetch_command(self.argv[2]).print_help(self.prog_name, self.argv[2]) + else: + sys.stderr.write(self.main_help_text() + '\n') + sys.exit(1) + # Special-cases: We want 'django-admin.py --version' and + # 'django-admin.py --help' to work, for backwards compatibility. + elif self.argv[1:] == ['--version']: + print django.get_version() + elif self.argv[1:] == ['--help']: + sys.stderr.write(self.main_help_text() + '\n') + else: + self.fetch_command(subcommand).run_from_argv(self.argv) class ProjectManagementUtility(ManagementUtility): """ @@ -132,8 +114,8 @@ class ProjectManagementUtility(ManagementUtility): In practice, this class represents manage.py, whereas ManagementUtility represents django-admin.py. """ - def __init__(self, project_directory): - super(ProjectManagementUtility, self).__init__() + def __init__(self, argv, project_directory): + super(ProjectManagementUtility, self).__init__(argv) # Remove the "startproject" command from self.commands, because # that's a django-admin.py command, not a manage.py command. @@ -167,8 +149,8 @@ def execute_from_command_line(argv=None): """ A simple method that runs a ManagementUtility. """ - utility = ManagementUtility() - utility.execute(argv) + utility = ManagementUtility(argv) + utility.execute() def execute_manager(settings_mod, argv=None): """ @@ -176,5 +158,5 @@ def execute_manager(settings_mod, argv=None): project-specific django-admin.py utility. """ project_directory = setup_environ(settings_mod) - utility = ProjectManagementUtility(project_directory) - utility.execute(argv) + utility = ProjectManagementUtility(argv, project_directory) + utility.execute() diff --git a/django/core/management/base.py b/django/core/management/base.py index 866dec4407..d883fe23dc 100644 --- a/django/core/management/base.py +++ b/django/core/management/base.py @@ -1,12 +1,22 @@ +import django from django.core.exceptions import ImproperlyConfigured from django.core.management.color import color_style +import itertools +from optparse import make_option, OptionParser import sys +import os class CommandError(Exception): pass class BaseCommand(object): # Metadata about this command. + option_list = ( + make_option('--settings', + help='The Python path to a settings module, e.g. "myproject.settings.main". If this isn\'t provided, the DJANGO_SETTINGS_MODULE environment variable will be used.'), + make_option('--pythonpath', + help='A directory to add to the Python path, e.g. "/home/djangoprojects/myproject".'), + ) help = '' args = '' @@ -18,6 +28,39 @@ class BaseCommand(object): def __init__(self): self.style = color_style() + def get_version(self): + """ + Returns the Django version, which should be correct for all built-in + Django commands. User-supplied commands should override this method. + """ + return django.get_version() + + def usage(self, subcommand): + usage = '%%prog %s [options] %s' % (subcommand, self.args) + if self.help: + return '%s\n\n%s' % (usage, self.help) + else: + return usage + + def create_parser(self, prog_name, subcommand): + return OptionParser(prog=prog_name, + usage=self.usage(subcommand), + version=self.get_version(), + option_list=self.option_list) + + def print_help(self, prog_name, subcommand): + parser = self.create_parser(prog_name, subcommand) + parser.print_help() + + def run_from_argv(self, argv): + parser = self.create_parser(argv[0], argv[1]) + options, args = parser.parse_args(argv[2:]) + if options.settings: + os.environ['DJANGO_SETTINGS_MODULE'] = options.settings + if options.pythonpath: + sys.path.insert(0, options.pythonpath) + self.execute(*args, **options.__dict__) + def execute(self, *args, **options): # Switch to English, because django-admin.py creates database content # like permissions, and those shouldn't contain any translations. @@ -44,7 +87,7 @@ class BaseCommand(object): sys.stderr.write(self.style.ERROR(str('Error: %s\n' % e))) sys.exit(1) - def validate(self, app=None): + def validate(self, app=None, display_num_errors=False): """ Validates the given app, raising CommandError for any errors. @@ -61,12 +104,14 @@ class BaseCommand(object): s.seek(0) error_text = s.read() raise CommandError("One or more models did not validate:\n%s" % error_text) + if display_num_errors: + print "%s error%s found" % (num_errors, num_errors != 1 and 's' or '') def handle(self, *args, **options): raise NotImplementedError() class AppCommand(BaseCommand): - args = '[appname ...]' + args = '<appname appname ...>' def handle(self, *app_labels, **options): from django.db import models @@ -87,7 +132,7 @@ class AppCommand(BaseCommand): raise NotImplementedError() class LabelCommand(BaseCommand): - args = '[label ...]' + args = '<label label ...>' label = 'label' def handle(self, *labels, **options): @@ -119,7 +164,6 @@ class NoArgsCommand(BaseCommand): def copy_helper(style, app_or_project, name, directory, other_name=''): import django - import os import re import shutil other = {'project': 'app', 'app': 'project'}[app_or_project] @@ -155,5 +199,18 @@ def copy_helper(style, app_or_project, name, directory, other_name=''): fp_new.close() try: shutil.copymode(path_old, path_new) + _make_writeable(path_new) except OSError: sys.stderr.write(style.NOTICE("Notice: Couldn't set permission bits on %s. You're probably using an uncommon filesystem setup. No problem.\n" % path_new)) + +def _make_writeable(filename): + "Makes sure that the file is writeable. Useful if our source is read-only." + import stat + if sys.platform.startswith('java'): + # On Jython there is no os.access() + return + if not os.access(filename, os.W_OK): + st = os.stat(filename) + new_permissions = stat.S_IMODE(st.st_mode) | stat.S_IWUSR + os.chmod(filename, new_permissions) + diff --git a/django/core/management/color.py b/django/core/management/color.py index 06edb6066b..ce95401491 100644 --- a/django/core/management/color.py +++ b/django/core/management/color.py @@ -7,7 +7,7 @@ import sys def color_style(): "Returns a Style object with the Django color scheme." - if sys.platform == 'win32' or sys.platform == 'Pocket PC' or not sys.stdout.isatty(): + if sys.platform == 'win32' or sys.platform == 'Pocket PC' or sys.platform.startswith('java') or not sys.stdout.isatty(): return no_style() class dummy: pass style = dummy() diff --git a/django/core/management/commands/adminindex.py b/django/core/management/commands/adminindex.py index e3dd493fd3..4f389136ca 100644 --- a/django/core/management/commands/adminindex.py +++ b/django/core/management/commands/adminindex.py @@ -1,4 +1,5 @@ from django.core.management.base import AppCommand +from django.utils.encoding import force_unicode from django.utils.text import capfirst MODULE_TEMPLATE = ''' {%% if perms.%(app)s.%(addperm)s or perms.%(app)s.%(changeperm)s %%} @@ -24,7 +25,7 @@ class Command(AppCommand): output.append(MODULE_TEMPLATE % { 'app': app_label, 'mod': model._meta.module_name, - 'name': capfirst(model._meta.verbose_name_plural), + 'name': force_unicode(capfirst(model._meta.verbose_name_plural)), 'addperm': model._meta.get_add_permission(), 'changeperm': model._meta.get_change_permission(), }) diff --git a/django/core/management/commands/createcachetable.py b/django/core/management/commands/createcachetable.py index c1fa1a26a5..c8df8d04f7 100644 --- a/django/core/management/commands/createcachetable.py +++ b/django/core/management/commands/createcachetable.py @@ -2,7 +2,7 @@ from django.core.management.base import LabelCommand class Command(LabelCommand): help = "Creates the table needed to use the SQL cache backend." - args = "[tablename]" + args = "<tablename>" label = 'tablename' requires_model_validation = False diff --git a/django/core/management/commands/dumpdata.py b/django/core/management/commands/dumpdata.py index 48677ca5fa..7bdcc4271f 100644 --- a/django/core/management/commands/dumpdata.py +++ b/django/core/management/commands/dumpdata.py @@ -1,8 +1,16 @@ from django.core.management.base import BaseCommand, CommandError +from optparse import make_option + class Command(BaseCommand): + option_list = BaseCommand.option_list + ( + make_option('--format', default='json', dest='format', + help='Specifies the output serialization format for fixtures'), + make_option('--indent', default=None, dest='indent', type='int', + help='Specifies the indent level to use when pretty-printing output'), + ) help = 'Output the contents of the database as a fixture of the given format.' - args = '[--format] [--indent] [appname ...]' + args = '[appname ...]' def handle(self, *app_labels, **options): from django.db.models import get_app, get_apps, get_models diff --git a/django/core/management/commands/flush.py b/django/core/management/commands/flush.py index 395359d269..87a99b8beb 100644 --- a/django/core/management/commands/flush.py +++ b/django/core/management/commands/flush.py @@ -1,9 +1,16 @@ from django.core.management.base import NoArgsCommand, CommandError from django.core.management.color import no_style +from optparse import make_option class Command(NoArgsCommand): + option_list = NoArgsCommand.option_list + ( + make_option('--verbosity', action='store', dest='verbosity', default='1', + type='choice', choices=['0', '1', '2'], + help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'), + make_option('--noinput', action='store_false', dest='interactive', default=True, + help='Tells Django to NOT prompt the user for input of any kind.'), + ) help = "Executes ``sqlflush`` on the current database." - args = '[--verbosity] [--noinput]' def handle_noargs(self, **options): from django.conf import settings diff --git a/django/core/management/commands/loaddata.py b/django/core/management/commands/loaddata.py index 4cbdb55c67..83fc9b8ac9 100644 --- a/django/core/management/commands/loaddata.py +++ b/django/core/management/commands/loaddata.py @@ -1,5 +1,6 @@ from django.core.management.base import BaseCommand from django.core.management.color import no_style +from optparse import make_option import sys import os @@ -9,8 +10,13 @@ except NameError: from sets import Set as set # Python 2.3 fallback class Command(BaseCommand): + option_list = BaseCommand.option_list + ( + make_option('--verbosity', action='store', dest='verbosity', default='1', + type='choice', choices=['0', '1', '2'], + help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'), + ) help = 'Installs the named fixture(s) in the database.' - args = "[--verbosity] fixture, fixture, ..." + args = "fixture [fixture ...]" def handle(self, *fixture_labels, **options): from django.db.models import get_apps diff --git a/django/core/management/commands/reset.py b/django/core/management/commands/reset.py index 5c89d94678..3e7ca9f689 100644 --- a/django/core/management/commands/reset.py +++ b/django/core/management/commands/reset.py @@ -1,9 +1,14 @@ from django.core.management.base import AppCommand, CommandError from django.core.management.color import no_style +from optparse import make_option class Command(AppCommand): + option_list = AppCommand.option_list + ( + make_option('--noinput', action='store_false', dest='interactive', default=True, + help='Tells Django to NOT prompt the user for input of any kind.'), + ) help = "Executes ``sqlreset`` for the given app(s) in the current database." - args = '[--noinput] [appname ...]' + args = '[appname ...]' output_transaction = True diff --git a/django/core/management/commands/runfcgi.py b/django/core/management/commands/runfcgi.py index 406a27b8c3..a60d4ebc59 100644 --- a/django/core/management/commands/runfcgi.py +++ b/django/core/management/commands/runfcgi.py @@ -14,3 +14,7 @@ class Command(BaseCommand): pass from django.core.servers.fastcgi import runfastcgi runfastcgi(args) + + def usage(self, subcommand): + from django.core.servers.fastcgi import FASTCGI_HELP + return FASTCGI_HELP diff --git a/django/core/management/commands/runserver.py b/django/core/management/commands/runserver.py index d06744e9fa..5b141d03ed 100644 --- a/django/core/management/commands/runserver.py +++ b/django/core/management/commands/runserver.py @@ -1,10 +1,17 @@ from django.core.management.base import BaseCommand, CommandError +from optparse import make_option import os import sys class Command(BaseCommand): + option_list = BaseCommand.option_list + ( + make_option('--noreload', action='store_false', dest='use_reloader', default=True, + help='Tells Django to NOT use the auto-reloader.'), + make_option('--adminmedia', dest='admin_media_path', default='', + help='Specifies the directory from which to serve admin media.'), + ) help = "Starts a lightweight Web server for development." - args = '[--noreload] [--adminmedia=ADMIN_MEDIA_PATH] [optional port number, or ipaddr:port]' + args = '[optional port number, or ipaddr:port]' # Validation is called explicitly each time the server is reloaded. requires_model_validation = False @@ -37,7 +44,7 @@ class Command(BaseCommand): def inner_run(): from django.conf import settings print "Validating models..." - self.validate() + self.validate(display_num_errors=True) print "\nDjango version %s, using settings %r" % (django.get_version(), settings.SETTINGS_MODULE) print "Development server is running at http://%s:%s/" % (addr, port) print "Quit the server with %s." % quit_command diff --git a/django/core/management/commands/shell.py b/django/core/management/commands/shell.py index bc76c44b97..96169020e5 100644 --- a/django/core/management/commands/shell.py +++ b/django/core/management/commands/shell.py @@ -1,8 +1,13 @@ +import os from django.core.management.base import NoArgsCommand +from optparse import make_option class Command(NoArgsCommand): + option_list = NoArgsCommand.option_list + ( + make_option('--plain', action='store_true', dest='plain', + help='Tells Django to use plain Python, not IPython.'), + ) help = "Runs a Python interactive interpreter. Tries to use IPython, if it's available." - args = '[--plain]' requires_model_validation = False @@ -39,4 +44,16 @@ class Command(NoArgsCommand): import rlcompleter readline.set_completer(rlcompleter.Completer(imported_objects).complete) readline.parse_and_bind("tab:complete") + + # We want to honor both $PYTHONSTARTUP and .pythonrc.py, so follow system + # conventions and get $PYTHONSTARTUP first then import user. + if not use_plain: + pythonrc = os.environ.get("PYTHONSTARTUP") + if pythonrc and os.path.isfile(pythonrc): + try: + execfile(pythonrc) + except NameError: + pass + # This will import .pythonrc.py as a side-effect + import user code.interact(local=imported_objects) diff --git a/django/core/management/commands/startproject.py b/django/core/management/commands/startproject.py index 0d9e4bd381..ab4f409f15 100644 --- a/django/core/management/commands/startproject.py +++ b/django/core/management/commands/startproject.py @@ -28,11 +28,6 @@ class Command(LabelCommand): # Create a random SECRET_KEY hash, and put it in the main settings. main_settings_file = os.path.join(directory, project_name, 'settings.py') settings_contents = open(main_settings_file, 'r').read() - - # If settings.py was copied from a read-only source, make it writeable. - if not os.access(main_settings_file, os.W_OK): - os.chmod(main_settings_file, 0600) - fp = open(main_settings_file, 'w') secret_key = ''.join([choice('abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)') for i in range(50)]) settings_contents = re.sub(r"(?<=SECRET_KEY = ')'", secret_key + "'", settings_contents) diff --git a/django/core/management/commands/syncdb.py b/django/core/management/commands/syncdb.py index 2e272b541b..8b4bb68005 100644 --- a/django/core/management/commands/syncdb.py +++ b/django/core/management/commands/syncdb.py @@ -1,5 +1,6 @@ from django.core.management.base import NoArgsCommand from django.core.management.color import no_style +from optparse import make_option import sys try: @@ -8,8 +9,14 @@ except NameError: from sets import Set as set # Python 2.3 fallback class Command(NoArgsCommand): + option_list = NoArgsCommand.option_list + ( + make_option('--verbosity', action='store', dest='verbosity', default='1', + type='choice', choices=['0', '1', '2'], + help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'), + make_option('--noinput', action='store_false', dest='interactive', default=True, + help='Tells Django to NOT prompt the user for input of any kind.'), + ) help = "Create the database tables for all apps in INSTALLED_APPS whose tables haven't already been created." - args = '[--verbosity] [--noinput]' def handle_noargs(self, **options): from django.db import connection, transaction, models @@ -31,16 +38,16 @@ class Command(NoArgsCommand): cursor = connection.cursor() - # Get a list of all existing database tables, - # so we know what needs to be added. - table_list = table_list() if connection.features.uses_case_insensitive_names: - table_name_converter = str.upper + table_name_converter = lambda x: x.upper() else: table_name_converter = lambda x: x + # Get a list of all existing database tables, so we know what needs to + # be added. + tables = [table_name_converter(name) for name in table_list()] # Get a list of already installed *models* so that references work right. - seen_models = installed_models(table_list) + seen_models = installed_models(tables) created_models = set() pending_references = {} @@ -52,7 +59,7 @@ class Command(NoArgsCommand): # Create the model's database table, if it doesn't already exist. if verbosity >= 2: print "Processing %s.%s model" % (app_name, model._meta.object_name) - if table_name_converter(model._meta.db_table) in table_list: + if table_name_converter(model._meta.db_table) in tables: continue sql, references = sql_model_create(model, self.style, seen_models) seen_models.add(model) @@ -64,7 +71,7 @@ class Command(NoArgsCommand): print "Creating table %s" % model._meta.db_table for statement in sql: cursor.execute(statement) - table_list.append(table_name_converter(model._meta.db_table)) + tables.append(table_name_converter(model._meta.db_table)) # Create the m2m tables. This must be done after all tables have been created # to ensure that all referred tables will exist. diff --git a/django/core/management/commands/test.py b/django/core/management/commands/test.py index 8e27fd5606..f0e13a2069 100644 --- a/django/core/management/commands/test.py +++ b/django/core/management/commands/test.py @@ -1,9 +1,17 @@ from django.core.management.base import BaseCommand +from optparse import make_option import sys class Command(BaseCommand): + option_list = BaseCommand.option_list + ( + make_option('--verbosity', action='store', dest='verbosity', default='1', + type='choice', choices=['0', '1', '2'], + help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'), + make_option('--noinput', action='store_false', dest='interactive', default=True, + help='Tells Django to NOT prompt the user for input of any kind.'), + ) help = 'Runs the test suite for the specified applications, or the entire site if no apps are specified.' - args = '[--verbosity] [--noinput] [appname ...]' + args = '[appname ...]' requires_model_validation = False diff --git a/django/core/management/commands/testserver.py b/django/core/management/commands/testserver.py index 907960894c..9b169d3d9b 100644 --- a/django/core/management/commands/testserver.py +++ b/django/core/management/commands/testserver.py @@ -1,6 +1,16 @@ from django.core.management.base import BaseCommand +from optparse import make_option + class Command(BaseCommand): + option_list = BaseCommand.option_list + ( + make_option('--verbosity', action='store', dest='verbosity', default='1', + type='choice', choices=['0', '1', '2'], + help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'), + make_option('--addrport', action='store', dest='addrport', + type='string', default='', + help='port number or ipaddr:port to run the server on'), + ) help = 'Runs a development server with data from the given fixture(s).' args = '[fixture ...]' @@ -12,6 +22,7 @@ class Command(BaseCommand): from django.test.utils import create_test_db verbosity = int(options.get('verbosity', 1)) + addrport = options.get('addrport') # Create a test database. db_name = create_test_db(verbosity=verbosity) @@ -23,4 +34,4 @@ class Command(BaseCommand): # a strange error -- it causes this handle() method to be called # multiple times. shutdown_message = '\nServer stopped.\nNote that the test database, %r, has not been deleted. You can explore it on your own.' % db_name - call_command('runserver', shutdown_message=shutdown_message, use_reloader=False) + call_command('runserver', addrport=addrport, shutdown_message=shutdown_message, use_reloader=False) diff --git a/django/core/management/commands/validate.py b/django/core/management/commands/validate.py index 2751f41abd..760d41c5bf 100644 --- a/django/core/management/commands/validate.py +++ b/django/core/management/commands/validate.py @@ -6,4 +6,4 @@ class Command(NoArgsCommand): requires_model_validation = False def handle_noargs(self, **options): - self.validate() + self.validate(display_num_errors=True) diff --git a/django/core/management/sql.py b/django/core/management/sql.py index 92effe0fa2..884063f4f0 100644 --- a/django/core/management/sql.py +++ b/django/core/management/sql.py @@ -130,7 +130,7 @@ def sql_delete(app, style): else: table_names = [] if connection.features.uses_case_insensitive_names: - table_name_converter = str.upper + table_name_converter = lambda x: x.upper() else: table_name_converter = lambda x: x @@ -302,7 +302,8 @@ def sql_model_create(model, style, known_models=set()): if opts.has_auto_field: # Add any extra SQL needed to support auto-incrementing primary keys. - autoinc_sql = connection.ops.autoinc_sql(opts.db_table) + auto_column = opts.auto_field.db_column or opts.auto_field.name + autoinc_sql = connection.ops.autoinc_sql(opts.db_table, auto_column) if autoinc_sql: for stmt in autoinc_sql: final_output.append(stmt) @@ -385,7 +386,7 @@ def many_to_many_sql_for_model(model, style): final_output.append('\n'.join(table_output)) # Add any extra SQL needed to support auto-incrementing PKs - autoinc_sql = connection.ops.autoinc_sql(f.m2m_db_table()) + autoinc_sql = connection.ops.autoinc_sql(f.m2m_db_table(), 'id') if autoinc_sql: for stmt in autoinc_sql: final_output.append(stmt) diff --git a/django/core/management/validation.py b/django/core/management/validation.py index aa4ef47c2f..9e004d3d25 100644 --- a/django/core/management/validation.py +++ b/django/core/management/validation.py @@ -1,5 +1,6 @@ import sys from django.core.management.color import color_style +from django.utils.itercompat import is_iterable class ModelErrorCollection: def __init__(self, outfile=sys.stdout): @@ -51,7 +52,7 @@ def get_validation_errors(outfile, app=None): if f.prepopulate_from is not None and type(f.prepopulate_from) not in (list, tuple): e.add(opts, '"%s": prepopulate_from should be a list or tuple.' % f.name) if f.choices: - if not hasattr(f.choices, '__iter__'): + if isinstance(f.choices, basestring) or not is_iterable(f.choices): e.add(opts, '"%s": "choices" should be iterable (e.g., a tuple or list).' % f.name) else: for c in f.choices: diff --git a/django/core/paginator.py b/django/core/paginator.py index 380808a3dd..b50ca826c4 100644 --- a/django/core/paginator.py +++ b/django/core/paginator.py @@ -20,6 +20,7 @@ class ObjectPaginator(object): self.num_per_page = num_per_page self.orphans = orphans self._hits = self._pages = None + self._page_range = None def validate_page_number(self, page_number): try: @@ -83,6 +84,16 @@ class ObjectPaginator(object): hits = 0 self._pages = hits // self.num_per_page + 1 return self._pages + + def _get_page_range(self): + """ + Returns a 1-based range of pages for iterating through within + a template for loop. + """ + if self._page_range is None: + self._page_range = range(1, self._pages + 1) + return self._page_range hits = property(_get_hits) pages = property(_get_pages) + page_range = property(_get_page_range) diff --git a/django/core/serializers/__init__.py b/django/core/serializers/__init__.py index 049edf7521..1e24e2bd22 100644 --- a/django/core/serializers/__init__.py +++ b/django/core/serializers/__init__.py @@ -3,9 +3,9 @@ Interfaces for serializing Django objects. Usage:: - >>> from django.core import serializers - >>> json = serializers.serialize("json", some_query_set) - >>> objects = list(serializers.deserialize("json", json)) + from django.core import serializers + json = serializers.serialize("json", some_query_set) + objects = list(serializers.deserialize("json", json)) To add your own serializers, use the SERIALIZATION_MODULES setting:: diff --git a/django/core/serializers/python.py b/django/core/serializers/python.py index f61a2fa4a2..6fc13d76b5 100644 --- a/django/core/serializers/python.py +++ b/django/core/serializers/python.py @@ -27,13 +27,13 @@ class Serializer(base.Serializer): def end_object(self, obj): self.objects.append({ "model" : smart_unicode(obj._meta), - "pk" : smart_unicode(obj._get_pk_val()), + "pk" : smart_unicode(obj._get_pk_val(), strings_only=True), "fields" : self._current }) self._current = None def handle_field(self, obj, field): - self._current[field.name] = getattr(obj, field.name) + self._current[field.name] = smart_unicode(getattr(obj, field.name), strings_only=True) def handle_fk_field(self, obj, field): related = getattr(obj, field.name) @@ -44,10 +44,11 @@ class Serializer(base.Serializer): else: # Related to remote object via other field related = getattr(related, field.rel.field_name) - self._current[field.name] = related + self._current[field.name] = smart_unicode(related, strings_only=True) def handle_m2m_field(self, obj, field): - self._current[field.name] = [related._get_pk_val() for related in getattr(obj, field.name).iterator()] + self._current[field.name] = [smart_unicode(related._get_pk_val(), strings_only=True) + for related in getattr(obj, field.name).iterator()] def getvalue(self): return self.objects diff --git a/django/core/servers/fastcgi.py b/django/core/servers/fastcgi.py index 619758a0b1..de04a5af62 100644 --- a/django/core/servers/fastcgi.py +++ b/django/core/servers/fastcgi.py @@ -17,14 +17,12 @@ import sys, os __version__ = "0.1" __all__ = ["runfastcgi"] -FASTCGI_HELP = r"""runfcgi: +FASTCGI_HELP = r""" Run this project as a fastcgi (or some other protocol supported by flup) application. To do this, the flup package from http://www.saddi.com/software/flup/ is required. -Usage: - django-admin.py runfcgi --settings=yourproject.settings [fcgi settings] - manage.py runfcgi [fcgi settings] + runfcgi [options] [fcgi settings] Optional Fcgi settings: (setting=value) protocol=PROTOCOL fcgi, scgi, ajp, ... (default fcgi) diff --git a/django/core/validators.py b/django/core/validators.py index 8a93462b21..874edaefdd 100644 --- a/django/core/validators.py +++ b/django/core/validators.py @@ -9,16 +9,17 @@ form field is required. """ import urllib2 -from django.conf import settings -from django.utils.translation import ugettext as _, ugettext_lazy, ungettext -from django.utils.functional import Promise, lazy -from django.utils.encoding import force_unicode import re try: from decimal import Decimal, DecimalException except ImportError: from django.utils._decimal import Decimal, DecimalException # Python 2.3 +from django.conf import settings +from django.utils.translation import ugettext as _, ugettext_lazy, ungettext +from django.utils.functional import Promise, lazy +from django.utils.encoding import force_unicode + _datere = r'\d{4}-\d{1,2}-\d{1,2}' _timere = r'(?:[01]?[0-9]|2[0-3]):[0-5][0-9](?::[0-5][0-9])?' alnum_re = re.compile(r'^\w+$') @@ -148,7 +149,7 @@ def _isValidDate(date_string): date(year, month, day) except ValueError, e: msg = _('Invalid date: %s') % _(str(e)) - raise ValidationError, msg + raise ValidationError, msg def isValidANSIDate(field_data, all_data): if not ansi_date_re.search(field_data): @@ -180,8 +181,15 @@ def isValidImage(field_data, all_data): except TypeError: raise ValidationError, _("No file was submitted. Check the encoding type on the form.") try: - Image.open(StringIO(content)) - except IOError: # Python Imaging Library doesn't recognize it as an image + # load() is the only method that can spot a truncated JPEG, + # but it cannot be called sanely after verify() + trial_image = Image.open(StringIO(content)) + trial_image.load() + # verify() is the only method that can spot a corrupt PNG, + # but it must be called immediately after the constructor + trial_image = Image.open(StringIO(content)) + trial_image.verify() + except Exception: # Python Imaging Library doesn't recognize it as an image raise ValidationError, _("Upload a valid image. The file you uploaded was either not an image or a corrupted image.") def isValidImageURL(field_data, all_data): @@ -251,7 +259,7 @@ def isExistingURL(field_data, all_data): raise ValidationError, _("The URL %s is a broken link.") % field_data except: # urllib2.URLError, httplib.InvalidURL, etc. raise ValidationError, _("The URL %s is a broken link.") % field_data - + def isValidUSState(field_data, all_data): "Checks that the given string is a valid two-letter U.S. state abbreviation" states = ['AA', 'AE', 'AK', 'AL', 'AP', 'AR', 'AS', 'AZ', 'CA', 'CO', 'CT', 'DC', 'DE', 'FL', 'FM', 'GA', 'GU', 'HI', 'IA', 'ID', 'IL', 'IN', 'KS', 'KY', 'LA', 'MA', 'MD', 'ME', 'MH', 'MI', 'MN', 'MO', 'MP', 'MS', 'MT', 'NC', 'ND', 'NE', 'NH', 'NJ', 'NM', 'NV', 'NY', 'OH', 'OK', 'OR', 'PA', 'PR', 'PW', 'RI', 'SC', 'SD', 'TN', 'TX', 'UT', 'VA', 'VI', 'VT', 'WA', 'WI', 'WV', 'WY'] @@ -380,13 +388,13 @@ class NumberIsInRange(object): self.error_message = error_message def __call__(self, field_data, all_data): - # Try to make the value numeric. If this fails, we assume another + # Try to make the value numeric. If this fails, we assume another # validator will catch the problem. try: val = float(field_data) except ValueError: return - + # Now validate if self.lower and self.upper and (val < self.lower or val > self.upper): raise ValidationError(self.error_message) @@ -397,12 +405,17 @@ class NumberIsInRange(object): class IsAPowerOf(object): """ - >>> v = IsAPowerOf(2) - >>> v(4, None) - >>> v(8, None) - >>> v(16, None) - >>> v(17, None) - django.core.validators.ValidationError: ['This value must be a power of 2.'] + Usage: If you create an instance of the IsPowerOf validator: + v = IsAPowerOf(2) + + The following calls will succeed: + v(4, None) + v(8, None) + v(16, None) + + But this call: + v(17, None) + will raise "django.core.validators.ValidationError: ['This value must be a power of 2.']" """ def __init__(self, power_of): self.power_of = power_of @@ -423,7 +436,7 @@ class IsValidDecimal(object): except DecimalException: raise ValidationError, _("Please enter a valid decimal number.") - pieces = str(val).split('.') + pieces = str(val).lstrip("-").split('.') decimals = (len(pieces) == 2) and len(pieces[1]) or 0 digits = len(pieces[0]) diff --git a/django/db/__init__.py b/django/db/__init__.py index 33223d200a..d4ea1403bd 100644 --- a/django/db/__init__.py +++ b/django/db/__init__.py @@ -1,6 +1,9 @@ +import os from django.conf import settings from django.core import signals +from django.core.exceptions import ImproperlyConfigured from django.dispatch import dispatcher +from django.utils.functional import curry __all__ = ('backend', 'connection', 'DatabaseError', 'IntegrityError') @@ -8,25 +11,43 @@ if not settings.DATABASE_ENGINE: settings.DATABASE_ENGINE = 'dummy' try: - backend = __import__('django.db.backends.%s.base' % settings.DATABASE_ENGINE, {}, {}, ['']) + # Most of the time, the database backend will be one of the official + # backends that ships with Django, so look there first. + _import_path = 'django.db.backends.' + backend = __import__('%s%s.base' % (_import_path, settings.DATABASE_ENGINE), {}, {}, ['']) except ImportError, e: - # The database backend wasn't found. Display a helpful error message - # listing all possible database backends. - from django.core.exceptions import ImproperlyConfigured - import os - backend_dir = os.path.join(__path__[0], 'backends') - 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() - if settings.DATABASE_ENGINE not in available_backends: - raise ImproperlyConfigured, "%r isn't an available database backend. Available options are: %s" % \ - (settings.DATABASE_ENGINE, ", ".join(map(repr, available_backends))) - else: - raise # If there's some other error, this must be an error in Django itself. + # If the import failed, we might be looking for a database backend + # distributed external to Django. So we'll try that next. + try: + _import_path = '' + backend = __import__('%s.base' % settings.DATABASE_ENGINE, {}, {}, ['']) + except ImportError, e_user: + # The database backend wasn't found. Display a helpful error message + # listing all possible (built-in) database backends. + backend_dir = os.path.join(__path__[0], 'backends') + 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() + if settings.DATABASE_ENGINE not in available_backends: + raise ImproperlyConfigured, "%r isn't an available database backend. Available options are: %s" % \ + (settings.DATABASE_ENGINE, ", ".join(map(repr, available_backends))) + else: + raise # If there's some other error, this must be an error in Django itself. -get_introspection_module = lambda: __import__('django.db.backends.%s.introspection' % settings.DATABASE_ENGINE, {}, {}, ['']) -get_creation_module = lambda: __import__('django.db.backends.%s.creation' % settings.DATABASE_ENGINE, {}, {}, ['']) -runshell = lambda: __import__('django.db.backends.%s.client' % settings.DATABASE_ENGINE, {}, {}, ['']).runshell() +def _import_database_module(import_path='', module_name=''): + """Lazyily import a database module when requested.""" + return __import__('%s%s.%s' % (_import_path, settings.DATABASE_ENGINE, module_name), {}, {}, ['']) +# We don't want to import the introspect/creation modules unless +# someone asks for 'em, so lazily load them on demmand. +get_introspection_module = curry(_import_database_module, _import_path, 'introspection') +get_creation_module = curry(_import_database_module, _import_path, 'creation') + +# We want runshell() to work the same way, but we have to treat it a +# little differently (since it just runs instead of returning a module like +# the above) and wrap the lazily-loaded runshell() method. +runshell = lambda: _import_database_module(_import_path, "client").runshell() + +# Convenient aliases for backend bits. connection = backend.DatabaseWrapper(**settings.DATABASE_OPTIONS) DatabaseError = backend.DatabaseError IntegrityError = backend.IntegrityError diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py index f3c6f59258..1b6ba07f24 100644 --- a/django/db/backends/__init__.py +++ b/django/db/backends/__init__.py @@ -56,7 +56,7 @@ class BaseDatabaseOperations(object): a backend performs ordering or calculates the ID of a recently-inserted row. """ - def autoinc_sql(self, table): + def autoinc_sql(self, table, column): """ Returns any SQL needed to support auto-incrementing primary keys, or None if no SQL is necessary. diff --git a/django/db/backends/ado_mssql/creation.py b/django/db/backends/ado_mssql/creation.py index 3aa13a31b4..08edc3ee26 100644 --- a/django/db/backends/ado_mssql/creation.py +++ b/django/db/backends/ado_mssql/creation.py @@ -6,10 +6,10 @@ DATA_TYPES = { 'DateField': 'smalldatetime', 'DateTimeField': 'smalldatetime', 'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)', - 'FileField': 'varchar(100)', - 'FilePathField': 'varchar(100)', + 'FileField': 'varchar(%(max_length)s)', + 'FilePathField': 'varchar(%(max_length)s)', 'FloatField': 'double precision', - 'ImageField': 'varchar(100)', + 'ImageField': 'varchar(%(max_length)s)', 'IntegerField': 'int', 'IPAddressField': 'char(15)', 'NullBooleanField': 'bit', diff --git a/django/db/backends/creation.py b/django/db/backends/creation.py new file mode 100644 index 0000000000..4071cef6aa --- /dev/null +++ b/django/db/backends/creation.py @@ -0,0 +1,7 @@ +class BaseCreation(object): + """ + This class encapsulates all backend-specific differences that pertain to + database *creation*, such as the column types to use for particular Django + Fields. + """ + pass diff --git a/django/db/backends/mysql/base.py b/django/db/backends/mysql/base.py index f913b88709..f729629751 100644 --- a/django/db/backends/mysql/base.py +++ b/django/db/backends/mysql/base.py @@ -24,6 +24,12 @@ from MySQLdb.constants import FIELD_TYPE import types import re +# Raise exceptions for database warnings if DEBUG is on +from django.conf import settings +if settings.DEBUG: + from warnings import filterwarnings + filterwarnings("error", category=Database.Warning) + DatabaseError = Database.DatabaseError IntegrityError = Database.IntegrityError @@ -153,7 +159,6 @@ class DatabaseWrapper(BaseDatabaseWrapper): return False def _cursor(self, settings): - from warnings import filterwarnings if not self._valid_connection(): kwargs = { 'conv': django_conversions, @@ -175,8 +180,6 @@ class DatabaseWrapper(BaseDatabaseWrapper): kwargs.update(self.options) self.connection = Database.connect(**kwargs) cursor = self.connection.cursor() - if settings.DEBUG: - filterwarnings("error", category=Database.Warning) return cursor def _rollback(self): diff --git a/django/db/backends/mysql/creation.py b/django/db/backends/mysql/creation.py index e63ca09c35..17da00bd36 100644 --- a/django/db/backends/mysql/creation.py +++ b/django/db/backends/mysql/creation.py @@ -10,10 +10,10 @@ DATA_TYPES = { 'DateField': 'date', 'DateTimeField': 'datetime', 'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)', - 'FileField': 'varchar(100)', - 'FilePathField': 'varchar(100)', + 'FileField': 'varchar(%(max_length)s)', + 'FilePathField': 'varchar(%(max_length)s)', 'FloatField': 'double precision', - 'ImageField': 'varchar(100)', + 'ImageField': 'varchar(%(max_length)s)', 'IntegerField': 'integer', 'IPAddressField': 'char(15)', 'NullBooleanField': 'bool', diff --git a/django/db/backends/mysql_old/creation.py b/django/db/backends/mysql_old/creation.py index b2b3992651..efb351c07e 100644 --- a/django/db/backends/mysql_old/creation.py +++ b/django/db/backends/mysql_old/creation.py @@ -10,10 +10,10 @@ DATA_TYPES = { 'DateField': 'date', 'DateTimeField': 'datetime', 'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)', - 'FileField': 'varchar(100)', - 'FilePathField': 'varchar(100)', + 'FileField': 'varchar(%(max_length)s)', + 'FilePathField': 'varchar(%(max_length)s)', 'FloatField': 'double precision', - 'ImageField': 'varchar(100)', + 'ImageField': 'varchar(%(max_length)s)', 'IntegerField': 'integer', 'IPAddressField': 'char(15)', 'NullBooleanField': 'bool', diff --git a/django/db/backends/oracle/base.py b/django/db/backends/oracle/base.py index 23ce30f37e..496fc26306 100644 --- a/django/db/backends/oracle/base.py +++ b/django/db/backends/oracle/base.py @@ -31,20 +31,23 @@ class DatabaseFeatures(BaseDatabaseFeatures): uses_custom_queryset = True class DatabaseOperations(BaseDatabaseOperations): - def autoinc_sql(self, table): + def autoinc_sql(self, table, column): # To simulate auto-incrementing primary keys in Oracle, we have to # create a sequence and a trigger. sq_name = get_sequence_name(table) tr_name = get_trigger_name(table) + tbl_name = self.quote_name(table) + col_name = self.quote_name(column) sequence_sql = 'CREATE SEQUENCE %s;' % sq_name trigger_sql = """ - CREATE OR REPLACE TRIGGER %s - BEFORE INSERT ON %s + CREATE OR REPLACE TRIGGER %(tr_name)s + BEFORE INSERT ON %(tbl_name)s FOR EACH ROW - WHEN (new.id IS NULL) + WHEN (new.%(col_name)s IS NULL) BEGIN - SELECT %s.nextval INTO :new.id FROM dual; - END;/""" % (tr_name, self.quote_name(table), sq_name) + SELECT %(sq_name)s.nextval + INTO :new.%(col_name)s FROM dual; + END;/""" % locals() return sequence_sql, trigger_sql def date_extract_sql(self, lookup_type, field_name): @@ -287,7 +290,7 @@ class DatabaseOperations(BaseDatabaseOperations): # string instead of null, but only if the field accepts the # empty string. if value is None and isinstance(field, Field) and field.empty_strings_allowed: - value = '' + value = u'' # Convert 1 or 0 to True or False elif value in (1, 0) and isinstance(field, (BooleanField, NullBooleanField)): value = bool(value) @@ -351,7 +354,10 @@ class DatabaseOperations(BaseDatabaseOperations): for sequence_info in sequences: table_name = sequence_info['table'] seq_name = get_sequence_name(table_name) - query = _get_sequence_reset_sql() % {'sequence': seq_name, 'table': self.quote_name(table_name)} + column_name = self.quote_name(sequence_info['column'] or 'id') + query = _get_sequence_reset_sql() % {'sequence': seq_name, + 'table': self.quote_name(table_name), + 'column': column_name} sql.append(query) return sql else: @@ -365,13 +371,16 @@ class DatabaseOperations(BaseDatabaseOperations): for f in model._meta.fields: if isinstance(f, models.AutoField): sequence_name = get_sequence_name(model._meta.db_table) - output.append(query % {'sequence':sequence_name, - 'table':model._meta.db_table}) + column_name = self.quote_name(f.db_column or f.name) + output.append(query % {'sequence': sequence_name, + 'table': model._meta.db_table, + 'column': column_name}) break # Only one AutoField is allowed per model, so don't bother continuing. for f in model._meta.many_to_many: sequence_name = get_sequence_name(f.m2m_db_table()) - output.append(query % {'sequence':sequence_name, - 'table':f.m2m_db_table()}) + output.append(query % {'sequence': sequence_name, + 'table': f.m2m_db_table(), + 'column': self.quote_name('id')}) return output def start_transaction_sql(self): @@ -397,6 +406,7 @@ class DatabaseWrapper(BaseDatabaseWrapper): 'istartswith': "LIKE UPPER(%s) ESCAPE '\\'", 'iendswith': "LIKE UPPER(%s) ESCAPE '\\'", } + oracle_version = None def _valid_connection(self): return self.connection is not None @@ -411,6 +421,10 @@ class DatabaseWrapper(BaseDatabaseWrapper): else: conn_string = "%s/%s@%s" % (settings.DATABASE_USER, settings.DATABASE_PASSWORD, settings.DATABASE_NAME) self.connection = Database.connect(conn_string, **self.options) + try: + self.oracle_version = int(self.connection.version.split('.')[0]) + except ValueError: + pass cursor = FormatStylePlaceholderCursor(self.connection) # Default arraysize of 1 is highly sub-optimal. cursor.arraysize = 100 @@ -430,21 +444,6 @@ class FormatStylePlaceholderCursor(Database.Cursor): """ charset = 'utf-8' - def _rewrite_args(self, query, params=None): - if params is None: - params = [] - else: - params = self._format_params(params) - args = [(':arg%d' % i) for i in range(len(params))] - query = smart_str(query, self.charset) % tuple(args) - # cx_Oracle wants no trailing ';' for SQL statements. For PL/SQL, it - # it does want a trailing ';' but not a trailing '/'. However, these - # characters must be included in the original query in case the query - # is being passed to SQL*Plus. - if query.endswith(';') or query.endswith('/'): - query = query[:-1] - return query, params - def _format_params(self, params): if isinstance(params, dict): result = {} @@ -456,12 +455,35 @@ class FormatStylePlaceholderCursor(Database.Cursor): return tuple([smart_str(p, self.charset, True) for p in params]) def execute(self, query, params=None): - query, params = self._rewrite_args(query, params) + if params is None: + params = [] + else: + params = self._format_params(params) + args = [(':arg%d' % i) for i in range(len(params))] + # cx_Oracle wants no trailing ';' for SQL statements. For PL/SQL, it + # it does want a trailing ';' but not a trailing '/'. However, these + # characters must be included in the original query in case the query + # is being passed to SQL*Plus. + if query.endswith(';') or query.endswith('/'): + query = query[:-1] + query = smart_str(query, self.charset) % tuple(args) return Database.Cursor.execute(self, query, params) def executemany(self, query, params=None): - query, params = self._rewrite_args(query, params) - return Database.Cursor.executemany(self, query, params) + try: + args = [(':arg%d' % i) for i in range(len(params[0]))] + except (IndexError, TypeError): + # No params given, nothing to do + return None + # cx_Oracle wants no trailing ';' for SQL statements. For PL/SQL, it + # it does want a trailing ';' but not a trailing '/'. However, these + # characters must be included in the original query in case the query + # is being passed to SQL*Plus. + if query.endswith(';') or query.endswith('/'): + query = query[:-1] + query = smart_str(query, self.charset) % tuple(args) + new_param_list = [self._format_params(i) for i in params] + return Database.Cursor.executemany(self, query, new_param_list) def fetchone(self): return to_unicode(Database.Cursor.fetchone(self)) @@ -491,7 +513,7 @@ def _get_sequence_reset_sql(): cval integer; BEGIN LOCK TABLE %(table)s IN SHARE MODE; - SELECT NVL(MAX(id), 0) INTO startvalue FROM %(table)s; + SELECT NVL(MAX(%(column)s), 0) INTO startvalue FROM %(table)s; SELECT %(sequence)s.nextval INTO cval FROM dual; cval := startvalue - cval; IF cval != 0 THEN diff --git a/django/db/backends/oracle/creation.py b/django/db/backends/oracle/creation.py index af8ac58792..93dc3c2bf1 100644 --- a/django/db/backends/oracle/creation.py +++ b/django/db/backends/oracle/creation.py @@ -13,10 +13,10 @@ DATA_TYPES = { 'DateField': 'DATE', 'DateTimeField': 'TIMESTAMP', 'DecimalField': 'NUMBER(%(max_digits)s, %(decimal_places)s)', - 'FileField': 'NVARCHAR2(100)', - 'FilePathField': 'NVARCHAR2(100)', + 'FileField': 'NVARCHAR2(%(max_length)s)', + 'FilePathField': 'NVARCHAR2(%(max_length)s)', 'FloatField': 'DOUBLE PRECISION', - 'ImageField': 'NVARCHAR2(100)', + 'ImageField': 'NVARCHAR2(%(max_length)s)', 'IntegerField': 'NUMBER(11)', 'IPAddressField': 'VARCHAR2(15)', 'NullBooleanField': 'NUMBER(1) CHECK ((%(column)s IN (0,1)) OR (%(column)s IS NULL))', @@ -28,7 +28,7 @@ DATA_TYPES = { 'SmallIntegerField': 'NUMBER(11)', 'TextField': 'NCLOB', 'TimeField': 'TIMESTAMP', - 'URLField': 'VARCHAR2(200)', + 'URLField': 'VARCHAR2(%(max_length)s)', 'USStateField': 'CHAR(2)', 'NoField': None, } diff --git a/django/db/backends/postgresql/creation.py b/django/db/backends/postgresql/creation.py index 7dae852a21..6d4087a459 100644 --- a/django/db/backends/postgresql/creation.py +++ b/django/db/backends/postgresql/creation.py @@ -10,10 +10,10 @@ DATA_TYPES = { 'DateField': 'date', 'DateTimeField': 'timestamp with time zone', 'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)', - 'FileField': 'varchar(100)', - 'FilePathField': 'varchar(100)', + 'FileField': 'varchar(%(max_length)s)', + 'FilePathField': 'varchar(%(max_length)s)', 'FloatField': 'double precision', - 'ImageField': 'varchar(100)', + 'ImageField': 'varchar(%(max_length)s)', 'IntegerField': 'integer', 'IPAddressField': 'inet', 'NullBooleanField': 'boolean', diff --git a/django/db/backends/sqlite3/base.py b/django/db/backends/sqlite3/base.py index 7919e1cc50..b4b445cd16 100644 --- a/django/db/backends/sqlite3/base.py +++ b/django/db/backends/sqlite3/base.py @@ -1,5 +1,9 @@ """ -SQLite3 backend for django. Requires pysqlite2 (http://pysqlite.org/). +SQLite3 backend for django. + +Python 2.3 and 2.4 require pysqlite2 (http://pysqlite.org/). + +Python 2.5 and later use the sqlite3 module in the standard library. """ from django.db.backends import BaseDatabaseWrapper, BaseDatabaseFeatures, BaseDatabaseOperations, util @@ -129,8 +133,12 @@ class SQLiteCursorWrapper(Database.Cursor): return Database.Cursor.execute(self, query, params) def executemany(self, query, param_list): - query = self.convert_query(query, len(param_list[0])) - return Database.Cursor.executemany(self, query, param_list) + try: + query = self.convert_query(query, len(param_list[0])) + return Database.Cursor.executemany(self, query, param_list) + except (IndexError,TypeError): + # No parameter list provided + return None def convert_query(self, query, num_params): return query % tuple("?" * num_params) diff --git a/django/db/backends/sqlite3/creation.py b/django/db/backends/sqlite3/creation.py index 764f56b422..48867f7636 100644 --- a/django/db/backends/sqlite3/creation.py +++ b/django/db/backends/sqlite3/creation.py @@ -9,10 +9,10 @@ DATA_TYPES = { 'DateField': 'date', 'DateTimeField': 'datetime', 'DecimalField': 'decimal', - 'FileField': 'varchar(100)', - 'FilePathField': 'varchar(100)', + 'FileField': 'varchar(%(max_length)s)', + 'FilePathField': 'varchar(%(max_length)s)', 'FloatField': 'real', - 'ImageField': 'varchar(100)', + 'ImageField': 'varchar(%(max_length)s)', 'IntegerField': 'integer', 'IPAddressField': 'char(15)', 'NullBooleanField': 'bool', diff --git a/django/db/models/base.py b/django/db/models/base.py index 72ea3e97a3..38ac45b042 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -12,7 +12,7 @@ from django.db.models.loading import register_models, get_model from django.dispatch import dispatcher from django.utils.datastructures import SortedDict from django.utils.functional import curry -from django.utils.encoding import smart_str, force_unicode +from django.utils.encoding import smart_str, force_unicode, smart_unicode from django.conf import settings from itertools import izip import types @@ -83,6 +83,11 @@ class Model(object): def _get_pk_val(self): return getattr(self, self._meta.pk.attname) + def _set_pk_val(self, value): + return setattr(self, self._meta.pk.attname, value) + + pk = property(_get_pk_val, _set_pk_val) + def __repr__(self): return smart_str(u'<%s: %s>' % (self.__class__.__name__, unicode(self))) @@ -213,7 +218,7 @@ class Model(object): pk_val = self._get_pk_val() # Note: the comparison with '' is required for compatibility with # oldforms-style model creation. - pk_set = pk_val is not None and pk_val != u'' + pk_set = pk_val is not None and smart_unicode(pk_val) != u'' record_exists = True if pk_set: # Determine whether a record with the primary key already exists. @@ -242,10 +247,13 @@ class Model(object): placeholders += [f.get_placeholder(f.pre_save(self, True)) for f in self._meta.fields if isinstance(f, AutoField)] if self._meta.order_with_respect_to: field_names.append(qn('_order')) - # TODO: This assumes the database supports subqueries. - placeholders.append('(SELECT COUNT(*) FROM %s WHERE %s = %%s)' % \ - (qn(self._meta.db_table), qn(self._meta.order_with_respect_to.column))) - db_values.append(getattr(self, self._meta.order_with_respect_to.attname)) + placeholders.append('%s') + subsel = 'SELECT COUNT(*) FROM %s WHERE %s = %%s' % ( + qn(self._meta.db_table), + qn(self._meta.order_with_respect_to.column)) + cursor.execute(subsel, (getattr(self, self._meta.order_with_respect_to.attname),)) + db_values.append(cursor.fetchone()[0]) + record_exists = False if db_values: cursor.execute("INSERT INTO %s (%s) VALUES (%s)" % \ (qn(self._meta.db_table), ','.join(field_names), @@ -260,7 +268,8 @@ class Model(object): transaction.commit_unless_managed() # Run any post-save hooks. - dispatcher.send(signal=signals.post_save, sender=self.__class__, instance=self) + dispatcher.send(signal=signals.post_save, sender=self.__class__, + instance=self, created=(not record_exists)) save.alters_data = True diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index 27a704d343..4766f97199 100644 --- a/django/db/models/fields/__init__.py +++ b/django/db/models/fields/__init__.py @@ -1,3 +1,11 @@ +import datetime +import os +import time +try: + import decimal +except ImportError: + from django.utils import _decimal as decimal # for Python 2.3 + from django.db import get_creation_module from django.db.models import signals from django.dispatch import dispatcher @@ -12,11 +20,6 @@ from django.utils.text import capfirst from django.utils.translation import ugettext_lazy, ugettext as _ from django.utils.encoding import smart_unicode, force_unicode, smart_str from django.utils.maxlength import LegacyMaxlength -import datetime, os, time -try: - import decimal -except ImportError: - from django.utils import _decimal as decimal # for Python 2.3 class NOT_PROVIDED: pass @@ -386,7 +389,7 @@ class Field(object): def save_form_data(self, instance, data): setattr(instance, self.name, data) - + def formfield(self, form_class=forms.CharField, **kwargs): "Returns a django.newforms.Field instance for this database Field." defaults = {'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text} @@ -434,6 +437,7 @@ class AutoField(Field): assert not cls._meta.has_auto_field, "A model can't have more than one AutoField." super(AutoField, self).contribute_to_class(cls, name) cls._meta.has_auto_field = True + cls._meta.auto_field = self def formfield(self, **kwargs): return None @@ -539,7 +543,12 @@ class DateField(Field): def get_db_prep_save(self, value): # Casts dates into string format for entry into database. if value is not None: - value = value.strftime('%Y-%m-%d') + try: + value = value.strftime('%Y-%m-%d') + except AttributeError: + # If value is already a string it won't have a strftime method, + # so we'll just let it pass through. + pass return Field.get_db_prep_save(self, value) def get_manipulator_field_objs(self): @@ -681,7 +690,7 @@ class DecimalField(Field): class EmailField(CharField): def __init__(self, *args, **kwargs): - kwargs['max_length'] = 75 + kwargs['max_length'] = kwargs.get('max_length', 75) CharField.__init__(self, *args, **kwargs) def get_internal_type(self): @@ -701,6 +710,7 @@ class EmailField(CharField): class FileField(Field): def __init__(self, verbose_name=None, name=None, upload_to='', **kwargs): self.upload_to = upload_to + kwargs['max_length'] = kwargs.get('max_length', 100) Field.__init__(self, verbose_name, name, **kwargs) def get_db_prep_save(self, value): @@ -789,10 +799,10 @@ class FileField(Field): def save_form_data(self, instance, data): if data: getattr(instance, "save_%s_file" % self.name)(data.filename, data.content, save=False) - + def formfield(self, **kwargs): defaults = {'form_class': forms.FileField} - # If a file has been provided previously, then the form doesn't require + # If a file has been provided previously, then the form doesn't require # that a new file is provided this time. if 'initial' in kwargs: defaults['required'] = False @@ -802,6 +812,7 @@ class FileField(Field): class FilePathField(Field): def __init__(self, verbose_name=None, name=None, path='', match=None, recursive=False, **kwargs): self.path, self.match, self.recursive = path, match, recursive + kwargs['max_length'] = kwargs.get('max_length', 100) Field.__init__(self, verbose_name, name, **kwargs) def get_manipulator_field_objs(self): @@ -849,6 +860,7 @@ class ImageField(FileField): def formfield(self, **kwargs): defaults = {'form_class': forms.ImageField} + defaults.update(kwargs) return super(ImageField, self).formfield(**defaults) class IntegerField(Field): @@ -873,6 +885,11 @@ class IPAddressField(Field): def validate(self, field_data, all_data): validators.isValidIPAddress4(field_data, None) + def formfield(self, **kwargs): + defaults = {'form_class': forms.IPAddressField} + defaults.update(kwargs) + return super(IPAddressField, self).formfield(**defaults) + class NullBooleanField(Field): empty_strings_allowed = False def __init__(self, *args, **kwargs): @@ -905,22 +922,29 @@ class PhoneNumberField(IntegerField): class PositiveIntegerField(IntegerField): def get_manipulator_field_objs(self): return [oldforms.PositiveIntegerField] + + def formfield(self, **kwargs): + defaults = {'min_value': 0} + defaults.update(kwargs) + return super(PositiveIntegerField, self).formfield(**defaults) class PositiveSmallIntegerField(IntegerField): def get_manipulator_field_objs(self): return [oldforms.PositiveSmallIntegerField] -class SlugField(Field): + def formfield(self, **kwargs): + defaults = {'min_value': 0} + defaults.update(kwargs) + return super(PositiveSmallIntegerField, self).formfield(**defaults) + +class SlugField(CharField): def __init__(self, *args, **kwargs): kwargs['max_length'] = kwargs.get('max_length', 50) kwargs.setdefault('validator_list', []).append(validators.isSlug) # Set db_index=True unless it's been set manually. if 'db_index' not in kwargs: kwargs['db_index'] = True - Field.__init__(self, *args, **kwargs) - - def get_manipulator_field_objs(self): - return [oldforms.TextField] + super(SlugField, self).__init__(*args, **kwargs) class SmallIntegerField(IntegerField): def get_manipulator_field_objs(self): diff --git a/django/db/models/loading.py b/django/db/models/loading.py index 090390aa9e..e7d134e6da 100644 --- a/django/db/models/loading.py +++ b/django/db/models/loading.py @@ -52,11 +52,7 @@ class AppCache(object): for app_name in settings.INSTALLED_APPS: if app_name in self.handled: continue - try: - self.load_app(app_name, True) - except Exception, e: - # Problem importing the app - self.app_errors[app_name] = e + self.load_app(app_name, True) if not self.nesting_level: for app_name in self.postponed: self.load_app(app_name) diff --git a/django/db/models/manager.py b/django/db/models/manager.py index 040b86656a..7b2e916738 100644 --- a/django/db/models/manager.py +++ b/django/db/models/manager.py @@ -111,3 +111,7 @@ class ManagerDescriptor(object): if instance != None: raise AttributeError, "Manager isn't accessible via %s instances" % type.__name__ return self.manager + +class EmptyManager(Manager): + def get_query_set(self): + return self.get_empty_query_set() diff --git a/django/db/models/manipulators.py b/django/db/models/manipulators.py index c3e5292198..e0085d13ff 100644 --- a/django/db/models/manipulators.py +++ b/django/db/models/manipulators.py @@ -9,7 +9,6 @@ from django.utils.datastructures import DotExpandedDict from django.utils.text import capfirst from django.utils.encoding import smart_str from django.utils.translation import ugettext as _ -import types def add_manipulators(sender): cls = sender @@ -38,7 +37,7 @@ class ManipulatorDescriptor(object): bases = [self.base] if hasattr(model, 'Manipulator'): bases = [model.Manipulator] + bases - self.man = types.ClassType(self.name, tuple(bases), {}) + self.man = type(self.name, tuple(bases), {}) self.man._prepare(model) return self.man diff --git a/django/db/models/options.py b/django/db/models/options.py index ad813ae0f7..788d1c80de 100644 --- a/django/db/models/options.py +++ b/django/db/models/options.py @@ -33,7 +33,7 @@ class Options(object): self.admin = None self.meta = meta self.pk = None - self.has_auto_field = False + self.has_auto_field, self.auto_field = False, None self.one_to_one_field = None self.parents = [] @@ -52,9 +52,19 @@ class Options(object): del meta_attrs['__doc__'] for attr_name in DEFAULT_NAMES: setattr(self, attr_name, meta_attrs.pop(attr_name, getattr(self, attr_name))) + + # unique_together can be either a tuple of tuples, or a single + # tuple of two strings. Normalize it to a tuple of tuples, so that + # calling code can uniformly expect that. + ut = meta_attrs.pop('unique_together', getattr(self, 'unique_together')) + if ut and not isinstance(ut[0], (tuple, list)): + ut = (ut,) + setattr(self, 'unique_together', ut) + # verbose_name_plural is a special case because it uses a 's' # by default. setattr(self, 'verbose_name_plural', meta_attrs.pop('verbose_name_plural', string_concat(self.verbose_name, 's'))) + # Any leftover attributes must be invalid. if meta_attrs != {}: raise TypeError, "'class Meta' got invalid attribute(s): %s" % ','.join(meta_attrs.keys()) diff --git a/django/db/models/query.py b/django/db/models/query.py index a750ef5550..23d0bac6c8 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -816,6 +816,9 @@ def get_where_clause(lookup_type, table_prefix, field_name, value, db_type): return connection.ops.fulltext_search_sql(field_sql) elif lookup_type in ('regex', 'iregex'): if settings.DATABASE_ENGINE == 'oracle': + if connection.oracle_version and connection.oracle_version <= 9: + msg = "Regexes are not supported in Oracle before version 10g." + raise NotImplementedError(msg) if lookup_type == 'regex': match_option = 'c' else: diff --git a/django/http/__init__.py b/django/http/__init__.py index 7cd47481dc..9a47e70592 100644 --- a/django/http/__init__.py +++ b/django/http/__init__.py @@ -2,6 +2,7 @@ import os from Cookie import SimpleCookie from pprint import pformat from urllib import urlencode +from urlparse import urljoin from django.utils.datastructures import MultiValueDict, FileDict from django.utils.encoding import smart_str, iri_to_uri, force_unicode @@ -41,9 +42,39 @@ class HttpRequest(object): def has_key(self, key): return key in self.GET or key in self.POST + __contains__ = has_key + + def get_host(self): + "Returns the HTTP host using the environment or request headers." + # We try three options, in order of decreasing preference. + host = self.META.get('HTTP_X_FORWARDED_HOST', '') + if 'HTTP_HOST' in self.META: + host = self.META['HTTP_HOST'] + else: + # Reconstruct the host using the algorithm from PEP 333. + host = self.META['SERVER_NAME'] + server_port = self.META['SERVER_PORT'] + if server_port != (self.is_secure() and 443 or 80): + host = '%s:%s' % (host, server_port) + return host + def get_full_path(self): return '' + def build_absolute_uri(self, location=None): + """ + Builds an absolute URI from the location and the variables available in + this request. If no location is specified, the absolute URI is built on + ``request.get_full_path()``. + """ + if not location: + location = self.get_full_path() + if not ':' in location: + current_uri = '%s://%s%s' % (self.is_secure() and 'https' or 'http', + self.get_host(), self.path) + location = urljoin(current_uri, location) + return location + def is_secure(self): return os.environ.get("HTTPS") == "on" @@ -229,7 +260,7 @@ class HttpResponse(object): else: self._container = [content] self._is_string = True - self.headers = {'Content-Type': content_type} + self._headers = {'content-type': content_type} self.cookies = SimpleCookie() if status: self.status_code = status @@ -237,28 +268,32 @@ class HttpResponse(object): def __str__(self): "Full HTTP message, including headers" return '\n'.join(['%s: %s' % (key, value) - for key, value in self.headers.items()]) \ + for key, value in self._headers.items()]) \ + '\n\n' + self.content def __setitem__(self, header, value): - self.headers[header] = value + self._headers[header.lower()] = value def __delitem__(self, header): try: - del self.headers[header] + del self._headers[header.lower()] except KeyError: pass def __getitem__(self, header): - return self.headers[header] + return self._headers[header.lower()] def has_header(self, header): "Case-insensitive check for a header" - header = header.lower() - for key in self.headers.keys(): - if key.lower() == header: - return True - return False + return self._headers.has_key(header.lower()) + + __contains__ = has_header + + def items(self): + return self._headers.items() + + def get(self, header, alternate): + return self._headers.get(header, alternate) def set_cookie(self, key, value='', max_age=None, expires=None, path='/', domain=None, secure=None): self.cookies[key] = value @@ -287,7 +322,7 @@ class HttpResponse(object): content = property(_get_content, _set_content) def __iter__(self): - self._iterator = self._container.__iter__() + self._iterator = iter(self._container) return self def next(self): @@ -360,12 +395,9 @@ class HttpResponseServerError(HttpResponse): def __init__(self, *args, **kwargs): HttpResponse.__init__(self, *args, **kwargs) +# A backwards compatible alias for HttpRequest.get_host. def get_host(request): - "Gets the HTTP host from the environment or request headers." - host = request.META.get('HTTP_X_FORWARDED_HOST', '') - if not host: - host = request.META.get('HTTP_HOST', '') - return host + return request.get_host() # It's neither necessary nor appropriate to use # django.utils.encoding.smart_unicode for parsing URLs and form inputs. Thus, diff --git a/django/middleware/common.py b/django/middleware/common.py index e18ec079af..57af4eb481 100644 --- a/django/middleware/common.py +++ b/django/middleware/common.py @@ -32,7 +32,7 @@ class CommonMiddleware(object): return http.HttpResponseForbidden('<h1>Forbidden</h1>') # Check for a redirect based on settings.APPEND_SLASH and settings.PREPEND_WWW - host = http.get_host(request) + host = request.get_host() old_url = [host, request.path] new_url = old_url[:] if settings.PREPEND_WWW and old_url[0] and not old_url[0].startswith('www.'): @@ -61,7 +61,7 @@ class CommonMiddleware(object): if settings.SEND_BROKEN_LINK_EMAILS: # If the referrer was from an internal link or a non-search-engine site, # send a note to the managers. - domain = http.get_host(request) + domain = request.get_host() referer = request.META.get('HTTP_REFERER', None) is_internal = _is_internal_request(domain, referer) path = request.get_full_path() diff --git a/django/middleware/gzip.py b/django/middleware/gzip.py index 9b2a5f3d22..7fd0d82419 100644 --- a/django/middleware/gzip.py +++ b/django/middleware/gzip.py @@ -20,7 +20,7 @@ class GZipMiddleware(object): # Avoid gzipping if we've already got a content-encoding or if the # content-type is Javascript (silly IE...) - is_js = "javascript" in response.headers.get('Content-Type', '').lower() + is_js = "javascript" in response.get('Content-Type', '').lower() if response.has_header('Content-Encoding') or is_js: return response diff --git a/django/middleware/http.py b/django/middleware/http.py index 8db3e4a524..78e066c67b 100644 --- a/django/middleware/http.py +++ b/django/middleware/http.py @@ -55,6 +55,7 @@ class SetRemoteAddrFromForwardedFor(object): return None else: # HTTP_X_FORWARDED_FOR can be a comma-separated list of IPs. - # Take just the first one. - real_ip = real_ip.split(",")[0] + # Take just the last one. + # See http://bob.pythonmac.org/archives/2005/09/23/apache-x-forwarded-for-caveat/ + real_ip = real_ip.split(",")[-1].strip() request.META['REMOTE_ADDR'] = real_ip diff --git a/django/newforms/fields.py b/django/newforms/fields.py index bb8a3dc582..a39987e1b5 100644 --- a/django/newforms/fields.py +++ b/django/newforms/fields.py @@ -2,6 +2,7 @@ Field classes """ +import copy import datetime import re import time @@ -25,7 +26,7 @@ __all__ = ( 'RegexField', 'EmailField', 'FileField', 'ImageField', 'URLField', 'BooleanField', 'ChoiceField', 'NullBooleanField', 'MultipleChoiceField', 'ComboField', 'MultiValueField', 'FloatField', 'DecimalField', - 'SplitDateTimeField', + 'SplitDateTimeField', 'IPAddressField', ) # These values, if given to to_python(), will trigger the self.required check. @@ -100,6 +101,12 @@ class Field(object): """ return {} + def __deepcopy__(self, memo): + result = copy.copy(self) + memo[id(self)] = result + result.widget = copy.deepcopy(self.widget, memo) + return result + class CharField(Field): def __init__(self, max_length=None, min_length=None, *args, **kwargs): self.max_length, self.min_length = max_length, min_length @@ -137,7 +144,7 @@ class IntegerField(Field): if value in EMPTY_VALUES: return None try: - value = int(value) + value = int(str(value)) except (ValueError, TypeError): raise ValidationError(ugettext(u'Enter a whole number.')) if self.max_value is not None and value > self.max_value: @@ -185,12 +192,12 @@ class DecimalField(Field): super(DecimalField, self).clean(value) if not self.required and value in EMPTY_VALUES: return None - value = value.strip() + value = str(value).strip() try: value = Decimal(value) except DecimalException: raise ValidationError(ugettext('Enter a number.')) - pieces = str(value).split('.') + pieces = str(value).lstrip("-").split('.') decimals = (len(pieces) == 2) and len(pieces[1]) or 0 digits = len(pieces[0]) if self.max_value is not None and value > self.max_value: @@ -335,12 +342,6 @@ class EmailField(RegexField): RegexField.__init__(self, email_re, max_length, min_length, ugettext(u'Enter a valid e-mail address.'), *args, **kwargs) -url_re = re.compile( - r'^https?://' # http:// or https:// - r'(?:[A-Z0-9-]+\.)+[A-Z]{2,6}' # domain - r'(?::\d+)?' # optional port - r'(?:/?|/\S+)$', re.IGNORECASE) - try: from django.conf import settings URL_VALIDATOR_USER_AGENT = settings.URL_VALIDATOR_USER_AGENT @@ -353,7 +354,7 @@ class UploadedFile(StrAndUnicode): def __init__(self, filename, content): self.filename = filename self.content = content - + def __unicode__(self): """ The unicode representation is the filename, so that the pre-database-insertion @@ -392,11 +393,26 @@ class ImageField(FileField): from PIL import Image from cStringIO import StringIO try: - Image.open(StringIO(f.content)) - except IOError: # Python Imaging Library doesn't recognize it as an image + # load() is the only method that can spot a truncated JPEG, + # but it cannot be called sanely after verify() + trial_image = Image.open(StringIO(f.content)) + trial_image.load() + # verify() is the only method that can spot a corrupt PNG, + # but it must be called immediately after the constructor + trial_image = Image.open(StringIO(f.content)) + trial_image.verify() + except Exception: # Python Imaging Library doesn't recognize it as an image raise ValidationError(ugettext(u"Upload a valid image. The file you uploaded was either not an image or a corrupted image.")) return f - + +url_re = re.compile( + r'^https?://' # http:// or https:// + r'(?:(?:[A-Z0-9-]+\.)+[A-Z]{2,6}|' #domain... + r'localhost|' #localhost... + r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip + r'(?::\d+)?' # optional port + r'(?:/?|/\S+)$', re.IGNORECASE) + class URLField(RegexField): def __init__(self, max_length=None, min_length=None, verify_exists=False, validator_user_agent=URL_VALIDATOR_USER_AGENT, *args, **kwargs): @@ -405,6 +421,9 @@ class URLField(RegexField): self.user_agent = validator_user_agent def clean(self, value): + # If no URL scheme given, assume http:// + if value and '://' not in value: + value = u'http://%s' % value value = super(URLField, self).clean(value) if value == u'': return value @@ -433,6 +452,10 @@ class BooleanField(Field): def clean(self, value): "Returns a Python boolean object." super(BooleanField, self).clean(value) + # Explicitly check for the string '0', which is what as hidden field + # will submit for False. + if value == '0': + return False return bool(value) class NullBooleanField(BooleanField): @@ -526,7 +549,7 @@ class ComboField(Field): class MultiValueField(Field): """ A Field that aggregates the logic of multiple Fields. - + Its clean() method takes a "decompressed" list of values, which are then cleaned into a single value according to self.fields. Each value in this list is cleaned by the corresponding field -- the first value is @@ -612,3 +635,11 @@ class SplitDateTimeField(MultiValueField): raise ValidationError(ugettext(u'Enter a valid time.')) return datetime.datetime.combine(*data_list) return None + +ipv4_re = re.compile(r'^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$') + +class IPAddressField(RegexField): + def __init__(self, *args, **kwargs): + RegexField.__init__(self, ipv4_re, + error_message=ugettext(u'Enter a valid IPv4 address.'), + *args, **kwargs) diff --git a/django/newforms/forms.py b/django/newforms/forms.py index 906978c86f..3196db339e 100644 --- a/django/newforms/forms.py +++ b/django/newforms/forms.py @@ -31,7 +31,7 @@ class SortedDictFromList(SortedDict): dict.__init__(self, dict(data)) def copy(self): - return SortedDictFromList([(k, copy.copy(v)) for k, v in self.items()]) + return SortedDictFromList([(k, copy.deepcopy(v)) for k, v in self.items()]) class DeclarativeFieldsMetaclass(type): """ @@ -57,13 +57,16 @@ class BaseForm(StrAndUnicode): # class is different than Form. See the comments by the Form class for more # information. Any improvements to the form API should be made to *this* # class, not to the Form class. - def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, initial=None): + def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, + initial=None, error_class=ErrorList, label_suffix=':'): self.is_bound = data is not None or files is not None self.data = data or {} self.files = files or {} self.auto_id = auto_id self.prefix = prefix self.initial = initial or {} + self.error_class = error_class + self.label_suffix = label_suffix self._errors = None # Stores the errors after clean() has been called. # The base_fields class attribute is the *class-wide* definition of @@ -117,7 +120,7 @@ class BaseForm(StrAndUnicode): output, hidden_fields = [], [] for name, field in self.fields.items(): bf = BoundField(self, field, name) - bf_errors = ErrorList([escape(error) for error in bf.errors]) # Escape and cache in local variable. + bf_errors = self.error_class([escape(error) for error in bf.errors]) # Escape and cache in local variable. if bf.is_hidden: if bf_errors: top_errors.extend(['(Hidden field %s) %s' % (name, force_unicode(e)) for e in bf_errors]) @@ -127,9 +130,10 @@ class BaseForm(StrAndUnicode): output.append(error_row % force_unicode(bf_errors)) if bf.label: label = escape(force_unicode(bf.label)) - # Only add a colon if the label does not end in punctuation. - if label[-1] not in ':?.!': - label += ':' + # Only add the suffix if the label does not end in punctuation. + if self.label_suffix: + if label[-1] not in ':?.!': + label += self.label_suffix label = bf.label_tag(label) or '' else: label = '' @@ -168,7 +172,7 @@ class BaseForm(StrAndUnicode): field -- i.e., from Form.clean(). Returns an empty ErrorList if there are none. """ - return self.errors.get(NON_FIELD_ERRORS, ErrorList()) + return self.errors.get(NON_FIELD_ERRORS, self.error_class()) def full_clean(self): """ @@ -210,6 +214,16 @@ class BaseForm(StrAndUnicode): """ return self.cleaned_data + def is_multipart(self): + """ + Returns True if the form needs to be multipart-encrypted, i.e. it has + FileInput. Otherwise, False. + """ + for field in self.fields.values(): + if field.widget.needs_multipart_form: + return True + return False + class Form(BaseForm): "A collection of Fields, plus their associated data." # This is a separate class from BaseForm in order to abstract the way @@ -241,7 +255,7 @@ class BoundField(StrAndUnicode): Returns an ErrorList for this field. Returns an empty ErrorList if there are none. """ - return self.form.errors.get(self.name, ErrorList()) + return self.form.errors.get(self.name, self.form.error_class()) errors = property(_errors) def as_widget(self, widget=None, attrs=None): diff --git a/django/newforms/util.py b/django/newforms/util.py index 2bafc8d9c7..e19d894397 100644 --- a/django/newforms/util.py +++ b/django/newforms/util.py @@ -1,5 +1,6 @@ from django.utils.html import escape -from django.utils.encoding import smart_unicode, StrAndUnicode +from django.utils.encoding import smart_unicode, StrAndUnicode, force_unicode +from django.utils.functional import Promise def flatatt(attrs): """ @@ -21,10 +22,10 @@ class ErrorDict(dict, StrAndUnicode): def as_ul(self): if not self: return u'' - return u'<ul class="errorlist">%s</ul>' % ''.join([u'<li>%s%s</li>' % (k, smart_unicode(v)) for k, v in self.items()]) + return u'<ul class="errorlist">%s</ul>' % ''.join([u'<li>%s%s</li>' % (k, force_unicode(v)) for k, v in self.items()]) def as_text(self): - return u'\n'.join([u'* %s\n%s' % (k, u'\n'.join([u' * %s' % smart_unicode(i) for i in v])) for k, v in self.items()]) + return u'\n'.join([u'* %s\n%s' % (k, u'\n'.join([u' * %s' % force_unicode(i) for i in v])) for k, v in self.items()]) class ErrorList(list, StrAndUnicode): """ @@ -35,11 +36,11 @@ class ErrorList(list, StrAndUnicode): def as_ul(self): if not self: return u'' - return u'<ul class="errorlist">%s</ul>' % ''.join([u'<li>%s</li>' % smart_unicode(e) for e in self]) + return u'<ul class="errorlist">%s</ul>' % ''.join([u'<li>%s</li>' % force_unicode(e) for e in self]) def as_text(self): if not self: return u'' - return u'\n'.join([u'* %s' % smart_unicode(e) for e in self]) + return u'\n'.join([u'* %s' % force_unicode(e) for e in self]) class ValidationError(Exception): def __init__(self, message): @@ -47,7 +48,7 @@ class ValidationError(Exception): if isinstance(message, list): self.messages = ErrorList([smart_unicode(msg) for msg in message]) else: - assert isinstance(message, basestring), ("%s should be a basestring" % repr(message)) + assert isinstance(message, (basestring, Promise)), ("%s should be a basestring or lazy translation" % repr(message)) message = smart_unicode(message) self.messages = ErrorList([message]) @@ -57,3 +58,4 @@ class ValidationError(Exception): # AttributeError: ValidationError instance has no attribute 'args' # See http://www.python.org/doc/current/tut/node10.html#handling return repr(self.messages) + diff --git a/django/newforms/widgets.py b/django/newforms/widgets.py index f985124389..0e7752499e 100644 --- a/django/newforms/widgets.py +++ b/django/newforms/widgets.py @@ -24,6 +24,7 @@ __all__ = ( class Widget(object): is_hidden = False # Determines whether this corresponds to an <input type="hidden">. + needs_multipart_form = False # Determines does this widget need multipart-encrypted form def __init__(self, attrs=None): if attrs is not None: @@ -120,6 +121,7 @@ class MultipleHiddenInput(HiddenInput): class FileInput(Input): input_type = 'file' + needs_multipart_form = True def render(self, name, value, attrs=None): return super(FileInput, self).render(name, None, attrs=attrs) diff --git a/django/oldforms/__init__.py b/django/oldforms/__init__.py index 93cfa1d8fa..9bb90416c4 100644 --- a/django/oldforms/__init__.py +++ b/django/oldforms/__init__.py @@ -447,7 +447,7 @@ class LargeTextField(TextField): self.field_name, self.rows, self.cols, escape(data)) class HiddenField(FormField): - def __init__(self, field_name, is_required=False, validator_list=None): + def __init__(self, field_name, is_required=False, validator_list=None, max_length=None): if validator_list is None: validator_list = [] self.field_name, self.is_required = field_name, is_required self.validator_list = validator_list[:] @@ -674,7 +674,7 @@ class CheckboxSelectMultipleField(SelectMultipleField): #################### class FileUploadField(FormField): - def __init__(self, field_name, is_required=False, validator_list=None): + def __init__(self, field_name, is_required=False, validator_list=None, max_length=None): if validator_list is None: validator_list = [] self.field_name, self.is_required = field_name, is_required self.validator_list = [self.isNonEmptyFile] + validator_list @@ -946,7 +946,7 @@ class IPAddressField(TextField): class FilePathField(SelectField): "A SelectField whose choices are the files in a given directory." - def __init__(self, field_name, path, match=None, recursive=False, is_required=False, validator_list=None): + def __init__(self, field_name, path, match=None, recursive=False, is_required=False, validator_list=None, max_length=None): import os from django.db.models import BLANK_CHOICE_DASH if match is not None: diff --git a/django/shortcuts/__init__.py b/django/shortcuts/__init__.py index dfb0c28abd..611b997736 100644 --- a/django/shortcuts/__init__.py +++ b/django/shortcuts/__init__.py @@ -14,8 +14,8 @@ def render_to_response(*args, **kwargs): Returns a HttpResponse whose content is filled with the result of calling django.template.loader.render_to_string() with the passed arguments. """ - return HttpResponse(loader.render_to_string(*args, **kwargs)) -load_and_render = render_to_response # For backwards compatibility. + httpresponse_kwargs = {'mimetype': kwargs.pop('mimetype', None)} + return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs) def _get_queryset(klass): """ diff --git a/django/template/__init__.py b/django/template/__init__.py index 6880fd5997..449e0d0c28 100644 --- a/django/template/__init__.py +++ b/django/template/__init__.py @@ -34,14 +34,8 @@ will be raised if the template doesn't have proper syntax. Sample code: ->>> import template ->>> s = ''' -... <html> -... {% if test %} -... <h1>{{ varvalue }}</h1> -... {% endif %} -... </html> -... ''' +>>> from django import template +>>> s = u'<html>{% if test %}<h1>{{ varvalue }}</h1>{% endif %}</html>' >>> t = template.Template(s) (t is now a compiled template, and its render() method can be called multiple @@ -49,15 +43,16 @@ times with multiple contexts) >>> c = template.Context({'test':True, 'varvalue': 'Hello'}) >>> t.render(c) -'\n<html>\n\n <h1>Hello</h1>\n\n</html>\n' +u'<html><h1>Hello</h1></html>' >>> c = template.Context({'test':False, 'varvalue': 'Hello'}) >>> t.render(c) -'\n<html>\n\n</html>\n' +u'<html></html>' """ import re from inspect import getargspec from django.conf import settings from django.template.context import Context, RequestContext, ContextPopException +from django.utils.itercompat import is_iterable from django.utils.functional import curry, Promise from django.utils.text import smart_split from django.utils.encoding import smart_unicode, force_unicode @@ -528,10 +523,11 @@ class FilterExpression(object): and return a list of tuples of the filter name and arguments. Sample: >>> token = 'variable|default:"Default value"|date:"Y-m-d"' - >>> p = FilterParser(token) - >>> p.filters - [('default', 'Default value'), ('date', 'Y-m-d')] - >>> p.var + >>> p = Parser('') + >>> fe = FilterExpression(token, p) + >>> len(fe.filters) + 2 + >>> fe.var 'variable' This class should never be instantiated outside of the @@ -646,7 +642,7 @@ def resolve_variable(path, context): >>> c = {'article': {'section':'News'}} >>> resolve_variable('article.section', c) - 'News' + u'News' >>> resolve_variable('article', c) {'section': 'News'} >>> class AClass: pass @@ -654,7 +650,7 @@ def resolve_variable(path, context): >>> c.article = AClass() >>> c.article.section = 'News' >>> resolve_variable('article.section', c) - 'News' + u'News' (The example assumes VARIABLE_ATTRIBUTE_SEPARATOR is '.') """ @@ -900,7 +896,7 @@ class Library(object): if not getattr(self, 'nodelist', False): from django.template.loader import get_template, select_template - if hasattr(file_name, '__iter__'): + if not isinstance(file_name, basestring) and is_iterable(file_name): t = select_template(file_name) else: t = get_template(file_name) diff --git a/django/template/context.py b/django/template/context.py index 59650b05fe..51cd88b7e9 100644 --- a/django/template/context.py +++ b/django/template/context.py @@ -49,8 +49,7 @@ class Context(object): return True return False - def __contains__(self, key): - return self.has_key(key) + __contains__ = has_key def get(self, key, otherwise=None): for d in self.dicts: diff --git a/django/template/defaultfilters.py b/django/template/defaultfilters.py index 22babfd6c0..1fd6d02c70 100644 --- a/django/template/defaultfilters.py +++ b/django/template/defaultfilters.py @@ -254,13 +254,20 @@ def escape(value): escape = stringfilter(escape) def linebreaks(value): - "Converts newlines into <p> and <br />s" + """ + Replaces line breaks in plain text with appropriate HTML; a single + newline becomes an HTML line break (``<br />``) and a new line + followed by a blank line becomes a paragraph break (``</p>``). + """ from django.utils.html import linebreaks return linebreaks(value) linebreaks = stringfilter(linebreaks) def linebreaksbr(value): - "Converts newlines into <br />s" + """ + Converts all newlines in a piece of plain text to HTML line breaks + (``<br />``). + """ return value.replace('\n', '<br />') linebreaksbr = stringfilter(linebreaksbr) diff --git a/django/template/defaulttags.py b/django/template/defaulttags.py index 11cd04653f..e23295f732 100644 --- a/django/template/defaulttags.py +++ b/django/template/defaulttags.py @@ -30,6 +30,7 @@ class CycleNode(Node): def render(self, context): self.counter += 1 value = self.cyclevars[self.counter % self.cyclevars_len] + value = resolve_variable(value, context) if self.variable_name: context[self.variable_name] = value return value @@ -403,7 +404,7 @@ def cycle(parser, token): the loop:: {% for o in some_list %} - <tr class="{% cycle row1,row2 %}"> + <tr class="{% cycle 'row1' 'row2' %}"> ... </tr> {% endfor %} @@ -411,16 +412,17 @@ def cycle(parser, token): Outside of a loop, give the values a unique name the first time you call it, then use that name each sucessive time through:: - <tr class="{% cycle row1,row2,row3 as rowcolors %}">...</tr> + <tr class="{% cycle 'row1' 'row2' 'row3' as rowcolors %}">...</tr> <tr class="{% cycle rowcolors %}">...</tr> <tr class="{% cycle rowcolors %}">...</tr> - You can use any number of values, seperated by commas. Make sure not to - put spaces between the values -- only commas. + You can use any number of values, seperated by spaces. Commas can also + be used to separate values; if a comma is used, the cycle values are + interpreted as literal strings. """ # Note: This returns the exact same node on each {% cycle name %} call; that - # is, the node object returned from {% cycle a,b,c as name %} and the one + # is, the node object returned from {% cycle a b c as name %} and the one # returned from {% cycle name %} are the exact same object. This shouldn't # cause problems (heh), but if it does, now you know. # @@ -429,40 +431,34 @@ def cycle(parser, token): # a global variable, which would make cycle names have to be unique across # *all* templates. - args = token.contents.split() + args = token.split_contents() + if len(args) < 2: - raise TemplateSyntaxError("'Cycle' statement requires at least two arguments") + raise TemplateSyntaxError("'cycle' tag requires at least two arguments") - elif len(args) == 2 and "," in args[1]: - # {% cycle a,b,c %} - cyclevars = [v for v in args[1].split(",") if v] # split and kill blanks - return CycleNode(cyclevars) - # {% cycle name %} + if ',' in args[1]: + # Backwards compatibility: {% cycle a,b %} or {% cycle a,b as foo %} + # case. + args[1:2] = ['"%s"' % arg for arg in args[1].split(",")] - elif len(args) == 2: + if len(args) == 2: + # {% cycle foo %} case name = args[1] if not hasattr(parser, '_namedCycleNodes'): raise TemplateSyntaxError("No named cycles in template: '%s' is not defined" % name) - if name not in parser._namedCycleNodes: + if not name in parser._namedCycleNodes: raise TemplateSyntaxError("Named cycle '%s' does not exist" % name) return parser._namedCycleNodes[name] - elif len(args) == 4: - # {% cycle a,b,c as name %} - if args[2] != 'as': - raise TemplateSyntaxError("Second 'cycle' argument must be 'as'") - cyclevars = [v for v in args[1].split(",") if v] # split and kill blanks - name = args[3] - node = CycleNode(cyclevars, name) - + if len(args) > 4 and args[-2] == 'as': + name = args[-1] + node = CycleNode(args[1:-2], name) if not hasattr(parser, '_namedCycleNodes'): parser._namedCycleNodes = {} - parser._namedCycleNodes[name] = node - return node - else: - raise TemplateSyntaxError("Invalid arguments to 'cycle': %s" % args) + node = CycleNode(args[1:]) + return node cycle = register.tag(cycle) def debug(parser, token): @@ -799,7 +795,7 @@ def load(parser, token): for taglib in bits[1:]: # add the library to the parser try: - lib = get_library("django.templatetags.%s" % taglib.split('.')[-1]) + lib = get_library("django.templatetags.%s" % taglib) parser.add_library(lib) except InvalidTemplateLibrary, e: raise TemplateSyntaxError, "'%s' is not a valid tag library: %s" % (taglib, e) diff --git a/django/test/_doctest.py b/django/test/_doctest.py index 8777a2cbba..3589e16225 100644 --- a/django/test/_doctest.py +++ b/django/test/_doctest.py @@ -1,5 +1,5 @@ # This is a slightly modified version of the doctest.py that shipped with Python 2.4 -# It incorporates changes that have been submitted the the Python ticket tracker +# It incorporates changes that have been submitted the the Python ticket tracker # as ticket #1521051. These changes allow for a DoctestRunner and Doctest base # class to be specified when constructing a DoctestSuite. @@ -105,6 +105,14 @@ import unittest, difflib, pdb, tempfile import warnings from StringIO import StringIO +if sys.platform.startswith('java'): + # On Jython, isclass() reports some modules as classes. Patch it. + def patch_isclass(isclass): + def patched_isclass(obj): + return isclass(obj) and hasattr(obj, '__module__') + return patched_isclass + inspect.isclass = patch_isclass(inspect.isclass) + # Don't whine about the deprecated is_private function in this # module's tests. warnings.filterwarnings("ignore", "is_private", DeprecationWarning, diff --git a/django/test/client.py b/django/test/client.py index 9ec3615973..6a05d9dd9c 100644 --- a/django/test/client.py +++ b/django/test/client.py @@ -4,17 +4,17 @@ from cStringIO import StringIO from urlparse import urlparse from django.conf import settings from django.contrib.auth import authenticate, login -from django.contrib.sessions.models import Session -from django.contrib.sessions.middleware import SessionWrapper from django.core.handlers.base import BaseHandler from django.core.handlers.wsgi import WSGIRequest from django.core.signals import got_request_exception from django.dispatch import dispatcher from django.http import SimpleCookie, HttpRequest +from django.template import TemplateDoesNotExist from django.test import signals from django.utils.functional import curry from django.utils.encoding import smart_str from django.utils.http import urlencode +from django.utils.itercompat import is_iterable BOUNDARY = 'BoUnDaRyStRiNg' MULTIPART_CONTENT = 'multipart/form-data; boundary=%s' % BOUNDARY @@ -73,21 +73,22 @@ def encode_multipart(boundary, data): '', value.read() ]) - elif hasattr(value, '__iter__'): - for item in value: + else: + if not isinstance(value, basestring) and is_iterable(value): + for item in value: + lines.extend([ + '--' + boundary, + 'Content-Disposition: form-data; name="%s"' % to_str(key), + '', + to_str(item) + ]) + else: lines.extend([ '--' + boundary, 'Content-Disposition: form-data; name="%s"' % to_str(key), '', - to_str(item) + to_str(value) ]) - else: - lines.extend([ - '--' + boundary, - 'Content-Disposition: form-data; name="%s"' % to_str(key), - '', - to_str(value) - ]) lines.extend([ '--' + boundary + '--', @@ -129,9 +130,10 @@ class Client: def _session(self): "Obtain the current session variables" if 'django.contrib.sessions' in settings.INSTALLED_APPS: + engine = __import__(settings.SESSION_ENGINE, {}, {}, ['']) cookie = self.cookies.get(settings.SESSION_COOKIE_NAME, None) if cookie: - return SessionWrapper(cookie.value) + return engine.SessionStore(cookie.value) return {} session = property(_session) @@ -165,7 +167,25 @@ class Client: # Capture exceptions created by the handler dispatcher.connect(self.store_exc_info, signal=got_request_exception) - response = self.handler(environ) + try: + response = self.handler(environ) + except TemplateDoesNotExist, e: + # If the view raises an exception, Django will attempt to show + # the 500.html template. If that template is not available, + # we should ignore the error in favor of re-raising the + # underlying exception that caused the 500 error. Any other + # template found to be missing during view error handling + # should be reported as-is. + if e.args != ('500.html',): + raise + + # Look for a signalled exception and reraise it + if self.exc_info: + raise self.exc_info[1], None, self.exc_info[2] + + # Save the client and request that stimulated the response + response.client = self + response.request = request # Add any rendered template detail to the response # If there was only one template rendered (the most likely case), @@ -179,10 +199,6 @@ class Client: else: setattr(response, detail, None) - # Look for a signalled exception and reraise it - if self.exc_info: - raise self.exc_info[1], None, self.exc_info[2] - # Update persistent cookie data if response.cookies: self.cookies.update(response.cookies) @@ -230,24 +246,23 @@ class Client: """ user = authenticate(**credentials) if user and user.is_active and 'django.contrib.sessions' in settings.INSTALLED_APPS: - obj = Session.objects.get_new_session_object() + engine = __import__(settings.SESSION_ENGINE, {}, {}, ['']) # Create a fake request to store login details request = HttpRequest() - request.session = SessionWrapper(obj.session_key) + request.session = engine.SessionStore() login(request, user) # Set the cookie to represent the session - self.cookies[settings.SESSION_COOKIE_NAME] = obj.session_key + self.cookies[settings.SESSION_COOKIE_NAME] = request.session.session_key self.cookies[settings.SESSION_COOKIE_NAME]['max-age'] = None self.cookies[settings.SESSION_COOKIE_NAME]['path'] = '/' self.cookies[settings.SESSION_COOKIE_NAME]['domain'] = settings.SESSION_COOKIE_DOMAIN self.cookies[settings.SESSION_COOKIE_NAME]['secure'] = settings.SESSION_COOKIE_SECURE or None self.cookies[settings.SESSION_COOKIE_NAME]['expires'] = None - # Set the session values - Session.objects.save(obj.session_key, request.session._session, - datetime.datetime.now() + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE)) + # Save the session values + request.session.save() return True else: @@ -258,9 +273,6 @@ class Client: Causes the authenticated user to be logged out. """ - try: - Session.objects.get(session_key=self.cookies['sessionid'].value).delete() - except KeyError: - pass - + session = __import__(settings.SESSION_ENGINE, {}, {}, ['']).SessionStore() + session.delete(session_key=self.cookies['sessionid'].value) self.cookies = SimpleCookie() diff --git a/django/test/testcases.py b/django/test/testcases.py index 21c429271c..6b7714ec7b 100644 --- a/django/test/testcases.py +++ b/django/test/testcases.py @@ -1,14 +1,28 @@ -import re, unittest -from urlparse import urlparse +import re +import unittest +from urlparse import urlsplit + +from django.http import QueryDict from django.db import transaction from django.core import mail from django.core.management import call_command -from django.db.models import get_apps from django.test import _doctest as doctest from django.test.client import Client normalize_long_ints = lambda s: re.sub(r'(?<![\w])(\d+)L(?![\w])', '\\1', s) +def to_list(value): + """ + Puts value into a list if it's not already one. + Returns an empty list if value is None. + """ + if value is None: + value = [] + elif not isinstance(value, list): + value = [value] + return value + + class OutputChecker(doctest.OutputChecker): def check_output(self, want, got, optionflags): ok = doctest.OutputChecker.check_output(self, want, got, optionflags) @@ -20,28 +34,27 @@ class OutputChecker(doctest.OutputChecker): if not ok: return normalize_long_ints(want) == normalize_long_ints(got) return ok - + class DocTestRunner(doctest.DocTestRunner): def __init__(self, *args, **kwargs): doctest.DocTestRunner.__init__(self, *args, **kwargs) self.optionflags = doctest.ELLIPSIS - + def report_unexpected_exception(self, out, test, example, exc_info): - doctest.DocTestRunner.report_unexpected_exception(self,out,test,example,exc_info) - + doctest.DocTestRunner.report_unexpected_exception(self, out, test, + example, exc_info) # Rollback, in case of database errors. Otherwise they'd have # side effects on other tests. - from django.db import transaction transaction.rollback_unless_managed() -class TestCase(unittest.TestCase): +class TestCase(unittest.TestCase): def _pre_setup(self): - """Perform any pre-test setup. This includes: - - * If the Test Case class has a 'fixtures' member, clearing the - database and installing the named fixtures at the start of each test. + """Performs any pre-test setup. This includes: + + * If the Test Case class has a 'fixtures' member, clearing the + database and installing the named fixtures at the start of each + test. * Clearing the mail test outbox. - """ call_command('flush', verbosity=0, interactive=False) if hasattr(self, 'fixtures'): @@ -60,97 +73,116 @@ class TestCase(unittest.TestCase): self._pre_setup() super(TestCase, self).__call__(result) - def assertRedirects(self, response, expected_path, status_code=302, target_status_code=200): - """Assert that a response redirected to a specific URL, and that the + def assertRedirects(self, response, expected_url, status_code=302, + target_status_code=200): + """Asserts that a response redirected to a specific URL, and that the redirect URL can be loaded. - + + Note that assertRedirects won't work for external links since it uses + TestClient to do a request. """ - self.assertEqual(response.status_code, status_code, - "Response didn't redirect as expected: Response code was %d (expected %d)" % - (response.status_code, status_code)) - scheme, netloc, path, params, query, fragment = urlparse(response['Location']) - self.assertEqual(path, expected_path, - "Response redirected to '%s', expected '%s'" % (path, expected_path)) - redirect_response = self.client.get(path) - self.assertEqual(redirect_response.status_code, target_status_code, - "Couldn't retrieve redirection page '%s': response code was %d (expected %d)" % - (path, redirect_response.status_code, target_status_code)) - + self.assertEqual(response.status_code, status_code, + ("Response didn't redirect as expected: Response code was %d" + " (expected %d)" % (response.status_code, status_code))) + url = response['Location'] + scheme, netloc, path, query, fragment = urlsplit(url) + self.assertEqual(url, expected_url, + "Response redirected to '%s', expected '%s'" % (url, expected_url)) + + # Get the redirection page, using the same client that was used + # to obtain the original response. + redirect_response = response.client.get(path, QueryDict(query)) + self.assertEqual(redirect_response.status_code, target_status_code, + ("Couldn't retrieve redirection page '%s': response code was %d" + " (expected %d)") % + (path, redirect_response.status_code, target_status_code)) + def assertContains(self, response, text, count=None, status_code=200): - """Assert that a response indicates that a page was retreived successfully, - (i.e., the HTTP status code was as expected), and that ``text`` occurs ``count`` - times in the content of the response. If ``count`` is None, the count doesn't - matter - the assertion is true if the text occurs at least once in the response. - + """ + Asserts that a response indicates that a page was retreived + successfully, (i.e., the HTTP status code was as expected), and that + ``text`` occurs ``count`` times in the content of the response. + If ``count`` is None, the count doesn't matter - the assertion is true + if the text occurs at least once in the response. """ self.assertEqual(response.status_code, status_code, - "Couldn't retrieve page: Response code was %d (expected %d)'" % + "Couldn't retrieve page: Response code was %d (expected %d)'" % (response.status_code, status_code)) real_count = response.content.count(text) if count is not None: self.assertEqual(real_count, count, - "Found %d instances of '%s' in response (expected %d)" % (real_count, text, count)) + "Found %d instances of '%s' in response (expected %d)" % + (real_count, text, count)) else: - self.failUnless(real_count != 0, "Couldn't find '%s' in response" % text) - + self.failUnless(real_count != 0, + "Couldn't find '%s' in response" % text) + def assertFormError(self, response, form, field, errors): - "Assert that a form used to render the response has a specific field error" - if not response.context: - self.fail('Response did not use any contexts to render the response') + """ + Asserts that a form used to render the response has a specific field + error. + """ + # Put context(s) into a list to simplify processing. + contexts = to_list(response.context) + if not contexts: + self.fail('Response did not use any contexts to render the' + ' response') - # If there is a single context, put it into a list to simplify processing - if not isinstance(response.context, list): - contexts = [response.context] - else: - contexts = response.context + # Put error(s) into a list to simplify processing. + errors = to_list(errors) - # If a single error string is provided, make it a list to simplify processing - if not isinstance(errors, list): - errors = [errors] - # Search all contexts for the error. found_form = False for i,context in enumerate(contexts): - if form in context: - found_form = True - for err in errors: - if field: - if field in context[form].errors: - self.failUnless(err in context[form].errors[field], - "The field '%s' on form '%s' in context %d does not contain the error '%s' (actual errors: %s)" % - (field, form, i, err, list(context[form].errors[field]))) - elif field in context[form].fields: - self.fail("The field '%s' on form '%s' in context %d contains no errors" % - (field, form, i)) - else: - self.fail("The form '%s' in context %d does not contain the field '%s'" % (form, i, field)) + if form not in context: + continue + found_form = True + for err in errors: + if field: + if field in context[form].errors: + field_errors = context[form].errors[field] + self.failUnless(err in field_errors, + "The field '%s' on form '%s' in" + " context %d does not contain the" + " error '%s' (actual errors: %s)" % + (field, form, i, err, + list(field_errors))) + elif field in context[form].fields: + self.fail("The field '%s' on form '%s' in context %d" + " contains no errors" % (field, form, i)) else: - self.failUnless(err in context[form].non_field_errors(), - "The form '%s' in context %d does not contain the non-field error '%s' (actual errors: %s)" % - (form, i, err, list(context[form].non_field_errors()))) + self.fail("The form '%s' in context %d does not" + " contain the field '%s'" % + (form, i, field)) + else: + non_field_errors = context[form].non_field_errors() + self.failUnless(err in non_field_errors, + "The form '%s' in context %d does not contain the" + " non-field error '%s' (actual errors: %s)" % + (form, i, err, non_field_errors)) if not found_form: - self.fail("The form '%s' was not used to render the response" % form) - + self.fail("The form '%s' was not used to render the response" % + form) + def assertTemplateUsed(self, response, template_name): - "Assert that the template with the provided name was used in rendering the response" - if isinstance(response.template, list): - template_names = [t.name for t in response.template] - self.failUnless(template_name in template_names, - u"Template '%s' was not one of the templates used to render the response. Templates used: %s" % - (template_name, u', '.join(template_names))) - elif response.template: - self.assertEqual(template_name, response.template.name, - u"Template '%s' was not used to render the response. Actual template was '%s'" % - (template_name, response.template.name)) - else: + """ + Asserts that the template with the provided name was used in rendering + the response. + """ + template_names = [t.name for t in to_list(response.template)] + if not template_names: self.fail('No templates used to render the response') + self.failUnless(template_name in template_names, + (u"Template '%s' was not a template used to render the response." + u" Actual template(s) used: %s") % (template_name, + u', '.join(template_names))) def assertTemplateNotUsed(self, response, template_name): - "Assert that the template with the provided name was NOT used in rendering the response" - if isinstance(response.template, list): - self.failIf(template_name in [t.name for t in response.template], - u"Template '%s' was used unexpectedly in rendering the response" % template_name) - elif response.template: - self.assertNotEqual(template_name, response.template.name, - u"Template '%s' was used unexpectedly in rendering the response" % template_name) - + """ + Asserts that the template with the provided name was NOT used in + rendering the response. + """ + template_names = [t.name for t in to_list(response.template)] + self.failIf(template_name in template_names, + (u"Template '%s' was used unexpectedly in rendering the" + u" response") % template_name) diff --git a/django/utils/cache.py b/django/utils/cache.py index 2753d86949..2494d7839e 100644 --- a/django/utils/cache.py +++ b/django/utils/cache.py @@ -42,9 +42,9 @@ def patch_cache_control(response, **kwargs): def dictitem(s): t = s.split('=',1) if len(t) > 1: - return (t[0].lower().replace('-', '_'), t[1]) + return (t[0].lower(), t[1]) else: - return (t[0].lower().replace('-', '_'), True) + return (t[0].lower(), True) def dictvalue(t): if t[1] is True: diff --git a/django/utils/datastructures.py b/django/utils/datastructures.py index 4b60d1d194..2f3c9bb568 100644 --- a/django/utils/datastructures.py +++ b/django/utils/datastructures.py @@ -14,9 +14,6 @@ class MergeDict(object): pass raise KeyError - def __contains__(self, key): - return self.has_key(key) - def __copy__(self): return self.__class__(*self.dicts) @@ -45,6 +42,8 @@ class MergeDict(object): if key in dict: return True return False + + __contains__ = has_key def copy(self): """ returns a copy of this object""" @@ -73,12 +72,23 @@ class SortedDict(dict): def items(self): return zip(self.keyOrder, self.values()) + def iteritems(self): + for key in self.keyOrder: + yield key, dict.__getitem__(self, key) + def keys(self): return self.keyOrder[:] + def iterkeys(self): + return iter(self.keyOrder) + def values(self): return [dict.__getitem__(self, k) for k in self.keyOrder] + def itervalues(self): + for key in self.keyOrder: + yield dict.__getitem__(self, key) + def update(self, dict): for k, v in dict.items(): self.__setitem__(k, v) @@ -92,6 +102,15 @@ class SortedDict(dict): "Returns the value of the item at the given zero-based index." return self[self.keyOrder[index]] + def insert(self, index, key, value): + "Inserts the key, value pair before the item with the given index." + if key in self.keyOrder: + n = self.keyOrder.index(key) + del self.keyOrder[n] + if n < index: index -= 1 + self.keyOrder.insert(index, key) + dict.__setitem__(self, key, value) + def copy(self): "Returns a copy of this object." # This way of initializing the copy means it works for subclasses, too. @@ -130,7 +149,7 @@ class MultiValueDict(dict): dict.__init__(self, key_to_list_mapping) def __repr__(self): - return "<MultiValueDict: %s>" % dict.__repr__(self) + return "<%s: %s>" % (self.__class__.__name__, dict.__repr__(self)) def __getitem__(self, key): """ @@ -239,22 +258,20 @@ class DotExpandedDict(dict): may contain dots to specify inner dictionaries. It's confusing, but this example should make sense. - >>> d = DotExpandedDict({'person.1.firstname': ['Simon'], - 'person.1.lastname': ['Willison'], - 'person.2.firstname': ['Adrian'], + >>> d = DotExpandedDict({'person.1.firstname': ['Simon'], \ + 'person.1.lastname': ['Willison'], \ + 'person.2.firstname': ['Adrian'], \ 'person.2.lastname': ['Holovaty']}) >>> d - {'person': {'1': {'lastname': ['Willison'], 'firstname': ['Simon']}, - '2': {'lastname': ['Holovaty'], 'firstname': ['Adrian']}}} + {'person': {'1': {'lastname': ['Willison'], 'firstname': ['Simon']}, '2': {'lastname': ['Holovaty'], 'firstname': ['Adrian']}}} >>> d['person'] - {'1': {'firstname': ['Simon'], 'lastname': ['Willison'], - '2': {'firstname': ['Adrian'], 'lastname': ['Holovaty']} + {'1': {'lastname': ['Willison'], 'firstname': ['Simon']}, '2': {'lastname': ['Holovaty'], 'firstname': ['Adrian']}} >>> d['person']['1'] - {'firstname': ['Simon'], 'lastname': ['Willison']} + {'lastname': ['Willison'], 'firstname': ['Simon']} # Gotcha: Results are unpredictable if the dots are "uneven": >>> DotExpandedDict({'c.1': 2, 'c.2': 3, 'c': 1}) - >>> {'c': 1} + {'c': 1} """ def __init__(self, key_to_list_mapping): for k, v in key_to_list_mapping.items(): diff --git a/django/utils/dateformat.py b/django/utils/dateformat.py index d5f3499d82..9a296c3f2d 100644 --- a/django/utils/dateformat.py +++ b/django/utils/dateformat.py @@ -166,8 +166,8 @@ class DateFormat(TimeFormat): def O(self): "Difference to Greenwich time in hours; e.g. '+0200'" - tz = self.timezone.utcoffset(self.data) - return u"%+03d%02d" % (tz.seconds // 3600, (tz.seconds // 60) % 60) + seconds = self.Z() + return u"%+03d%02d" % (seconds // 3600, (seconds // 60) % 60) def r(self): "RFC 822 formatted date; e.g. 'Thu, 21 Dec 2000 16:01:07 +0200'" @@ -248,10 +248,15 @@ class DateFormat(TimeFormat): return doy def Z(self): - """Time zone offset in seconds (i.e. '-43200' to '43200'). The offset - for timezones west of UTC is always negative, and for those east of UTC - is always positive.""" - return self.timezone.utcoffset(self.data).seconds + """ + Time zone offset in seconds (i.e. '-43200' to '43200'). The offset for + timezones west of UTC is always negative, and for those east of UTC is + always positive. + """ + offset = self.timezone.utcoffset(self.data) + # Only days can be negative, so negative offsets have days=-1 and + # seconds positive. Positive offsets have days=0 + return offset.days * 86400 + offset.seconds def format(value, format_string): "Convenience function" diff --git a/django/utils/encoding.py b/django/utils/encoding.py index 2319496538..69c3e9c28b 100644 --- a/django/utils/encoding.py +++ b/django/utils/encoding.py @@ -30,7 +30,7 @@ def force_unicode(s, encoding='utf-8', strings_only=False, errors='strict'): If strings_only is True, don't convert (some) non-string-like objects. """ - if strings_only and isinstance(s, (types.NoneType, int)): + if strings_only and isinstance(s, (types.NoneType, int, long)): return s if not isinstance(s, basestring,): if hasattr(s, '__unicode__'): diff --git a/django/utils/feedgenerator.py b/django/utils/feedgenerator.py index 6b6dedfbe9..e296331324 100644 --- a/django/utils/feedgenerator.py +++ b/django/utils/feedgenerator.py @@ -3,6 +3,7 @@ Syndication feed generation library -- used for generating RSS, etc. Sample usage: +>>> from django.utils import feedgenerator >>> feed = feedgenerator.Rss201rev2Feed( ... title=u"Poynter E-Media Tidbits", ... link=u"http://www.poynter.org/column.asp?id=31", @@ -27,7 +28,10 @@ def rfc2822_date(date): return email.Utils.formatdate(time.mktime(date.timetuple())) def rfc3339_date(date): - return date.strftime('%Y-%m-%dT%H:%M:%SZ') + if date.tzinfo: + return date.strftime('%Y-%m-%dT%H:%M:%S%z') + else: + return date.strftime('%Y-%m-%dT%H:%M:%SZ') def get_tag_uri(url, date): "Creates a TagURI. See http://diveintomark.org/archives/2004/05/28/howto-atom-id" diff --git a/django/utils/functional.py b/django/utils/functional.py index 734704f6f3..f4580e7bd5 100644 --- a/django/utils/functional.py +++ b/django/utils/functional.py @@ -101,6 +101,13 @@ def lazy(func, *resultclasses): else: raise AssertionError('__mod__ not supported for non-string types') + def __deepcopy__(self, memo): + # Instances of this class are effectively immutable. It's just a + # collection of functions. So we don't need to do anything + # complicated for copying. + memo[id(self)] = self + return self + def __wrapper__(*args, **kw): # Creates the proxy object, instead of the actual value. return __proxy__(args, kw) diff --git a/django/utils/itercompat.py b/django/utils/itercompat.py index 0de1b6cbe2..3742d6c5d8 100644 --- a/django/utils/itercompat.py +++ b/django/utils/itercompat.py @@ -57,3 +57,13 @@ else: tee = compat_tee if hasattr(itertools, 'groupby'): groupby = itertools.groupby + +def is_iterable(x): + "A implementation independent way of checking for iterables" + try: + iter(x) + except TypeError: + return False + else: + return True + diff --git a/django/utils/timesince.py b/django/utils/timesince.py index 455788e7d7..e1132c3ab3 100644 --- a/django/utils/timesince.py +++ b/django/utils/timesince.py @@ -1,11 +1,20 @@ -import datetime, math, time +import datetime +import time + from django.utils.tzinfo import LocalTimezone from django.utils.translation import ungettext, ugettext def timesince(d, now=None): """ - Takes two datetime objects and returns the time between then and now - as a nicely formatted string, e.g "10 minutes" + Takes two datetime objects and returns the time between d and now + as a nicely formatted string, e.g. "10 minutes". If d occurs after now, + then "0 minutes" is returned. + + Units used are years, months, weeks, days, hours, and minutes. + Seconds and microseconds are ignored. Up to two adjacent units will be + displayed. For example, "2 weeks, 3 days" and "1 year, 3 months" are + possible outputs, but "2 weeks, 3 hours" and "1 year, 5 days" are not. + Adapted from http://blog.natbat.co.uk/archive/2003/Jun/14/time_since """ chunks = ( @@ -32,6 +41,9 @@ def timesince(d, now=None): # ignore microsecond part of 'd' since we removed it from 'now' delta = now - (d - datetime.timedelta(0, 0, d.microsecond)) since = delta.days * 24 * 60 * 60 + delta.seconds + if since <= 0: + # d is in the future compared to now, stop processing. + return u'0 ' + ugettext('minutes') for i, (seconds, name) in enumerate(chunks): count = since // seconds if count != 0: diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py index 765152afce..5fff1ea63a 100644 --- a/django/utils/translation/trans_real.py +++ b/django/utils/translation/trans_real.py @@ -491,6 +491,8 @@ def templatize(src): elif g[0] == "'": g = g.strip("'") out.write(' gettext(%r) ' % g) elif bmatch: + for fmatch in constant_re.findall(t.contents): + out.write(' _(%s) ' % fmatch) intrans = True inplural = False singular = [] diff --git a/django/views/generic/date_based.py b/django/views/generic/date_based.py index c0f219f280..e6a75e63aa 100644 --- a/django/views/generic/date_based.py +++ b/django/views/generic/date_based.py @@ -1,14 +1,16 @@ +import datetime +import time + from django.template import loader, RequestContext from django.core.exceptions import ObjectDoesNotExist from django.core.xheaders import populate_xheaders from django.db.models.fields import DateTimeField from django.http import Http404, HttpResponse -import datetime, time def archive_index(request, queryset, date_field, num_latest=15, template_name=None, template_loader=loader, extra_context=None, allow_empty=False, context_processors=None, - mimetype=None, allow_future=False): + mimetype=None, allow_future=False, template_object_name='latest'): """ Generic top-level archive of date-based objects. @@ -37,7 +39,7 @@ def archive_index(request, queryset, date_field, num_latest=15, t = template_loader.get_template(template_name) c = RequestContext(request, { 'date_list' : date_list, - 'latest' : latest, + template_object_name : latest, }, context_processors) for key, value in extra_context.items(): if callable(value): @@ -76,7 +78,7 @@ def archive_year(request, year, queryset, date_field, template_name=None, if not date_list and not allow_empty: raise Http404 if make_object_list: - object_list = queryset.filter(**lookup_kwargs).order_by(date_field) + object_list = queryset.filter(**lookup_kwargs) else: object_list = [] if not template_name: diff --git a/django/views/generic/list_detail.py b/django/views/generic/list_detail.py index f5616b9745..b72173bd76 100644 --- a/django/views/generic/list_detail.py +++ b/django/views/generic/list_detail.py @@ -39,6 +39,8 @@ def object_list(request, queryset, paginate_by=None, page=None, first_on_page the result number of the first object in the object_list (1-indexed) + page_range: + A list of the page numbers (1-indexed). """ if extra_context is None: extra_context = {} queryset = queryset._clone() @@ -47,10 +49,17 @@ def object_list(request, queryset, paginate_by=None, page=None, if not page: page = request.GET.get('page', 1) try: - page = int(page) - object_list = paginator.get_page(page - 1) - except (InvalidPage, ValueError): - if page == 1 and allow_empty: + page_number = int(page) + except ValueError: + if page == 'last': + page_number = paginator.pages + else: + # Page is not 'last', nor can it be converted to an int + raise Http404 + try: + object_list = paginator.get_page(page_number - 1) + except InvalidPage: + if page_number == 1 and allow_empty: object_list = [] else: raise Http404 @@ -58,15 +67,16 @@ def object_list(request, queryset, paginate_by=None, page=None, '%s_list' % template_object_name: object_list, 'is_paginated': paginator.pages > 1, 'results_per_page': paginate_by, - 'has_next': paginator.has_next_page(page - 1), - 'has_previous': paginator.has_previous_page(page - 1), - 'page': page, - 'next': page + 1, - 'previous': page - 1, - 'last_on_page': paginator.last_on_page(page - 1), - 'first_on_page': paginator.first_on_page(page - 1), + 'has_next': paginator.has_next_page(page_number - 1), + 'has_previous': paginator.has_previous_page(page_number - 1), + 'page': page_number, + 'next': page_number + 1, + 'previous': page_number - 1, + 'last_on_page': paginator.last_on_page(page_number - 1), + 'first_on_page': paginator.first_on_page(page_number - 1), 'pages': paginator.pages, 'hits' : paginator.hits, + 'page_range' : paginator.page_range }, context_processors) else: c = RequestContext(request, { diff --git a/django/views/generic/simple.py b/django/views/generic/simple.py index 69a494931e..9d7efdc6c4 100644 --- a/django/views/generic/simple.py +++ b/django/views/generic/simple.py @@ -2,11 +2,12 @@ from django.shortcuts import render_to_response from django.template import loader, RequestContext from django.http import HttpResponse, HttpResponsePermanentRedirect, HttpResponseGone -def direct_to_template(request, template, extra_context={}, mimetype=None, **kwargs): +def direct_to_template(request, template, extra_context=None, mimetype=None, **kwargs): """ Render a given template with any extra URL parameters in the context as ``{{ params }}``. """ + if extra_context is None: extra_context = {} dictionary = {'params': kwargs} for key, value in extra_context.items(): if callable(value): diff --git a/django/views/i18n.py b/django/views/i18n.py index 320caf37d7..cccec13941 100644 --- a/django/views/i18n.py +++ b/django/views/i18n.py @@ -9,20 +9,26 @@ def set_language(request): """ Redirect to a given url while setting the chosen language in the session or cookie. The url and the language code need to be - specified in the GET parameters. + specified in the request parameters. + + Since this view changes how the user will see the rest of the site, it must + only be accessed as a POST request. If called as a GET request, it will + redirect to the page in the request (the 'next' parameter) without changing + any state. """ - lang_code = request.GET.get('language', None) - next = request.GET.get('next', None) + next = request.REQUEST.get('next', None) if not next: next = request.META.get('HTTP_REFERER', None) if not next: next = '/' response = http.HttpResponseRedirect(next) - if lang_code and check_for_language(lang_code): - if hasattr(request, 'session'): - request.session['django_language'] = lang_code - else: - response.set_cookie('django_language', lang_code) + if request.method == 'POST': + lang_code = request.POST.get('language', None) + if lang_code and check_for_language(lang_code): + if hasattr(request, 'session'): + request.session['django_language'] = lang_code + else: + response.set_cookie('django_language', lang_code) return response NullSource = """ diff --git a/docs/add_ons.txt b/docs/add_ons.txt index a1d78b8685..00c6e0dcf4 100644 --- a/docs/add_ons.txt +++ b/docs/add_ons.txt @@ -70,8 +70,9 @@ 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. +See the `form preview documentation`_. + +.. _form preview documentation: ../form_preview/ humanize ======== diff --git a/docs/apache_auth.txt b/docs/apache_auth.txt index 583cb96b39..cab57fe6d5 100644 --- a/docs/apache_auth.txt +++ b/docs/apache_auth.txt @@ -21,14 +21,57 @@ file, you'll need to use mod_python's ``PythonAuthenHandler`` directive along with the standard ``Auth*`` and ``Require`` directives:: <Location /example/> - AuthType basic + AuthType Basic AuthName "example.com" Require valid-user SetEnv DJANGO_SETTINGS_MODULE mysite.settings PythonAuthenHandler django.contrib.auth.handlers.modpython </Location> + +.. admonition:: Using the authentication handler with Apache 2.2 + If you're using Apache 2.2, you'll need to take a couple extra steps. + + You'll need to ensure that ``mod_auth_basic`` and ``mod_authz_user`` + are loaded. These might be compiled statically into Apache, or you might + need to use ``LoadModule`` to load them dynamically (as shown in the + example at the bottom of this note). + + You'll also need to insert configuration directives that prevent Apache + from trying to use other authentication modules. Depending on which other + authentication modules you have loaded, you might need one or more of + the following directives:: + + AuthBasicAuthoritative Off + AuthDefaultAuthoritative Off + AuthzLDAPAuthoritative Off + AuthzDBMAuthoritative Off + AuthzDefaultAuthoritative Off + AuthzGroupFileAuthoritative Off + AuthzOwnerAuthoritative Off + AuthzUserAuthoritative Off + + A complete configuration, with differences between Apache 2.0 and + Apache 2.2 marked in bold, would look something like: + + .. parsed-literal:: + + **LoadModule auth_basic_module modules/mod_auth_basic.so** + **LoadModule authz_user_module modules/mod_authz_user.so** + + ... + + <Location /exmaple/> + AuthType Basic + AuthName "example.com" + **AuthBasicAuthoritative Off** + Require valid-user + + SetEnv DJANGO_SETTINGS_MODULE mysite.settings + PythonAuthenHandler django.contrib.auth.handlers.modpython + </Location> + By default, the authentication handler will limit access to the ``/example/`` location to users marked as staff members. You can use a set of ``PythonOption`` directives to modify this behavior: diff --git a/docs/authentication.txt b/docs/authentication.txt index 7860b59d7d..aee9c5224a 100644 --- a/docs/authentication.txt +++ b/docs/authentication.txt @@ -190,7 +190,7 @@ function that comes with Django:: >>> from django.contrib.auth.models import User >>> user = User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword') - # At this point, user is a User object ready to be saved + # At this point, user is a User object that has already been saved # to the database. You can continue to change its attributes # if you want to change other fields. >>> user.is_staff = True @@ -244,6 +244,9 @@ Anonymous users the ``django.contrib.auth.models.User`` interface, with these differences: * ``id`` is always ``None``. + * ``is_staff`` and ``is_superuser`` are always False. + * ``is_active`` is always True. + * ``groups`` and ``user_permissions`` are always empty. * ``is_anonymous()`` returns ``True`` instead of ``False``. * ``is_authenticated()`` returns ``False`` instead of ``True``. * ``has_perm()`` always returns ``False``. @@ -402,11 +405,29 @@ introduced in Python 2.4:: def my_view(request): # ... +In the Django development version, ``login_required`` also takes an optional +``redirect_field_name`` parameter. Example:: + + from django.contrib.auth.decorators import login_required + + def my_view(request): + # ... + my_view = login_required(redirect_field_name='redirect_to')(my_view) + +Again, an equivalent example of the more compact decorator syntax introduced in Python 2.4:: + + from django.contrib.auth.decorators import login_required + + @login_required(redirect_field_name='redirect_to') + def my_view(request): + # ... + ``login_required`` does the following: * If the user isn't logged in, redirect to ``settings.LOGIN_URL`` (``/accounts/login/`` by default), passing the current absolute URL - in the query string as ``next``. For example: + in the query string as ``next`` or the value of ``redirect_field_name``. + For example: ``/accounts/login/?next=/polls/3/``. * If the user is logged in, execute the view normally. The view code is free to assume the user is logged in. @@ -974,10 +995,10 @@ Writing an authentication backend --------------------------------- An authentication backend is a class that implements two methods: -``get_user(id)`` and ``authenticate(**credentials)``. +``get_user(user_id)`` and ``authenticate(**credentials)``. -The ``get_user`` method takes an ``id`` -- which could be a username, database -ID or whatever -- and returns a ``User`` object. +The ``get_user`` method takes a ``user_id`` -- which could be a username, +database ID or whatever -- and returns a ``User`` object. The ``authenticate`` method takes credentials as keyword arguments. Most of the time, it'll just look like this:: @@ -1041,3 +1062,40 @@ object the first time a user authenticates:: return User.objects.get(pk=user_id) except User.DoesNotExist: return None + +Handling authorization in custom backends +----------------------------------------- + +Custom auth backends can provide their own permissions. + +The user model will delegate permission lookup functions +(``get_group_permissions()``, ``get_all_permissions()``, ``has_perm()``, and +``has_module_perms()``) to any authentication backend that implements these +functions. + +The permissions given to the user will be the superset of all permissions +returned by all backends. That is, Django grants a permission to a user that any +one backend grants. + +The simple backend above could implement permissions for the magic admin fairly +simply:: + + class SettingsBackend: + + # ... + + def has_perm(self, user_obj, perm): + if user_obj.username == settings.ADMIN_LOGIN: + return True + else: + return False + +This gives full permissions to the user granted access in the above example. Notice +that the backend auth functions all take the user object as an argument, and +they also accept the same arguments given to the associated ``User`` functions. + +A full authorization implementation can be found in +``django/contrib/auth/backends.py`` _, which is the default backend and queries +the ``auth_permission`` table most of the time. + +.. _django/contrib/auth/backends.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/backends.py diff --git a/docs/cache.txt b/docs/cache.txt index d13352b025..8ba0383909 100644 --- a/docs/cache.txt +++ b/docs/cache.txt @@ -176,9 +176,11 @@ just implements the cache interface without doing anything. This is useful if you have a production site that uses heavy-duty caching in various places but a development/test environment on which you don't want to -cache. In that case, set ``CACHE_BACKEND`` to ``"dummy:///"`` in the settings -file for your development environment. As a result, your development -environment won't use caching and your production environment still will. +cache. As a result, your development environment won't use caching and your +production environment still will. To activate dummy caching, set +``CACHE_BACKEND`` like so:: + + CACHE_BACKEND = 'dummy:///' CACHE_BACKEND arguments ----------------------- @@ -522,6 +524,15 @@ the value of the ``CACHE_MIDDLEWARE_SETTINGS`` setting. If you use a custom ``max_age`` in a ``cache_control`` decorator, the decorator will take precedence, and the header values will be merged correctly.) +If you want to use headers to disable caching altogether, +``django.views.decorators.never_cache`` is a view decorator that adds +headers to ensure the response won't be cached by browsers or other caches. Example:: + + from django.views.decorators.cache import never_cache + @never_cache + def myview(request): + ... + .. _`Cache-Control spec`: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9 Other optimizations diff --git a/docs/contenttypes.txt b/docs/contenttypes.txt new file mode 100644 index 0000000000..3ef83f2066 --- /dev/null +++ b/docs/contenttypes.txt @@ -0,0 +1,258 @@ +========================== +The contenttypes framework +========================== + +Django includes a "contenttypes" application that can track all of +the models installed in your Django-powered project, providing a +high-level, generic interface for working with your models. + +Overview +======== + +At the heart of the contenttypes application is the ``ContentType`` +model, which lives at +``django.contrib.contenttypes.models.ContentType``. Instances of +``ContentType`` represent and store information about the models +installed in your project, and new instances of ``ContentType`` are +automatically created whenever new models are installed. + +Instances of ``ContentType`` have methods for returning the model +classes they represent and for querying objects from those models. +``ContentType`` also has a `custom manager`_ that adds methods for +working with ``ContentType`` and for obtaining instances of +``ContentType`` for a particular model. + +Relations between your models and ``ContentType`` can also be used to +enable "generic" relationships between an instance of one of your +models and instances of any model you have installed. + +.. _custom manager: ../model-api/#custom-managers + +Installing the contenttypes framework +===================================== + +The contenttypes framework is included in the default +``INSTALLED_APPS`` list created by ``django-admin.py startproject``, +but if you've removed it or if you manually set up your +``INSTALLED_APPS`` list, you can enable it by adding +``'django.contrib.contenttypes'`` to your ``INSTALLED_APPS`` setting. + +It's generally a good idea to have the contenttypes framework +installed; several of Django's other bundled applications require it: + + * The admin application uses it to log the history of each object + added or changed through the admin interface. + + * Django's `authentication framework`_ uses it to tie user permissions + to specific models. + + * Django's comments system (``django.contrib.comments``) uses it to + "attach" comments to any installed model. + +.. _authentication framework: ../authentication/ + +The ``ContentType`` model +========================= + +Each instance of ``ContentType`` has three fields which, taken +together, uniquely describe an installed model: + + ``app_label`` + The name of the application the model is part of. This is taken from + the ``app_label`` attribute of the model, and includes only the *last* + part of the application's Python import path; + "django.contrib.contenttypes", for example, becomes an ``app_label`` + of "contenttypes". + + ``model`` + The name of the model class. + + ``name`` + The human-readable name of the model. This is taken from + `the verbose_name attribute`_ of the model. + +Let's look at an example to see how this works. If you already have +the contenttypes application installed, and then add `the sites +application`_ to your ``INSTALLED_APPS`` setting and run ``manage.py +syncdb`` to install it, the model ``django.contrib.sites.models.Site`` +will be installed into your database. Along with it a new instance +of ``ContentType`` will be created with the following values: + + * ``app_label`` will be set to ``'sites'`` (the last part of the Python + path "django.contrib.sites"). + + * ``model`` will be set to ``'site'``. + + * ``name`` will be set to ``'site'``. + +.. _the verbose_name attribute: ../model-api/#verbose_name +.. _the sites application: ../sites/ + +Methods on ``ContentType`` instances +==================================== + +Each ``ContentType`` instance has methods that allow you to get from a +``ContentType`` instance to the model it represents, or to retrieve objects +from that model: + + ``get_object_for_this_type(**kwargs)`` + Takes a set of valid `lookup arguments`_ for the model the + ``ContentType`` represents, and does `a get() lookup`_ on that + model, returning the corresponding object. + + ``model_class()`` + Returns the model class represented by this ``ContentType`` + instance. + +For example, we could look up the ``ContentType`` for the ``User`` model:: + + >>> from django.contrib.contenttypes.models import ContentType + >>> user_type = ContentType.objects.get(app_label="auth", model="user") + >>> user_type + <ContentType: user> + +And then use it to query for a particular ``User``, or to get access +to the ``User`` model class:: + + >>> user_type.model_class() + <class 'django.contrib.auth.models.User'> + >>> user_type.get_object_for_this_type(username='Guido') + <User: Guido> + +Together, ``get_object_for_this_type`` and ``model_class`` enable two +extremely important use cases: + + 1. Using these methods, you can write high-level generic code that + performs queries on any installed model -- instead of importing and + using a single specific model class, you can pass an ``app_label`` + and ``model`` into a ``ContentType`` lookup at runtime, and then + work with the model class or retrieve objects from it. + + 2. You can relate another model to ``ContentType`` as a way of tying + instances of it to particular model classes, and use these methods + to get access to those model classes. + +Several of Django's bundled applications make use of the latter +technique. For example, `the permissions system`_ in Django's +authentication framework uses a ``Permission`` model with a foreign +key to ``ContentType``; this lets ``Permission`` represent concepts +like "can add blog entry" or "can delete news story". + +.. _lookup arguments: ../db-api/#field-lookups +.. _a get() lookup: ../db-api/#get-kwargs +.. _the permissions system: ../authentication/#permissions + +The ``ContentTypeManager`` +-------------------------- + +``ContentType`` also has a custom manager, ``ContentTypeManager``, +which adds the following methods: + + ``clear_cache()`` + Clears an internal cache used by ``ContentType`` to keep track of which + models for which it has created ``ContentType`` instances. You probably + won't ever need to call this method yourself; Django will call it + automatically when it's needed. + + ``get_for_model(model)`` + Takes either a model class or an instance of a model, and returns the + ``ContentType`` instance representing that model. + +The ``get_for_model`` method is especially useful when you know you +need to work with a ``ContentType`` but don't want to go to the +trouble of obtaining the model's metadata to perform a manual lookup:: + + >>> from django.contrib.auth.models import User + >>> user_type = ContentType.objects.get_for_model(User) + >>> user_type + <ContentType: user> + +Generic relations +================= + +Adding a foreign key from one of your own models to ``ContentType`` +allows your model to effectively tie itself to another model class, as +in the example of the ``Permission`` model above. But it's possible to +go one step further and use ``ContentType`` to enable truly generic +(sometimes called "polymorphic") relationships between models. + +A simple example is a tagging system, which might look like this:: + + from django.db import models + from django.contrib.contenttypes.models import ContentType + from django.contrib.contenttypes import generic + + class TaggedItem(models.Model): + tag = models.SlugField() + content_type = models.ForeignKey(ContentType) + object_id = models.PositiveIntegerField() + content_object = generic.GenericForeignKey('content_type', 'object_id') + + def __unicode__(self): + return self.tag + +A normal ``ForeignKey`` can only "point to" one other model, which +means that if the ``TaggedItem`` model used a ``ForeignKey`` it would have to +choose one and only one model to store tags for. The contenttypes +application provides a special field type -- +``django.contrib.contenttypes.generic.GenericForeignKey`` -- which +works around this and allows the relationship to be with any +model. There are three parts to setting up a ``GenericForeignKey``: + + 1. Give your model a ``ForeignKey`` to ``ContentType``. + + 2. Give your model a field that can store a primary-key value from the + models you'll be relating to. (For most models, this means an + ``IntegerField`` or ``PositiveIntegerField``.) + + 3. Give your model a ``GenericForeignKey``, and pass it the names of + the two fields described above. If these fields are named + "content_type" and "object_id", you can omit this -- those are the + default field names ``GenericForeignKey`` will look for. + +This will enable an API similar to the one used for a normal ``ForeignKey``; +each ``TaggedItem`` will have a ``content_object`` field that returns the +object it's related to, and you can also assign to that field or use it when +creating a ``TaggedItem``:: + + >>> from django.contrib.models.auth import User + >>> guido = User.objects.get(username='Guido') + >>> t = TaggedItem(content_object=guido, tag='bdfl') + >>> t.save() + >>> t.content_object + <User: Guido> + +Reverse generic relations +------------------------- + +If you know which models you'll be using most often, you can also add +a "reverse" generic relationship to enable an additional API. For example:: + + class Bookmark(models.Model): + url = models.URLField() + tags = generic.GenericRelation(TaggedItem) + +``Bookmark`` instances will each have a ``tags`` attribute, which can +be used to retrieve their associated ``TaggedItems``:: + + >>> b = Bookmark('http://www.djangoproject.com/') + >>> b.save() + >>> t1 = TaggedItem(content_object=b, tag='django') + >>> t1.save() + >>> t2 = TaggedItem(content_object=b, tag='python') + >>> t2.save() + >>> b.tags.all() + [<TaggedItem: django>, <TaggedItem: python>] + +If you don't add the reverse relationship, you can do the lookup manually:: + + >>> b = Bookmark.objects.get(url='http://www.djangoproject.com/) + >>> bookmark_type = ContentType.objects.get_for_model(b) + >>> TaggedItem.objects.filter(content_type__pk=bookmark_type.id, + ... object_id=b.id) + [<TaggedItem: django>, <TaggedItem: python>] + +Note that if you delete an object that has a ``GenericRelation``, any objects +which have a ``GenericForeignKey`` pointing at it will be deleted as well. In +the example above, this means that if a ``Bookmark`` object were deleted, any +``TaggedItem`` objects pointing at it would be deleted at the same time. diff --git a/docs/contributing.txt b/docs/contributing.txt index b0df62fe99..3200a87012 100644 --- a/docs/contributing.txt +++ b/docs/contributing.txt @@ -112,6 +112,61 @@ Submitting patches We're always grateful for patches to Django's code. Indeed, bug reports with associated patches will get fixed *far* more quickly than those without patches. +"Claiming" tickets +------------------ + +In an open-source project with hundreds of contributors around the world, it's +important to manage communication efficiently so that work doesn't get +duplicated and contributors can be as effective as possible. Hence, our policy +is for contributors to "claim" tickets in order to let other developers know +that a particular bug or feature is being worked on. + +If you have identified a contribution you want to make and you're capable of +fixing it (as measured by your coding ability, knowledge of Django internals +and time availability), claim it by following these steps: + + * `Create an account`_ to use in our ticket system. + * If a ticket for this issue doesn't exist yet, create one in our + `ticket tracker`_. + * If a ticket for this issue already exists, make sure nobody else has + claimed it. To do this, look at the "Assigned to" section of the ticket. + If it's assigned to "nobody," then it's available to be claimed. + Otherwise, somebody else is working on this ticket, and you either find + another bug/feature to work on, or contact the developer working on the + ticket to offer your help. + * Log into your account, if you haven't already, by clicking "Login" in the + upper right of the ticket page. + * Claim the ticket by clicking the radio button next to "Accept ticket" + near the bottom of the page, then clicking "Submit changes." + +.. _Create an account: http://www.djangoproject.com/accounts/register/ + +Ticket claimers' responsibility +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Once you've claimed a ticket, you have a responsibility to work on that ticket +in a reasonably timely fashion. If you don't have time to work on it, either +unclaim it or don't claim it in the first place! + +Core Django developers go through the list of claimed tickets from time to +time, checking whether any progress has been made. If there's no sign of +progress on a particular claimed ticket for a week or two after it's been +claimed, we will unclaim it for you so that it's no longer monopolized and +somebody else can claim it. + +If you've claimed a ticket and it's taking a long time (days or weeks) to code, +keep everybody updated by posting comments on the ticket. That way, we'll know +not to unclaim it. More communication is better than less communication! + +Which tickets should be claimed? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Of course, going through the steps of claiming tickets is overkill in some +cases. In the case of small changes, such as typos in the documentation or +small bugs that will only take a few minutes to fix, you don't need to jump +through the hoops of claiming tickets. Just submit your patch and be done with +it. + Patch style ----------- @@ -122,6 +177,11 @@ Patch style English than in code. Indentation is the most common example; it's hard to read patches when the only difference in code is that it's indented. + * When creating patches, always run ``svn diff`` from the top-level + ``trunk`` directory -- i.e., the one that contains ``django``, ``docs``, + ``tests``, ``AUTHORS``, etc. This makes it easy for other people to apply + your patches. + * Attach patches to a ticket in the `ticket tracker`_, using the "attach file" button. Please *don't* put the patch in the ticket description or comment unless it's a single line patch. @@ -412,6 +472,44 @@ Documentation style We place a high importance on consistency and readability of documentation. (After all, Django was created in a journalism environment!) +How to document new features +---------------------------- + +We treat our documentation like we treat our code: we aim to improve it as +often as possible. This section explains how writers can craft their +documentation changes in the most useful and least error-prone ways. + +Documentation changes come in two forms: + + * General improvements -- Typo corrections, error fixes and better + explanations through clearer writing and more examples. + + * New features -- Documentation of features that have been added to the + framework since the last release. + +Our philosophy is that "general improvements" are something that *all* current +Django users should benefit from, including users of trunk *and* users of the +latest release. Hence, the documentation section on djangoproject.com points +people by default to the newest versions of the docs, because they have the +latest and greatest content. (In fact, the Web site pulls directly from the +Subversion repository, converting to HTML on the fly.) + +But this decision to feature bleeding-edge documentation has one large caveat: +any documentation of *new* features will be seen by Django users who don't +necessarily have access to those features yet, because they're only using the +latest release. Thus, our policy is: + + **All documentation of new features should be written in a way that clearly + designates the features are only available in the Django development + version. Assume documentation readers are using the latest release, not the + development version.** + +Our traditional way of marking new features is by prefacing the features' +documentation with: "New in Django development version." Changes aren't +*required* to include this exact text, but all documentation of new features +should include the phrase "development version," so we can find and remove +those phrases for the next release. + Guidelines for ReST files ------------------------- @@ -556,10 +654,31 @@ info, with the ``DATABASE_ENGINE`` setting. You will also need a ``ROOT_URLCONF` setting (its value is ignored; it just needs to be present) and a ``SITE_ID`` setting (any non-zero integer value will do) in order for all the tests to pass. -The unit tests will not touch your existing databases; they create a new -database, called ``django_test_db``, which is deleted when the tests are -finished. This means your user account needs permission to execute ``CREATE -DATABASE``. +If you're using the ``sqlite3`` database backend, no further settings are +needed. A temporary database will be created in memory when running the tests. + +If you're using another backend: + + * Your ``DATABASE_USER`` setting needs to specify an existing user account + for the database engine. + + * The ``DATABASE_NAME`` setting must be the name of an existing database to + which the given user has permission to connect. The unit tests will not + touch this database; the test runner creates a new database whose name is + ``DATABASE_NAME`` prefixed with ``test_``, and this test database is + deleted when the tests are finished. This means your user account needs + permission to execute ``CREATE DATABASE``. + +To run a subset of the unit tests, append the names of the test modules to the +``runtests.py`` command line. See the list of directories in +``tests/modeltests`` and ``tests/regressiontests`` for module names. + +As an example, if Django is not in your ``PYTHONPATH``, you placed +``settings.py`` in the ``tests/`` directory, and you'd like to only run tests +for generic relations and internationalization, type:: + + PYTHONPATH=.. + ./runtests.py --settings=settings generic_relations i18n Requesting features =================== diff --git a/docs/databases.txt b/docs/databases.txt index ed0cb61bc3..21ff4c7434 100644 --- a/docs/databases.txt +++ b/docs/databases.txt @@ -117,7 +117,7 @@ Here's a sample configuration which uses a MySQL option file:: [client] database = DATABASE_NAME user = DATABASE_USER - passwd = DATABASE_PASSWORD + password = DATABASE_PASSWORD default-character-set = utf8 Several other MySQLdb connection options may be useful, such as ``ssl``, diff --git a/docs/databrowse.txt b/docs/databrowse.txt index 81e9e8e83b..72e1c71720 100644 --- a/docs/databrowse.txt +++ b/docs/databrowse.txt @@ -58,4 +58,29 @@ How to use Databrowse 4. Run the Django server and visit ``/databrowse/`` in your browser. +Requiring user login +==================== + +You can restrict access to logged-in users with only a few extra lines of +code. Simply add the following import to your URLconf:: + + from django.contrib.auth.decorators import login_required + +Then modify the URLconf so that the ``databrowse.site.root`` view is decorated +with ``login_required``:: + + (r'^databrowse/(.*)', login_required(databrowse.site.root)), + +If you haven't already added support for user logins to your URLconf, as +described in the `user authentication docs`_, then you will need to do so +now with the following mapping:: + + (r'^accounts/login/$', 'django.contrib.auth.views.login'), + +The final step is to create the login form required by +``django.contrib.auth.views.login``. The `user authentication docs`_ +provide full details and a sample template that can be used for this +purpose. + .. _template loader docs: ../templates_python/#loader-types +.. _user authentication docs: ../authentication/ diff --git a/docs/db-api.txt b/docs/db-api.txt index 3198f335c4..08b5391e3c 100644 --- a/docs/db-api.txt +++ b/docs/db-api.txt @@ -160,7 +160,7 @@ When you save an object, Django performs the following steps: is used to provide notification that an object has been successfully saved. (These signals are not yet documented.) -Raw Saves +Raw saves ~~~~~~~~~ **New in Django development version** @@ -481,7 +481,7 @@ In SQL terms, that evaluates to:: WHERE NOT (pub_date > '2005-1-3' AND headline = 'Hello') This example excludes all entries whose ``pub_date`` is later than 2005-1-3 -AND whose headline is NOT "Hello":: +OR whose headline is "Hello":: Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3)).exclude(headline='Hello') @@ -511,6 +511,9 @@ like so:: Entry.objects.order_by('?') +Note: ``order_by('?')`` queries may be expensive and slow, depending on the +database backend you're using. + To order by a field in a different table, add the other table's name and a dot, like so:: @@ -799,6 +802,9 @@ of the arguments is required, but you should use at least one of them. Entry.objects.extra(where=['headline=%s'], params=['Lennon']) + The combined number of placeholders in the list of strings for ``select`` + or ``where`` should equal the number of values in the ``params`` list. + QuerySet methods that do not return QuerySets --------------------------------------------- @@ -945,6 +951,23 @@ Example:: If you pass ``in_bulk()`` an empty list, you'll get an empty dictionary. +``iterator()`` +~~~~~~~~~~~~ + +Evaluates the ``QuerySet`` (by performing the query) and returns an +`iterator`_ over the results. A ``QuerySet`` typically reads all of +its results and instantiates all of the corresponding objects the +first time you access it; ``iterator()`` will instead read results and +instantiate objects in discrete chunks, yielding them one at a +time. For a ``QuerySet`` which returns a large number of objects, this +often results in better performance and a significant reduction in +memory use. + +Note that using ``iterator()`` on a ``QuerySet`` which has already +been evaluated will force it to evaluate again, repeating the query. + +.. _iterator: http://www.python.org/dev/peps/pep-0234/ + ``latest(field_name=None)`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/distributions.txt b/docs/distributions.txt index f9b9cbe9f8..d65e047276 100644 --- a/docs/distributions.txt +++ b/docs/distributions.txt @@ -15,6 +15,18 @@ repository. .. _installing the development version: ../install/#installing-the-development-version +FreeBSD +======= + +The `FreeBSD`_ ports system offers both Django 0.96 (`py-django`_) and a more +recent, but not current, version based on Django's trunk (`py-django-devel`_). +These are installed in the normal FreeBSD way; for Django 0.96, for example, type: +``cd /usr/ports/www/py-django && sudo make install clean``. + +.. _FreeBSD: http://www.freebsd.org/ +.. _py-django: http://www.freebsd.org/cgi/cvsweb.cgi/ports/www/py-django/ +.. _py-django-devel: http://www.freebsd.org/cgi/cvsweb.cgi/ports/www/py-django-devel/ + Linux distributions =================== @@ -33,17 +45,6 @@ plan to use with Django. .. _Debian GNU/Linux: http://www.debian.org/ .. _packaged version of Django: http://packages.debian.org/stable/python/python-django -Ubuntu ------- - -The Debian ``python-django`` package is also available for `Ubuntu Linux`_, in -the "universe" repository for Ubuntu 7.04 ("Feisty Fawn"). The `current Ubuntu -package`_ is also based on Django 0.95.1 and can be installed in the same -fashion as for Debian. - -.. _Ubuntu Linux: http://www.ubuntu.com/ -.. _current Ubuntu package: http://packages.ubuntu.com/feisty/python/python-django - Fedora ------ @@ -65,6 +66,18 @@ The `current Gentoo build`_ can be installed by typing ``emerge django``. .. _Gentoo Linux: http://www.gentoo.org/ .. _current Gentoo build: http://packages.gentoo.org/packages/?category=dev-python;name=django +Ubuntu +------ + +The Debian ``python-django`` package is also available for `Ubuntu Linux`_, in +the "universe" repository for Ubuntu 7.04 ("Feisty Fawn"). The `current Ubuntu +package`_ is also based on Django 0.95.1 and can be installed in the same +fashion as for Debian. + +.. _Ubuntu Linux: http://www.ubuntu.com/ +.. _current Ubuntu package: http://packages.ubuntu.com/feisty/python/python-django + + Mac OS X ======== diff --git a/docs/django-admin.txt b/docs/django-admin.txt index e3d1067dd3..0f99987bad 100644 --- a/docs/django-admin.txt +++ b/docs/django-admin.txt @@ -35,39 +35,61 @@ be consistent, but any example can use ``manage.py`` just as well. Usage ===== -``django-admin.py action [options]`` +``django-admin.py <subcommand> [options]`` -``manage.py action [options]`` +``manage.py <subcommand> [options]`` -``action`` should be one of the actions listed in this document. ``options``, -which is optional, should be zero or more of the options listed in this -document. +``subcommand`` should be one of the subcommands listed in this document. +``options``, which is optional, should be zero or more of the options available +for the given subcommand. -Run ``django-admin.py --help`` to display a help message that includes a terse -list of all available actions and options. +Getting runtime help +-------------------- -Most actions take a list of ``appname``s. An ``appname`` is the basename of the -package containing your models. For example, if your ``INSTALLED_APPS`` -contains the string ``'mysite.blog'``, the ``appname`` is ``blog``. +In Django 0.96, run ``django-admin.py --help`` to display a help message that +includes a terse list of all available subcommands and options. -Available actions -================= +In the Django development version, run ``django-admin.py help`` to display a +list of all available subcommands. Run ``django-admin.py help <subcommand>`` +to display a description of the given subcommand and a list of its available +options. + +App names +--------- + +Many subcommands take a list of "app names." An "app name" is the basename of +the package containing your models. For example, if your ``INSTALLED_APPS`` +contains the string ``'mysite.blog'``, the app name is ``blog``. + +Determining the version +----------------------- + +Run ``django-admin.py --version`` to display the current Django version. -adminindex [appname appname ...] +Examples of output:: + + 0.95 + 0.96 + 0.97-pre-SVN-6069 + +Available subcommands +===================== + +adminindex <appname appname ...> -------------------------------- -Prints the admin-index template snippet for the given appnames. +Prints the admin-index template snippet for the given app name(s). Use admin-index template snippets if you want to customize the look and feel of your admin's index page. See `Tutorial 2`_ for more information. .. _Tutorial 2: ../tutorial02/ -createcachetable [tablename] +createcachetable <tablename> ---------------------------- Creates a cache table named ``tablename`` for use with the database cache -backend. See the `cache documentation`_ for more information. +backend. See the `cache documentation`_ for more information. .. _cache documentation: ../cache/ @@ -100,26 +122,44 @@ example, the default settings don't define ``ROOT_URLCONF``, so Note that Django's default settings live in ``django/conf/global_settings.py``, if you're ever curious to see the full list of defaults. -dumpdata [appname appname ...] +dumpdata <appname appname ...> ------------------------------ -Output to standard output all data in the database associated with the named +Outputs to standard output all data in the database associated with the named application(s). -By default, the database will be dumped in JSON format. If you want the output -to be in another format, use the ``--format`` option (e.g., ``format=xml``). -You may specify any Django serialization backend (including any user specified -serialization backends named in the ``SERIALIZATION_MODULES`` setting). The -``--indent`` option can be used to pretty-print the output. - If no application name is provided, all installed applications will be dumped. The output of ``dumpdata`` can be used as input for ``loaddata``. +--format +~~~~~~~~ + +By default, ``dumpdata`` will format its output in JSON, but you can use the +``--format`` option to specify another format. Currently supported formats are +listed in `Serialization formats`_. + +Example usage:: + + django-admin.py dumpdata --format=xml + +.. _Serialization formats: ../serialization/#serialization-formats + +--indent +~~~~~~~~ + +By default, ``dumpdata`` will output all data on a single line. This isn't easy +for humans to read, so you can use the ``--indent`` option to pretty-print the +output with a number of indentation spaces. + +Example usage:: + + django-admin.py dumpdata --indent=4 + flush ----- -Return the database to the state it was in immediately after syncdb was +Returns the database to the state it was in immediately after syncdb was executed. This means that all data will be removed from the database, any post-synchronization handlers will be re-executed, and the ``initial_data`` fixture will be re-installed. @@ -131,6 +171,27 @@ models and/or weren't in ``INSTALLED_APPS``). Now, the command only clears tables that are represented by Django models and are activated in ``INSTALLED_APPS``. +--noinput +~~~~~~~~~ + +Use the ``--noinput`` option to suppress all user prompting, such as +"Are you sure?" confirmation messages. This is useful if ``django-admin.py`` +is being executed as an unattended, automated script. + +--verbosity +~~~~~~~~~~~ + +Use ``--verbosity`` to specify the amount of notification and debug information +that ``django-admin.py`` should print to the console. + + * ``0`` means no input. + * ``1`` means normal input (default). + * ``2`` means verbose input. + +Example usage:: + + django-admin.py flush --verbosity=2 + inspectdb --------- @@ -172,15 +233,14 @@ needed. ``inspectdb`` works with PostgreSQL, MySQL and SQLite. Foreign-key detection only works in PostgreSQL and with certain types of MySQL tables. -loaddata [fixture fixture ...] +loaddata <fixture fixture ...> ------------------------------ Searches for and loads the contents of the named fixture into the database. -A *Fixture* is a collection of files that contain the serialized contents of -the database. Each fixture has a unique name; however, the files that -comprise the fixture can be distributed over multiple directories, in -multiple applications. +A *fixture* is a collection of files that contain the serialized contents of +the database. Each fixture has a unique name, and the files that comprise the +fixture can be distributed over multiple directories, in multiple applications. Django will search in three locations for fixtures: @@ -240,16 +300,37 @@ The ``dumpdata`` command can be used to generate input for ``loaddata``. references in your data files - MySQL doesn't provide a mechanism to defer checking of row constraints until a transaction is committed. -reset [appname appname ...] +--verbosity +~~~~~~~~~~~ + +Use ``--verbosity`` to specify the amount of notification and debug information +that ``django-admin.py`` should print to the console. + + * ``0`` means no input. + * ``1`` means normal input (default). + * ``2`` means verbose input. + +Example usage:: + + django-admin.py loaddata --verbosity=2 + +reset <appname appname ...> --------------------------- -Executes the equivalent of ``sqlreset`` for the given appnames. +Executes the equivalent of ``sqlreset`` for the given app name(s). + +--noinput +~~~~~~~~~ + +Use the ``--noinput`` option to suppress all user prompting, such as +"Are you sure?" confirmation messages. This is useful if ``django-admin.py`` +is being executed as an unattended, automated script. runfcgi [options] ----------------- -Starts a set of FastCGI processes suitable for use with any web server -which supports the FastCGI protocol. See the `FastCGI deployment +Starts a set of FastCGI processes suitable for use with any Web server +that supports the FastCGI protocol. See the `FastCGI deployment documentation`_ for details. Requires the Python FastCGI module from `flup`_. @@ -289,8 +370,36 @@ machines on your network. To make your development server viewable to other machines on the network, use its own IP address (e.g. ``192.168.2.1``) or ``0.0.0.0``. -Examples: -~~~~~~~~~ +--adminmedia +~~~~~~~~~~~~ + +Use the ``--adminmedia`` option to tell Django where to find the various CSS +and JavaScript files for the Django admin interface. Normally, the development +server serves these files out of the Django source tree magically, but you'd +want to use this if you made any changes to those files for your own site. + +Example usage:: + + django-admin.py runserver --adminmedia=/tmp/new-admin-style/ + +--noreload +~~~~~~~~~~ + +Use the ``--noreload`` option to disable the use of the auto-reloader. This +means any Python code changes you make while the server is running will *not* +take effect if the particular Python modules have already been loaded into +memory. + +Examples of using different ports and addresses +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Port 8000 on IP address 127.0.0.1:: + + django-admin.py runserver + +Port 8000 on IP address 1.2.3.4:: + + django-admin.py runserver 1.2.3.4:8000 Port 7000 on IP address 127.0.0.1:: @@ -331,31 +440,31 @@ option, like so:: .. _IPython: http://ipython.scipy.org/ -sql [appname appname ...] +sql <appname appname ...> ------------------------- -Prints the CREATE TABLE SQL statements for the given appnames. +Prints the CREATE TABLE SQL statements for the given app name(s). -sqlall [appname appname ...] +sqlall <appname appname ...> ---------------------------- -Prints the CREATE TABLE and initial-data SQL statements for the given appnames. +Prints the CREATE TABLE and initial-data SQL statements for the given app name(s). Refer to the description of ``sqlcustom`` for an explanation of how to specify initial data. -sqlclear [appname appname ...] +sqlclear <appname appname ...> ------------------------------ -Prints the DROP TABLE SQL statements for the given appnames. +Prints the DROP TABLE SQL statements for the given app name(s). -sqlcustom [appname appname ...] +sqlcustom <appname appname ...> ------------------------------- -Prints the custom SQL statements for the given appnames. +Prints the custom SQL statements for the given app name(s). For each model in each specified app, this command looks for the file -``<appname>/sql/<modelname>.sql``, where ``<appname>`` is the given appname and +``<appname>/sql/<modelname>.sql``, where ``<appname>`` is the given app name and ``<modelname>`` is the model's name in lowercase. For example, if you have an app ``news`` that includes a ``Story`` model, ``sqlcustom`` will attempt to read a file ``news/sql/story.sql`` and append it to the output of this @@ -373,31 +482,30 @@ sqlflush Prints the SQL statements that would be executed for the `flush`_ command. -sqlindexes [appname appname ...] +sqlindexes <appname appname ...> -------------------------------- -Prints the CREATE INDEX SQL statements for the given appnames. +Prints the CREATE INDEX SQL statements for the given app name(s). -sqlreset [appname appname ...] +sqlreset <appname appname ...> ------------------------------ -Prints the DROP TABLE SQL, then the CREATE TABLE SQL, for the given appnames. +Prints the DROP TABLE SQL, then the CREATE TABLE SQL, for the given app name(s). -sqlsequencereset [appname appname ...] +sqlsequencereset <appname appname ...> -------------------------------------- -Prints the SQL statements for resetting sequences for the given -appnames. +Prints the SQL statements for resetting sequences for the given app name(s). See http://simon.incutio.com/archive/2004/04/21/postgres for more information. -startapp [appname] +startapp <appname> ------------------ Creates a Django app directory structure for the given app name in the current directory. -startproject [projectname] +startproject <projectname> -------------------------- Creates a Django project directory structure for the given project name in the @@ -435,14 +543,57 @@ with an appropriate extension (e.g. ``json`` or ``xml``). See the documentation for ``loaddata`` for details on the specification of fixture data files. +--verbosity +~~~~~~~~~~~ + +Use ``--verbosity`` to specify the amount of notification and debug information +that ``django-admin.py`` should print to the console. + + * ``0`` means no input. + * ``1`` means normal input (default). + * ``2`` means verbose input. + +Example usage:: + + django-admin.py syncdb --verbosity=2 + +--noinput +~~~~~~~~~ + +Use the ``--noinput`` option to suppress all user prompting, such as +"Are you sure?" confirmation messages. This is useful if ``django-admin.py`` +is being executed as an unattended, automated script. + test ---- -Discover and run tests for all installed models. See `Testing Django applications`_ for more information. +Runs tests for all installed models. See `Testing Django applications`_ +for more information. .. _testing Django applications: ../testing/ -testserver [fixture fixture ...] +--noinput +~~~~~~~~~ + +Use the ``--noinput`` option to suppress all user prompting, such as +"Are you sure?" confirmation messages. This is useful if ``django-admin.py`` +is being executed as an unattended, automated script. + +--verbosity +~~~~~~~~~~~ + +Use ``--verbosity`` to specify the amount of notification and debug information +that ``django-admin.py`` should print to the console. + + * ``0`` means no input. + * ``1`` means normal input (default). + * ``2`` means verbose input. + +Example usage:: + + django-admin.py test --verbosity=2 + +testserver <fixture fixture ...> -------------------------------- **New in Django development version** @@ -476,125 +627,90 @@ This is useful in a number of ways: in any way, knowing that whatever data changes you're making are only being made to a test database. -Note that this server can only run on the default port on localhost; it does -not yet accept a ``host`` or ``port`` parameter. - -Also note that it does *not* automatically detect changes to your Python source -code (as ``runserver`` does). It does, however, detect changes to templates. +Note that this server does *not* automatically detect changes to your Python +source code (as ``runserver`` does). It does, however, detect changes to +templates. .. _unit tests: ../testing/ -validate --------- +--addrport [port number or ipaddr:port] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Validates all installed models (according to the ``INSTALLED_APPS`` setting) -and prints validation errors to standard output. +Use ``--addrport`` to specify a different port, or IP address and port, from +the default of 127.0.0.1:8000. This value follows exactly the same format and +serves exactly the same function as the argument to the ``runserver`` subcommand. -Available options -================= +Examples: ---settings ----------- +To run the test server on port 7000 with ``fixture1`` and ``fixture2``:: -Example usage:: + django-admin.py testserver --addrport 7000 fixture1 fixture2 + django-admin.py testserver fixture1 fixture2 --addrport 7000 - django-admin.py syncdb --settings=mysite.settings +(The above statements are equivalent. We include both of them to demonstrate +that it doesn't matter whether the options come before or after the fixture +arguments.) -Explicitly specifies the settings module to use. The settings module should be -in Python package syntax, e.g. ``mysite.settings``. If this isn't provided, -``django-admin.py`` will use the ``DJANGO_SETTINGS_MODULE`` environment -variable. +To run on 1.2.3.4:7000 with a `test` fixture:: -Note that this option is unnecessary in ``manage.py``, because it takes care of -setting ``DJANGO_SETTINGS_MODULE`` for you. + django-admin.py testserver --addrport 1.2.3.4:7000 test ---pythonpath ------------- - -Example usage:: +--verbosity +~~~~~~~~~~~ - django-admin.py syncdb --pythonpath='/home/djangoprojects/myproject' +Use ``--verbosity`` to specify the amount of notification and debug information +that ``django-admin.py`` should print to the console. -Adds the given filesystem path to the Python `import search path`_. If this -isn't provided, ``django-admin.py`` will use the ``PYTHONPATH`` environment -variable. + * ``0`` means no input. + * ``1`` means normal input (default). + * ``2`` means verbose input. -Note that this option is unnecessary in ``manage.py``, because it takes care of -setting the Python path for you. +Example usage:: -.. _import search path: http://diveintopython.org/getting_to_know_python/everything_is_an_object.html + django-admin.py testserver --verbosity=2 ---format +validate -------- -Example usage:: - - django-admin.py dumpdata --format=xml +Validates all installed models (according to the ``INSTALLED_APPS`` setting) +and prints validation errors to standard output. -Specifies the output format that will be used. The name provided must be the name -of a registered serializer. +Default options +=============== ---help ------- +Although some subcommands may allow their own custom options, every subcommand +allows for the following options: -Displays a help message that includes a terse list of all available actions and -options. - ---indent --------- +--pythonpath +------------ Example usage:: - django-admin.py dumpdata --indent=4 + django-admin.py syncdb --pythonpath='/home/djangoprojects/myproject' -Specifies the number of spaces that will be used for indentation when -pretty-printing output. By default, output will *not* be pretty-printed. -Pretty-printing will only be enabled if the indent option is provided. +Adds the given filesystem path to the Python `import search path`_. If this +isn't provided, ``django-admin.py`` will use the ``PYTHONPATH`` environment +variable. ---noinput ---------- +Note that this option is unnecessary in ``manage.py``, because it takes care of +setting the Python path for you. -Inform django-admin that the user should NOT be prompted for any input. Useful -if the django-admin script will be executed as an unattended, automated -script. +.. _import search path: http://diveintopython.org/getting_to_know_python/everything_is_an_object.html ---noreload +--settings ---------- -Disable the use of the auto-reloader when running the development server. - ---version ---------- - -Displays the current Django version. - -Example output:: - - 0.9.1 - 0.9.1 (SVN) - ---verbosity ------------ - Example usage:: - django-admin.py syncdb --verbosity=2 - -Verbosity determines the amount of notification and debug information that -will be printed to the console. '0' is no output, '1' is normal output, -and ``2`` is verbose output. - ---adminmedia ------------- - -Example usage:: + django-admin.py syncdb --settings=mysite.settings - django-admin.py --adminmedia=/tmp/new-admin-style/ +Explicitly specifies the settings module to use. The settings module should be +in Python package syntax, e.g. ``mysite.settings``. If this isn't provided, +``django-admin.py`` will use the ``DJANGO_SETTINGS_MODULE`` environment +variable. -Tells Django where to find the various CSS and JavaScript files for the admin -interface when running the development server. Normally these files are served -out of the Django source tree, but because some designers customize these files -for their site, this option allows you to test against custom versions. +Note that this option is unnecessary in ``manage.py``, because it takes care of +setting ``DJANGO_SETTINGS_MODULE`` for you. Extra niceties ============== diff --git a/docs/email.txt b/docs/email.txt index 97bdec0037..2bad79ce33 100644 --- a/docs/email.txt +++ b/docs/email.txt @@ -100,31 +100,31 @@ mail_admins() ============= ``django.core.mail.mail_admins()`` is a shortcut for sending an e-mail to the -site admins, as defined in the `ADMINS setting`_. Here's the definition:: +site admins, as defined in the `ADMINS`_ setting. Here's the definition:: mail_admins(subject, message, fail_silently=False) ``mail_admins()`` prefixes the subject with the value of the -`EMAIL_SUBJECT_PREFIX setting`_, which is ``"[Django] "`` by default. +`EMAIL_SUBJECT_PREFIX`_ setting, which is ``"[Django] "`` by default. -The "From:" header of the e-mail will be the value of the `SERVER_EMAIL setting`_. +The "From:" header of the e-mail will be the value of the `SERVER_EMAIL`_ setting. This method exists for convenience and readability. -.. _ADMINS setting: ../settings/#admins -.. _EMAIL_SUBJECT_PREFIX setting: ../settings/#email-subject-prefix -.. _SERVER_EMAIL setting: ../settings/#server-email +.. _ADMINS: ../settings/#admins +.. _EMAIL_SUBJECT_PREFIX: ../settings/#email-subject-prefix +.. _SERVER_EMAIL: ../settings/#server-email mail_managers() function ======================== ``django.core.mail.mail_managers()`` is just like ``mail_admins()``, except it -sends an e-mail to the site managers, as defined in the `MANAGERS setting`_. +sends an e-mail to the site managers, as defined in the `MANAGERS`_ setting. Here's the definition:: mail_managers(subject, message, fail_silently=False) -.. _MANAGERS setting: ../settings/#managers +.. _MANAGERS: ../settings/#managers Examples ======== @@ -225,7 +225,7 @@ optional and can be set at any time prior to calling the ``send()`` method. * ``from_email``: The sender's address. Both ``fred@example.com`` and ``Fred <fred@example.com>`` forms are legal. If omitted, the - ``DEFAULT_FROM_EMAIL`` setting is used. + `DEFAULT_FROM_EMAIL`_ setting is used. * ``to``: A list or tuple of recipient addresses. @@ -297,6 +297,8 @@ The class has the following methods: message.attach_file('/images/weather_map.png') +.. _DEFAULT_FROM_EMAIL: ../settings/#default-from-email + Sending alternative content types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -328,7 +330,7 @@ attribute on the ``EmailMessage`` class to change the main content type. The major type will always be ``"text"``, but you can change it to the subtype. For example:: - msg = EmailMessage(subject, html_content, from_email, to) + msg = EmailMessage(subject, html_content, from_email, [to]) msg.content_subtype = "html" # Main content is now text/html msg.send() diff --git a/docs/fastcgi.txt b/docs/fastcgi.txt index dff1689905..78ee9d408c 100644 --- a/docs/fastcgi.txt +++ b/docs/fastcgi.txt @@ -46,9 +46,8 @@ Prerequisite: flup ================== Before you can start using FastCGI with Django, you'll need to install flup_, -which is a Python library for dealing with FastCGI. Make sure to use the latest -Subversion snapshot of flup, as some users have reported stalled pages with -older flup versions. +which is a Python library for dealing with FastCGI. Version 0.5 or newer should +work fine. .. _flup: http://www.saddi.com/software/flup/ @@ -113,7 +112,7 @@ Running a preforked server on a Unix domain socket:: Run without daemonizing (backgrounding) the process (good for debugging):: - ./manage.py runfcgi daemonize=false socket=/tmp/mysite.sock + ./manage.py runfcgi daemonize=false socket=/tmp/mysite.sock maxrequests=1 Stopping the FastCGI daemon --------------------------- diff --git a/docs/form_preview.txt b/docs/form_preview.txt new file mode 100644 index 0000000000..4be7b07a74 --- /dev/null +++ b/docs/form_preview.txt @@ -0,0 +1,97 @@ +============ +Form preview +============ + +Django comes with an optional "form preview" application that helps automate +the following workflow: + +"Display an HTML form, force a preview, then do something with the submission." + +To force a preview of a form submission, all you have to do is write a short +Python class. + +Overview +========= + +Given a ``django.newforms.Form`` subclass that you define, this application +takes care of the following workflow: + + 1. Displays the form as HTML on a Web page. + 2. Validates the form data when it's submitted via POST. + a. If it's valid, displays a preview page. + b. If it's not valid, redisplays the form with error messages. + 3. When the "confirmation" form is submitted from the preview page, calls + a hook that you define -- a ``done()`` method that gets passed the valid + data. + +The framework enforces the required preview by passing a shared-secret hash to +the preview page via hidden form fields. If somebody tweaks the form parameters +on the preview page, the form submission will fail the hash-comparison test. + +How to use ``FormPreview`` +========================== + + 1. Point Django at the default FormPreview templates. There are two ways to + do this: + + * Add ``'django.contrib.formtools'`` to your ``INSTALLED_APPS`` + setting. This will work if your ``TEMPLATE_LOADERS`` setting includes + the ``app_directories`` template loader (which is the case by + default). See the `template loader docs`_ for more. + + * Otherwise, determine the full filesystem path to the + ``django/contrib/formtools/templates`` directory, and add that + directory to your ``TEMPLATE_DIRS`` setting. + + 2. Create a ``FormPreview`` subclass that overrides the ``done()`` method:: + + from django.contrib.formtools import FormPreview + from myapp.models import SomeModel + + class SomeModelFormPreview(FormPreview): + + def done(self, request, cleaned_data): + # Do something with the cleaned_data, then redirect + # to a "success" page. + return HttpResponseRedirect('/form/success') + + 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`` that is the end result of the form being + submitted. + + 3. Change your URLconf to point to an instance of your ``FormPreview`` + subclass:: + + from myapp.preview import SomeModelFormPreview + from myapp.models import SomeModel + from django import newforms as forms + + ...and add the following line to the appropriate model in your URLconf:: + + (r'^post/$', SomeModelFormPreview(forms.models.form_for_model(SomeModel))), + + Or, if you already have a Form class defined for the model:: + + (r'^post/$', SomeModelFormPreview(SomeModelForm)), + + 4. Run the Django server and visit ``/post/`` in your browser. + +.. _template loader docs: ../templates_python/#loader-types + +``FormPreview`` classes +======================= + +A ``FormPreview`` class is a simple Python class that represents the preview +workflow. ``FormPreview`` classes must subclass +``django.contrib.formtools.preview.FormPreview`` and override the ``done()`` +method. They can live anywhere in your codebase. + +``FormPreview`` templates +========================= + +By default, the form is rendered via the template ``formtools/form.html``, and +the preview page is rendered via the template ``formtools.preview.html``. +These values can be overridden for a particular form preview by setting +``preview_template`` and ``form_template`` attributes on the FormPreview +subclass. See ``django/contrib/formtools/templates`` for the default templates. diff --git a/docs/generic_views.txt b/docs/generic_views.txt index 0601aead11..87b82f7adf 100644 --- a/docs/generic_views.txt +++ b/docs/generic_views.txt @@ -201,6 +201,10 @@ a date in the *future* are not included unless you set ``allow_future`` to specified in ``date_field`` is greater than the current date/time. By default, this is ``False``. + * **New in Django development version:** ``template_object_name``: + Designates the name of the template variable to use in the template + context. By default, this is ``'latest'``. + **Template name:** If ``template_name`` isn't specified, this view will use the template @@ -221,10 +225,16 @@ In addition to ``extra_context``, the template's context will be: years that have objects available according to ``queryset``. These are ordered in reverse. This is equivalent to ``queryset.dates(date_field, 'year')[::-1]``. + * ``latest``: The ``num_latest`` objects in the system, ordered descending by ``date_field``. For example, if ``num_latest`` is ``10``, then ``latest`` will be a list of the latest 10 objects in ``queryset``. + **New in Django development version:** This variable's name depends on + the ``template_object_name`` parameter, which is ``'latest'`` by default. + If ``template_object_name`` is ``'foo'``, this variable's name will be + ``foo``. + .. _RequestContext docs: ../templates_python/#subclassing-context-requestcontext ``django.views.generic.date_based.archive_year`` @@ -688,9 +698,11 @@ A page representing a list of objects. * ``paginate_by``: An integer specifying how many objects should be displayed per page. If this is given, the view will paginate objects with ``paginate_by`` objects per page. The view will expect either a ``page`` - query string parameter (via ``GET``) containing a 1-based page - number, or a ``page`` variable specified in the URLconf. See - "Notes on pagination" below. + query string parameter (via ``GET``) or a ``page`` variable specified in + the URLconf. See `Notes on pagination`_ below. + + * ``page``: The current page number, as an integer. This is 1-based. + See `Notes on pagination`_ below. * ``template_name``: The full name of a template to use in rendering the page. This lets you override the default template name (see below). @@ -765,6 +777,9 @@ If the results are paginated, the context will contain these extra variables: * ``hits``: The total number of objects across *all* pages, not just this page. + * **New in Django development version:** ``page_range``: A list of the + page numbers that are available. This is 1-based. + Notes on pagination ~~~~~~~~~~~~~~~~~~~ @@ -777,12 +792,29 @@ specify the page number in the URL in one of two ways: (r'^objects/page(?P<page>[0-9]+)/$', 'object_list', dict(info_dict)) * Pass the page number via the ``page`` query-string parameter. For - example, a URL would look like this: + example, a URL would look like this:: /objects/?page=3 -In both cases, ``page`` is 1-based, not 0-based, so the first page would be -represented as page ``1``. + * To loop over all the available page numbers, use the ``page_range`` + variable. You can iterate over the list provided by ``page_range`` + to create a link to every page of results. + +These values and lists are is 1-based, not 0-based, so the first page would be +represented as page ``1``. + +**New in Django development version:** + +As a special case, you are also permitted to use +``last`` as a value for ``page``:: + + /objects/?page=last + +This allows you to access the final page of results without first having to +determine how many pages there are. + +Note that ``page`` *must* be either a valid page number or the value ``last``; +any other value for ``page`` will result in a 404 error. ``django.views.generic.list_detail.object_detail`` -------------------------------------------------- diff --git a/docs/i18n.txt b/docs/i18n.txt index 38252edeb1..bf73c88008 100644 --- a/docs/i18n.txt +++ b/docs/i18n.txt @@ -27,21 +27,8 @@ Essentially, Django does two things: * It uses these hooks to translate Web apps for particular users according to their language preferences. -How to internationalize your app: in three steps ------------------------------------------------- - - 1. Embed translation strings in your Python code and templates. - 2. Get translations for those strings, in whichever languages you want to - support. - 3. Activate the locale middleware in your Django settings. - -.. admonition:: Behind the scenes - - Django's translation machinery uses the standard ``gettext`` module that - comes with Python. - -If you don't need internationalization -====================================== +If you don't need internationalization in your app +================================================== Django's internationalization hooks are on by default, and that means there's a bit of i18n-related overhead in certain places of the framework. If you don't @@ -55,8 +42,21 @@ from your ``TEMPLATE_CONTEXT_PROCESSORS`` setting. .. _documentation for USE_I18N: ../settings/#use-i18n -How to specify translation strings -================================== +If you do need internationalization: three steps +================================================ + + 1. Embed translation strings in your Python code and templates. + 2. Get translations for those strings, in whichever languages you want to + support. + 3. Activate the locale middleware in your Django settings. + +.. admonition:: Behind the scenes + + Django's translation machinery uses the standard ``gettext`` module that + comes with Python. + +1. How to specify translation strings +===================================== Translation strings specify "This text should be translated." These strings can appear in your Python code and templates. It's your responsibility to mark @@ -295,7 +295,7 @@ string, so they don't need to be aware of translations. .. _Django templates: ../templates_python/ Working with lazy translation objects -===================================== +------------------------------------- Using ``ugettext_lazy()`` and ``ungettext_lazy()`` to mark strings in models and utility functions is a common operation. When you're working with these @@ -305,7 +305,7 @@ convert them to strings, because they should be converted as late as possible couple of helper functions. Joining strings: string_concat() --------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Standard Python string joins (``''.join([...])``) will not work on lists containing lazy translation objects. Instead, you can use @@ -324,7 +324,7 @@ strings when ``result`` itself is used in a string (usually at template rendering time). The allow_lazy() decorator --------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~ Django offers many utility functions (particularly in ``django.utils``) that take a string as their first argument and do something to that string. These @@ -359,8 +359,8 @@ Using this decorator means you can write your function and assume that the input is a proper string, then add support for lazy translation objects at the end. -How to create language files -============================ +2. How to create language files +=============================== Once you've tagged your strings for later translation, you need to write (or obtain) the language translations themselves. Here's how that works. @@ -393,7 +393,7 @@ To create or update a message file, run this command:: ...where ``de`` is the language code for the message file you want to create. The language code, in this case, is in locale format. For example, it's -``pt_BR`` for Brazilian Portugese and ``de_AT`` for Austrian German. +``pt_BR`` for Brazilian Portuguese and ``de_AT`` for Austrian German. The script should be run from one of three places: @@ -490,8 +490,8 @@ That's it. Your translations are ready for use. .. _Submitting and maintaining translations: ../contributing/ -How Django discovers language preference -======================================== +3. How Django discovers language preference +=========================================== Once you've prepared your translations -- or, if you just want to use the translations that come with Django -- you'll just need to activate translation @@ -546,7 +546,7 @@ following this algorithm: Notes: * In each of these places, the language preference is expected to be in the - standard language format, as a string. For example, Brazilian Portugese + standard language format, as a string. For example, Brazilian Portuguese is ``pt-br``. * If a base language is available but the sublanguage specified is not, Django uses the base language. For example, if a user specifies ``de-at`` @@ -629,44 +629,6 @@ in ``request.LANGUAGE_CODE``. .. _session: ../sessions/ .. _request object: ../request_response/#httprequest-objects -The ``set_language`` redirect view -================================== - -As a convenience, Django comes with a view, ``django.views.i18n.set_language``, -that sets a user's language preference and redirects back to the previous page. - -Activate this view by adding the following line to your URLconf:: - - (r'^i18n/', include('django.conf.urls.i18n')), - -(Note that this example makes the view available at ``/i18n/setlang/``.) - -The view expects to be called via the ``GET`` method, with a ``language`` -parameter set in the query string. If session support is enabled, the view -saves the language choice in the user's session. Otherwise, it saves the -language choice in a ``django_language`` cookie. - -After setting the language choice, Django redirects the user, following this -algorithm: - - * Django looks for a ``next`` parameter in the query string. - * If that doesn't exist, or is empty, Django tries the URL in the - ``Referer`` header. - * If that's empty -- say, if a user's browser suppresses that header -- - then the user will be redirected to ``/`` (the site root) as a fallback. - -Here's example HTML template code:: - - <form action="/i18n/setlang/" method="get"> - <input name="next" type="hidden" value="/next/page/" /> - <select name="language"> - {% for lang in LANGUAGES %} - <option value="{{ lang.0 }}">{{ lang.1 }}</option> - {% endfor %} - </select> - <input type="submit" value="Go" /> - </form> - Using translations in your own projects ======================================= @@ -707,8 +669,11 @@ To create message files, you use the same ``make-messages.py`` tool as with the Django message files. You only need to be in the right place -- in the directory where either the ``conf/locale`` (in case of the source tree) or the ``locale/`` (in case of app messages or project messages) directory are located. And you -use the same ``compile-messages.py`` to produce the binary ``django.mo`` files that -are used by ``gettext``. +use the same ``compile-messages.py`` to produce the binary ``django.mo`` files +that are used by ``gettext``. + +You can also run ``compile-message.py --settings=path.to.settings`` to make +the compiler process all the directories in your ``LOCALE_PATHS`` setting. Application message files are a bit complicated to discover -- they need the ``LocaleMiddleware``. If you don't use the middleware, only the Django message @@ -728,6 +693,44 @@ The easiest way out is to store applications that are not part of the project connected to your explicit project and not strings that are distributed independently. +The ``set_language`` redirect view +================================== + +As a convenience, Django comes with a view, ``django.views.i18n.set_language``, +that sets a user's language preference and redirects back to the previous page. + +Activate this view by adding the following line to your URLconf:: + + (r'^i18n/', include('django.conf.urls.i18n')), + +(Note that this example makes the view available at ``/i18n/setlang/``.) + +The view expects to be called via the ``POST`` method, with a ``language`` +parameter set in request. If session support is enabled, the view +saves the language choice in the user's session. Otherwise, it saves the +language choice in a ``django_language`` cookie. + +After setting the language choice, Django redirects the user, following this +algorithm: + + * Django looks for a ``next`` parameter in the ``POST`` data. + * If that doesn't exist, or is empty, Django tries the URL in the + ``Referrer`` header. + * If that's empty -- say, if a user's browser suppresses that header -- + then the user will be redirected to ``/`` (the site root) as a fallback. + +Here's example HTML template code:: + + <form action="/i18n/setlang/" method="post"> + <input name="next" type="hidden" value="/next/page/" /> + <select name="language"> + {% for lang in LANGUAGES %} + <option value="{{ lang.0 }}">{{ lang.1 }}</option> + {% endfor %} + </select> + <input type="submit" value="Go" /> + </form> + Translations and JavaScript =========================== @@ -752,7 +755,7 @@ The main solution to these problems is the ``javascript_catalog`` view, which sends out a JavaScript code library with functions that mimic the ``gettext`` interface, plus an array of translation strings. Those translation strings are taken from the application, project or Django core, according to what you -specify in either the {{{info_dict}}} or the URL. +specify in either the info_dict or the URL. You hook it up like this:: @@ -817,8 +820,8 @@ pluralizations). Creating JavaScript translation catalogs ---------------------------------------- -You create and update the translation catalogs the same way as the other Django -translation catalogs -- with the {{{make-messages.py}}} tool. The only +You create and update the translation catalogs the same way as the other +Django translation catalogs -- with the make-messages.py tool. The only difference is you need to provide a ``-d djangojs`` parameter, like this:: make-messages.py -d djangojs -l de @@ -827,13 +830,13 @@ This would create or update the translation catalog for JavaScript for German. After updating translation catalogs, just run ``compile-messages.py`` the same way as you do with normal Django translation catalogs. -Specialities of Django translation +Specialties of Django translation ================================== -If you know ``gettext``, you might note these specialities in the way Django +If you know ``gettext``, you might note these specialties in the way Django does translation: - * The string domain is ``django`` or ``djangojs``. The string domain is + * The string domain is ``django`` or ``djangojs``. This string domain is used to differentiate between different programs that store their data in a common message-file library (usually ``/usr/share/locale/``). The ``django`` domain is used for python and template translation strings @@ -841,5 +844,5 @@ does translation: domain is only used for JavaScript translation catalogs to make sure that those are as small as possible. * Django doesn't use ``xgettext`` alone. It uses Python wrappers around - ``xgettext`` and ``msgfmt``. That's mostly for convenience. + ``xgettext`` and ``msgfmt``. This is mostly for convenience. diff --git a/docs/install.txt b/docs/install.txt index 082000149f..2de8529d24 100644 --- a/docs/install.txt +++ b/docs/install.txt @@ -67,6 +67,16 @@ installed. * If you're using Oracle, you'll need cx_Oracle_, version 4.3.1 or higher. +If you plan to use Django's ``manage.py syncdb`` command to +automatically create database tables for your models, you'll need to +ensure that Django has permission to create tables in the database +you're using; if you plan to manually create the tables, you can +simply grant Django ``SELECT``, ``INSERT``, ``UPDATE`` and ``DELETE`` +permissions. Django does not issue ``ALTER TABLE`` statements, and so +will not require permission to do so. If you will be using Django's +`testing framework`_ with data fixtures, Django will need permission +to create a temporary test database. + .. _PostgreSQL: http://www.postgresql.org/ .. _MySQL: http://www.mysql.com/ .. _Django's ticket system: http://code.djangoproject.com/report/1 @@ -76,8 +86,9 @@ installed. .. _SQLite: http://www.sqlite.org/ .. _pysqlite: http://initd.org/tracker/pysqlite .. _MySQL backend: ../databases/ -.. _cx_Oracle: http://www.python.net/crew/atuining/cx_Oracle/ +.. _cx_Oracle: http://cx-oracle.sourceforge.net/ .. _Oracle: http://www.oracle.com/ +.. _testing framework: ../testing/ Remove any old versions of Django ================================= @@ -127,16 +138,24 @@ Installing an official release 1. Download the latest release from our `download page`_. - 2. Untar the downloaded file (e.g. ``tar xzvf Django-NNN.tar.gz``). + 2. Untar the downloaded file (e.g. ``tar xzvf Django-NNN.tar.gz``, + where ``NNN`` is the version number of the latest release). + If you're using Windows, you can download the command-line tool + bsdtar_ to do this, or you can use a GUI-based tool such as 7-zip_. - 3. Change into the downloaded directory (e.g. ``cd Django-NNN``). + 3. Change into the directory created in step 2 (e.g. ``cd Django-NNN``). - 4. Run ``sudo python setup.py install``. + 4. If you're using Linux, Mac OS X or some other flavor of Unix, enter + the command ``sudo python setup.py install`` at the shell prompt. + If you're using Windows, start up a command shell with administrator + privileges and run the command ``setup.py install``. -The command will install Django in your Python installation's ``site-packages`` -directory. +These commands will install Django in your Python installation's +``site-packages`` directory. .. _distribution specific notes: ../distributions/ +.. _bsdtar: http://gnuwin32.sourceforge.net/packages/bsdtar.htm +.. _7-zip: http://www.7-zip.org/ Installing the development version ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -144,34 +163,55 @@ Installing the development version If you'd like to be able to update your Django code occasionally with the latest bug fixes and improvements, follow these instructions: -1. Make sure you have Subversion_ installed. -2. Check out the Django code into your Python ``site-packages`` directory. +1. Make sure that you have Subversion_ installed, and that you can run its + commands from a shell. (Enter ``svn help`` at a shell prompt to test + this.) + +2. Check out Django's main development branch (the 'trunk') like so:: + + svn co http://code.djangoproject.com/svn/django/trunk/ django-trunk - On Linux / Mac OSX / Unix, do this:: +3. Next, make sure that the Python interpreter can load Django's code. There + are various ways of accomplishing this. One of the most convenient, on + Linux, Mac OSX or other Unix-like systems, is to use a symbolic link:: - svn co http://code.djangoproject.com/svn/django/trunk/ django_src - ln -s `pwd`/django_src/django SITE-PACKAGES-DIR/django + ln -s `pwd`/django-trunk/django SITE-PACKAGES-DIR/django (In the above line, change ``SITE-PACKAGES-DIR`` to match the location of your system's ``site-packages`` directory, as explained in the "Where are my ``site-packages`` stored?" section above.) - On Windows, do this:: + Alternatively, you can define your ``PYTHONPATH`` environment variable + so that it includes the ``django`` subdirectory of ``django-trunk``. + This is perhaps the most convenient solution on Windows systems, which + don't support symbolic links. (Environment variables can be defined on + Windows systems `from the Control Panel`_.) + + .. admonition:: What about Apache and mod_python? + + If you take the approach of setting ``PYTHONPATH``, you'll need to + remember to do the same thing in your Apache configuration once you + deploy your production site. Do this by setting ``PythonPath`` in your + Apache configuration file. + + More information about deployment is available, of course, in our + `How to use Django with mod_python`_ documentation. - svn co http://code.djangoproject.com/svn/django/trunk/django c:\Python24\lib\site-packages\django + .. _How to use Django with mod_python: ../modpython/ -3. Copy the file ``django_src/django/bin/django-admin.py`` to somewhere on your - system path, such as ``/usr/local/bin`` (Unix) or ``C:\Python24\Scripts`` +4. Copy the file ``django-trunk/django/bin/django-admin.py`` to somewhere on + your system path, such as ``/usr/local/bin`` (Unix) or ``C:\Python24\Scripts`` (Windows). This step simply lets you type ``django-admin.py`` from within any directory, rather than having to qualify the command with the full path to the file. -You *don't* have to run ``python setup.py install``, because that command -takes care of steps 2 and 3 for you. +You *don't* have to run ``python setup.py install``, because you've already +carried out the equivalent actions in steps 3 and 4. When you want to update your copy of the Django source code, just run the -command ``svn update`` from within the ``django`` directory. When you do this, -Subversion will automatically download any changes. +command ``svn update`` from within the ``django-trunk`` directory. When you do +this, Subversion will automatically download any changes. .. _`download page`: http://www.djangoproject.com/download/ .. _Subversion: http://subversion.tigris.org/ +.. _from the Control Panel: http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/sysdm_advancd_environmnt_addchange_variable.mspx diff --git a/docs/model-api.txt b/docs/model-api.txt index 7dac54992f..a0844ea961 100644 --- a/docs/model-api.txt +++ b/docs/model-api.txt @@ -148,7 +148,7 @@ and in Django's validation. Django veterans: Note that the argument is now called ``max_length`` to provide consistency throughout Django. There is full legacy support for -the old ``maxlength`` argument, but ``max_length`` is prefered. +the old ``maxlength`` argument, but ``max_length`` is preferred. ``CommaSeparatedIntegerField`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -178,7 +178,8 @@ A date field. Has a few extra optional arguments: ====================== =================================================== The admin represents this as an ``<input type="text">`` with a JavaScript -calendar and a shortcut for "Today." +calendar, and a shortcut for "Today." The JavaScript calendar will always start +the week on a Sunday. ``DateTimeField`` ~~~~~~~~~~~~~~~~~ @@ -221,8 +222,10 @@ The admin represents this as an ``<input type="text">`` (a single-line input). ~~~~~~~~~~~~~~ A ``CharField`` that checks that the value is a valid e-mail address. -This doesn't accept ``max_length``; its ``max_length`` is automatically set to -75. + +In Django 0.96, this doesn't accept ``max_length``; its ``max_length`` is +automatically set to 75. In the Django development version, ``max_length`` is +set to 75 by default, but you can specify it to override default behavior. ``FileField`` ~~~~~~~~~~~~~ @@ -290,6 +293,10 @@ visiting its URL on your site. Don't allow that. .. _`strftime formatting`: http://docs.python.org/lib/module-time.html#l2h-1941 +**New in development version:** By default, ``FileField`` instances are +created as ``varchar(100)`` columns in your database. As with other fields, you +can change the maximum length using the ``max_length`` argument. + ``FilePathField`` ~~~~~~~~~~~~~~~~~ @@ -308,7 +315,7 @@ on the filesystem. Has three special arguments, of which the first is ``FilePathField`` will use to filter filenames. Note that the regex will be applied to the base filename, not the full path. Example: - ``"foo.*\.txt^"``, which will match a file called + ``"foo.*\.txt$"``, which will match a file called ``foo23.txt`` but not ``bar.txt`` or ``foo23.gif``. ``recursive`` Optional. Either ``True`` or ``False``. Default is @@ -327,6 +334,10 @@ not the full path. So, this example:: because the ``match`` applies to the base filename (``foo.gif`` and ``bar.gif``). +**New in development version:** By default, ``FilePathField`` instances are +created as ``varchar(100)`` columns in your database. As with other fields, you +can change the maximum length using the ``max_length`` argument. + ``FloatField`` ~~~~~~~~~~~~~~ @@ -358,6 +369,11 @@ Requires the `Python Imaging Library`_. .. _Python Imaging Library: http://www.pythonware.com/products/pil/ .. _elsewhere: ../db-api/#get-foo-height-and-get-foo-width +**New in development version:** By default, ``ImageField`` instances are +created as ``varchar(100)`` columns in your database. As with other fields, you +can change the maximum length using the ``max_length`` argument. + + ``IntegerField`` ~~~~~~~~~~~~~~~~ @@ -1224,6 +1240,13 @@ together. It's used in the Django admin and is enforced at the database level (i.e., the appropriate ``UNIQUE`` statements are included in the ``CREATE TABLE`` statement). +**New in Django development version** + +For convenience, unique_together can be a single list when dealing +with a single set of fields:: + + unique_together = ("driver", "restaurant") + ``verbose_name`` ---------------- @@ -1274,6 +1297,17 @@ won't add the automatic ``id`` column. Each model requires exactly one field to have ``primary_key=True``. +The ``pk`` property +------------------- +**New in Django development version** + +Regardless of whether you define a primary key field yourself, or let Django +supply one for you, each model will have a property called ``pk``. It behaves +like a normal attribute on the model, but is actually an alias for whichever +attribute is the primary key field for the model. You can read and set this +value, just as you would for any other attribute, and it will update the +correct field in the model. + Admin options ============= @@ -1550,8 +1584,8 @@ Finally, note that in order to use ``list_display_links``, you must define Set ``list_filter`` to activate filters in the right sidebar of the change list page of the admin. This should be a list of field names, and each specified -field should be either a ``BooleanField``, ``DateField``, ``DateTimeField`` -or ``ForeignKey``. +field should be either a ``BooleanField``, ``CharField``, ``DateField``, +``DateTimeField``, ``IntegerField`` or ``ForeignKey``. This example, taken from the ``django.contrib.auth.models.User`` model, shows how both ``list_display`` and ``list_filter`` work:: @@ -1903,7 +1937,7 @@ as the value displayed to render an object in the Django admin site and as the value inserted into a template when it displays an object. Thus, you should always return a nice, human-readable string for the object's ``__str__``. Although this isn't required, it's strongly encouraged (see the description of -``__unicode__``, below, before putting ``_str__`` methods everywhere). +``__unicode__``, below, before putting ``__str__`` methods everywhere). For example:: diff --git a/docs/modpython.txt b/docs/modpython.txt index c90296bd9a..4a8c169a51 100644 --- a/docs/modpython.txt +++ b/docs/modpython.txt @@ -78,12 +78,12 @@ you have some applications under ``/usr/local/django-apps/`` (for example, ``DJANGO_SETTINGS_MODULE`` as in the above example. In this case, you would need to write your ``PythonPath`` directive as:: - PythonPath "['/var/production/django-apps/', '/var/www'] + sys.path" + PythonPath "['/usr/local/django-apps/', '/var/www'] + sys.path" With this path, ``import weblog`` and ``import mysite.settings`` will both work. If you had ``import blogroll`` in your code somewhere and ``blogroll`` lived under the ``weblog/`` directory, you would *also* need to add -``/var/production/django-apps/weblog/`` to your ``PythonPath``. Remember: the +``/usr/local/django-apps/weblog/`` to your ``PythonPath``. Remember: the **parent directories** of anything you import directly must be on the Python path. @@ -262,7 +262,8 @@ else. This is done using the PythonImport_ directive to mod_python. You need to ensure that you have specified the ``PythonInterpreter`` directive to mod_python as described above__ (you need to do this even if you aren't serving multiple installations in this case). Then add the ``PythonImport`` -line inside the ``Location`` or ``VirtualHost`` section. For example:: +line in the main server configuration (i.e., outside the ``Location`` or +``VirtualHost`` sections). For example:: PythonInterpreter my_django PythonImport /path/to/my/project/file.py my_django diff --git a/docs/newforms.txt b/docs/newforms.txt index 36c627b398..2c8f67ce32 100644 --- a/docs/newforms.txt +++ b/docs/newforms.txt @@ -513,6 +513,26 @@ include ``%s`` -- then the library will act as if ``auto_id`` is ``True``. By default, ``auto_id`` is set to the string ``'id_%s'``. +Normally, a colon (``:``) will be appended after any label name when a form is +rendered. It's possible to change the colon to another character, or omit it +entirely, using the ``label_suffix`` parameter:: + + >>> f = ContactForm(auto_id='id_for_%s', label_suffix='') + >>> print f.as_ul() + <li><label for="id_for_subject">Subject</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></li> + <li><label for="id_for_message">Message</label> <input type="text" name="message" id="id_for_message" /></li> + <li><label for="id_for_sender">Sender</label> <input type="text" name="sender" id="id_for_sender" /></li> + <li><label for="id_for_cc_myself">Cc myself</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></li> + >>> f = ContactForm(auto_id='id_for_%s', label_suffix=' ->') + >>> print f.as_ul() + <li><label for="id_for_subject">Subject -></label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></li> + <li><label for="id_for_message">Message -></label> <input type="text" name="message" id="id_for_message" /></li> + <li><label for="id_for_sender">Sender -></label> <input type="text" name="sender" id="id_for_sender" /></li> + <li><label for="id_for_cc_myself">Cc myself -></label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></li> + +Note that the label suffix is added only if the last character of the +label isn't a punctuation character (``.``, ``!``, ``?`` or ``:``) + Notes on field ordering ~~~~~~~~~~~~~~~~~~~~~~~ @@ -554,6 +574,29 @@ method you're using:: <p>Sender: <input type="text" name="sender" value="invalid e-mail address" /></p> <p>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></p> +Customizing the error list format +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +By default, forms use ``django.newforms.util.ErrorList`` to format validation +errors. If you'd like to use an alternate class for displaying errors, you can +pass that in at construction time:: + + >>> from django.newforms.util import ErrorList + >>> class DivErrorList(ErrorList): + ... def __unicode__(self): + ... return self.as_divs() + ... def as_divs(self): + ... if not self: return u'' + ... return u'<div class="errorlist">%s</div>' % ''.join([u'<div class="error">%s</div>' % e for e in self]) + >>> f = ContactForm(data, auto_id=False, error_class=DivErrorList) + >>> f.as_p() + <div class="errorlist"><div class="error">This field is required.</div></div> + <p>Subject: <input type="text" name="subject" maxlength="100" /></p> + <p>Message: <input type="text" name="message" value="Hi there" /></p> + <div class="errorlist"><div class="error">Enter a valid e-mail address.</div></div> + <p>Sender: <input type="text" name="sender" value="invalid e-mail address" /></p> + <p>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></p> + More granular output ~~~~~~~~~~~~~~~~~~~~ @@ -753,6 +796,27 @@ form data *and* file data:: # Unbound form with a image field >>> f = ContactFormWithMugshot() +Testing for multipart forms +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you're writing reusable views or templates, you may not know ahead of time +whether your form is a multipart form or not. The ``is_multipart()`` method +tells you whether the form requires multipart encoding for submission:: + + >>> f = ContactFormWithMugshot() + >>> f.is_multipart() + True + +Here's an example of how you might use this in a template:: + + {% if form.is_multipart %} + <form enctype="multipart/form-data" method="post" action="/foo/"> + {% else %} + <form method="post" action="/foo/"> + {% endif %} + {% form %} + </form> + Subclassing forms ----------------- @@ -962,7 +1026,7 @@ validation if a particular field's value is not given. ``initial`` values are ~~~~~~~~~~ The ``widget`` argument lets you specify a ``Widget`` class to use when -rendering this ``Field``. See "Widgets"_ below for more information. +rendering this ``Field``. See `Widgets`_ below for more information. ``help_text`` ~~~~~~~~~~~~~ @@ -1220,6 +1284,15 @@ When you use a ``FileField`` on a form, you must also remember to Takes two optional arguments for validation, ``max_value`` and ``min_value``. These control the range of values permitted in the field. +``IPAddressField`` +~~~~~~~~~~~~~~~~~~ + + * Default widget: ``TextInput`` + * Empty value: ``''`` (an empty string) + * Normalizes to: A Unicode object. + * Validates that the given value is a valid IPv4 address, using a regular + expression. + ``MultipleChoiceField`` ~~~~~~~~~~~~~~~~~~~~~~~ @@ -1646,7 +1719,7 @@ the full list of conversions: ``ForeignKey`` ``ModelChoiceField`` (see below) ``ImageField`` ``ImageField`` ``IntegerField`` ``IntegerField`` - ``IPAddressField`` ``CharField`` + ``IPAddressField`` ``IPAddressField`` ``ManyToManyField`` ``ModelMultipleChoiceField`` (see below) ``NullBooleanField`` ``CharField`` @@ -1887,12 +1960,23 @@ field on the model, you could define the callback:: ... else: ... return field.formfield(**kwargs) - >>> ArticleForm = form_for_model(formfield_callback=my_callback) + >>> ArticleForm = form_for_model(Article, formfield_callback=my_callback) Note that your callback needs to handle *all* possible model field types, not just the ones that you want to behave differently to the default. That's why this example has an ``else`` clause that implements the default behavior. +.. warning:: + The field that is passed into the ``formfield_callback`` function in + ``form_for_model()`` and ``form_for_instance`` is the field instance from + your model's class. You **must not** alter that object at all; treat it + as read-only! + + If you make any alterations to that object, it will affect any future + users of the model class, because you will have changed the field object + used to construct the class. This is almost certainly what you don't want + to have happen. + Finding the model associated with a form ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/request_response.txt b/docs/request_response.txt index 867464226a..7806886841 100644 --- a/docs/request_response.txt +++ b/docs/request_response.txt @@ -161,6 +161,18 @@ Methods Example: ``"/music/bands/the_beatles/?print=true"`` +``build_absolute_uri(location)`` + **New in Django development version** + + Returns the absolute URI form of ``location``. If no location is provided, + the location will be set to ``request.get_full_path()``. + + If the location is already an absolute URI, it will not be altered. + Otherwise the absolute URI is built using the server variables available in + this request. + + Example: ``"http://example.com/music/bands/the_beatles/?print=true"`` + ``is_secure()`` Returns ``True`` if the request is secure; that is, if it was made with HTTPS. @@ -178,11 +190,14 @@ necessary because some HTML form elements, notably That means you can't change attributes of ``request.POST`` and ``request.GET`` directly. -``QueryDict`` implements the all standard dictionary methods, because it's a +``QueryDict`` implements all the standard dictionary methods, because it's a subclass of dictionary. Exceptions are outlined here: * ``__getitem__(key)`` -- Returns the value for the given key. If the key has more than one value, ``__getitem__()`` returns the last value. + Raises ``django.utils.datastructure.MultiValueDictKeyError`` if the key + does not exist. (This is a subclass of Python's standard ``KeyError``, + so you can stick to catching ``KeyError``.) * ``__setitem__(key, value)`` -- Sets the given key to ``[value]`` (a Python list whose single element is ``value``). Note that this, as diff --git a/docs/sessions.txt b/docs/sessions.txt index 96a88c617a..96e8d36854 100644 --- a/docs/sessions.txt +++ b/docs/sessions.txt @@ -10,18 +10,21 @@ Cookies contain a session ID -- not the data itself. Enabling sessions ================= -Sessions are implemented via a piece of middleware_ and a Django model. +Sessions are implemented via a piece of middleware_. -To enable session functionality, do these two things: +To enable session functionality, do the following: * Edit the ``MIDDLEWARE_CLASSES`` setting and make sure ``MIDDLEWARE_CLASSES`` contains ``'django.contrib.sessions.middleware.SessionMiddleware'``. The default ``settings.py`` created by ``django-admin.py startproject`` has ``SessionMiddleware`` activated. - * Add ``'django.contrib.sessions'`` to your ``INSTALLED_APPS`` setting, and - run ``manage.py syncdb`` to install the single database table that stores - session data. + * Add ``'django.contrib.sessions'`` to your ``INSTALLED_APPS`` setting, + and run ``manage.py syncdb`` to install the single database table + that stores session data. + + **New in development version**: this step is optional if you're not using + the database session backend; see `configuring the session engine`_. If you don't want to use sessions, you might as well remove the ``SessionMiddleware`` line from ``MIDDLEWARE_CLASSES`` and ``'django.contrib.sessions'`` @@ -29,6 +32,44 @@ from your ``INSTALLED_APPS``. It'll save you a small bit of overhead. .. _middleware: ../middleware/ +Configuring the session engine +============================== + +**New in development version**. + +By default, Django stores sessions in your database (using the model +``django.contrib.sessions.models.Session``). Though this is convenient, in +some setups it's faster to store session data elsewhere, so Django can be +configured to store session data on your filesystem or in your cache. + +Using file-based sessions +------------------------- + +To use file-based sessions, set the ``SESSION_ENGINE`` setting to +``"django.contrib.sessions.backends.file"``. + +You might also want to set the ``SESSION_FILE_PATH`` setting (which +defaults to ``/tmp``) to control where Django stores session files. Be +sure to check that your Web server has permissions to read and write to +this location. + +Using cache-based sessions +-------------------------- + +To store session data using Django's cache system, set ``SESSION_ENGINE`` +to ``"django.contrib.sessions.backends.cache"``. You'll want to make sure +you've configured your cache; see the `cache documentation`_ for details. + +.. _cache documentation: ../cache/ + +.. note:: + + You should probably only use cache-based sessions if you're using the + memcached cache backend. The local memory and simple cache backends + don't retain data long enough to be good choices, and it'll be faster + to use file or database sessions directly instead of sending everything + through the file or database cache backends. + Using sessions in views ======================= @@ -153,9 +194,21 @@ Here's a typical usage example:: Using sessions out of views =========================== -Internally, each session is just a normal Django model. The ``Session`` model -is defined in ``django/contrib/sessions/models.py``. Because it's a normal -model, you can access sessions using the normal Django database API:: +**New in Django development version** + +An API is available to manipulate session data outside of a view:: + + >>> from django.contrib.sessions.backends.db import SessionStore + >>> s = SessionStore(session_key='2b1189a188b44ad18c35e113ac6ceead') + >>> s['last_login'] = datetime.datetime(2005, 8, 20, 13, 35, 10) + >>> s['last_login'] + datetime.datetime(2005, 8, 20, 13, 35, 0) + >>> s.save() + +If you're using the ``django.contrib.sessions.backends.db`` backend, each +session is just a normal Django model. The ``Session`` model is defined in +``django/contrib/sessions/models.py``. Because it's a normal model, you can +access sessions using the normal Django database API:: >>> from django.contrib.sessions.models import Session >>> s = Session.objects.get(pk='2b1189a188b44ad18c35e113ac6ceead') @@ -245,6 +298,31 @@ Settings A few `Django settings`_ give you control over session behavior: +SESSION_ENGINE +-------------- + +**New in Django development version** + +Default: ``django.contrib.sessions.backends.db`` + +Controls where Django stores session data. Valid values are: + + * ``'django.contrib.sessions.backends.db'`` + * ``'django.contrib.sessions.backends.file'`` + * ``'django.contrib.sessions.backends.cache'`` + +See `configuring the session engine`_ for more details. + +SESSION_FILE_PATH +----------------- + +**New in Django development version** + +Default: ``/tmp/`` + +If you're using file-based session storage, this sets the directory in +which Django will store session data. + SESSION_COOKIE_AGE ------------------ diff --git a/docs/settings.txt b/docs/settings.txt index 3f98296778..e40374a822 100644 --- a/docs/settings.txt +++ b/docs/settings.txt @@ -253,9 +253,15 @@ DATABASE_ENGINE Default: ``''`` (Empty string) -The database backend to use. Either ``'postgresql_psycopg2'``, -``'postgresql'``, ``'mysql'``, ``'mysql_old'``, ``'sqlite3'``, -``'oracle'``, or ``'ado_mssql'``. +The database backend to use. The build-in database backends are +``'postgresql_psycopg2'``, ``'postgresql'``, ``'mysql'``, ``'mysql_old'``, +``'sqlite3'``, ``'oracle'``, or ``'ado_mssql'``. + +In the Django development version, you can use a database backend that doesn't +ship with Django by setting ``DATABASE_ENGINE`` to a fully-qualified path (i.e. +``mypackage.backends.whatever``). Writing a whole new database backend from +scratch is left as an exercise to the reader; see the other backends for +examples. DATABASE_HOST ------------- @@ -325,7 +331,8 @@ The default formatting to use for date fields on Django admin change-list pages -- and, possibly, by other parts of the system. See `allowed date format strings`_. -See also DATETIME_FORMAT, TIME_FORMAT, YEAR_MONTH_FORMAT and MONTH_DAY_FORMAT. +See also ``DATETIME_FORMAT``, ``TIME_FORMAT``, ``YEAR_MONTH_FORMAT`` +and ``MONTH_DAY_FORMAT``. .. _allowed date format strings: ../templates/#now @@ -338,7 +345,8 @@ The default formatting to use for datetime fields on Django admin change-list pages -- and, possibly, by other parts of the system. See `allowed date format strings`_. -See also DATE_FORMAT, DATETIME_FORMAT, TIME_FORMAT, YEAR_MONTH_FORMAT and MONTH_DAY_FORMAT. +See also ``DATE_FORMAT``, ``DATETIME_FORMAT``, ``TIME_FORMAT``, +``YEAR_MONTH_FORMAT`` and ``MONTH_DAY_FORMAT``. .. _allowed date format strings: ../templates/#now @@ -350,8 +358,8 @@ Default: ``False`` A boolean that turns on/off debug mode. If you define custom settings, django/views/debug.py has a ``HIDDEN_SETTINGS`` -regular expression which will hide from the DEBUG view anything that contins -``'SECRET``, ``PASSWORD``, or ``PROFANITIES'``. This allows untrusted users to +regular expression which will hide from the DEBUG view anything that contains +``'SECRET'``, ``'PASSWORD'``, or ``'PROFANITIES'``. This allows untrusted users to be able to give backtraces without seeing sensitive (or offensive) settings. Still, note that there are always going to be sections of your debug output that @@ -656,8 +664,8 @@ drilldown, the header for a given day displays the day and month. Different locales have different formats. For example, U.S. English would say "January 1," whereas Spanish might say "1 Enero." -See `allowed date format strings`_. See also DATE_FORMAT, DATETIME_FORMAT, -TIME_FORMAT and YEAR_MONTH_FORMAT. +See `allowed date format strings`_. See also ``DATE_FORMAT``, +``DATETIME_FORMAT``, ``TIME_FORMAT`` and ``YEAR_MONTH_FORMAT``. PREPEND_WWW ----------- @@ -726,6 +734,21 @@ Default: ``'root@localhost'`` The e-mail address that error messages come from, such as those sent to ``ADMINS`` and ``MANAGERS``. +SESSION_ENGINE +-------------- + +**New in Django development version** + +Default: ``django.contrib.sessions.backends.db`` + +Controls where Django stores session data. Valid values are: + + * ``'django.contrib.sessions.backends.db'`` + * ``'django.contrib.sessions.backends.file'`` + * ``'django.contrib.sessions.backends.cache'`` + +See the `session docs`_ for more details. + SESSION_COOKIE_AGE ------------------ @@ -768,6 +791,17 @@ Default: ``False`` Whether to expire the session when the user closes his or her browser. See the `session docs`_. +SESSION_FILE_PATH +----------------- + +**New in Django development version** + +Default: ``/tmp/`` + +If you're using file-based session storage, this sets the directory in +which Django will store session data. See the `session docs`_ for +more details. + SESSION_SAVE_EVERY_REQUEST -------------------------- @@ -815,7 +849,7 @@ highlighted. Note that Django only displays fancy error pages if ``DEBUG`` is ``True``, so you'll want to set that to take advantage of this setting. -See also DEBUG. +See also ``DEBUG``. TEMPLATE_DIRS ------------- @@ -905,8 +939,8 @@ The default formatting to use for time fields on Django admin change-list pages -- and, possibly, by other parts of the system. See `allowed date format strings`_. -See also DATE_FORMAT, DATETIME_FORMAT, TIME_FORMAT, YEAR_MONTH_FORMAT and -MONTH_DAY_FORMAT. +See also ``DATE_FORMAT``, ``DATETIME_FORMAT``, ``TIME_FORMAT``, +``YEAR_MONTH_FORMAT`` and ``MONTH_DAY_FORMAT``. .. _allowed date format strings: ../templates/#now @@ -980,8 +1014,8 @@ drilldown, the header for a given month displays the month and the year. Different locales have different formats. For example, U.S. English would say "January 2006," whereas another locale might say "2006/January." -See `allowed date format strings`_. See also DATE_FORMAT, DATETIME_FORMAT, -TIME_FORMAT and MONTH_DAY_FORMAT. +See `allowed date format strings`_. See also ``DATE_FORMAT``, +``DATETIME_FORMAT``, ``TIME_FORMAT`` and ``MONTH_DAY_FORMAT``. .. _cache docs: ../cache/ .. _middleware docs: ../middleware/ diff --git a/docs/shortcuts.txt b/docs/shortcuts.txt new file mode 100644 index 0000000000..6c55486b5f --- /dev/null +++ b/docs/shortcuts.txt @@ -0,0 +1,143 @@ +========================= +Django shortcut functions +========================= + +The package ``django.shortcuts`` collects helper functions and classes that +"span" multiple levels of MVC. In other words, these functions/classes +introduce controlled coupling for convenience's sake. + +``render_to_response()`` +======================== + +``django.shortcuts.render_to_response`` renders a given template with a given +context dictionary and returns an ``HttpResponse`` object with that rendered +text. + +Required arguments +------------------ + +``template`` + The full name of a template to use. + +Optional arguments +------------------ + +``context`` + A dictionary of values to add to the template context. By default, this + is an empty dictionary. If a value in the dictionary is callable, the + view will call it just before rendering the template. + +``mimetype`` + **New in Django development version:** The MIME type to use for the + resulting document. Defaults to the value of the ``DEFAULT_CONTENT_TYPE`` + setting. + +Example +------- + +The following example renders the template ``myapp/index.html`` with the +MIME type ``application/xhtml+xml``:: + + from django.shortcuts import render_to_response + + def my_view(request): + # View code here... + return render_to_response('myapp/index.html', {"foo": "bar"}, + mimetype="application/xhtml+xml") + +This example is equivalent to:: + + from django.http import HttpResponse + from django.template import Context, loader + + def my_view(request): + # View code here... + t = loader.get_template('myapp/template.html') + c = Context({'foo': 'bar'}) + r = HttpResponse(t.render(c), + mimetype="application/xhtml+xml") + +.. _an HttpResponse object: ../request_response/#httpresponse-objects + +``get_object_or_404`` +===================== + +``django.shortcuts.get_object_or_404`` calls `get()`_ on a given model +manager, but it raises ``django.http.Http404`` instead of the model's +``DoesNotExist`` exception. + +Required arguments +------------------ + +``klass`` + A ``Model``, ``Manager`` or ``QuerySet`` instance from which to get the + object. + +``**kwargs`` + Lookup parameters, which should be in the format accepted by ``get()`` and + ``filter()``. + +Example +------- + +The following example gets the object with the primary key of 1 from +``MyModel``:: + + from django.shortcuts import get_object_or_404 + + def my_view(request): + my_object = get_object_or_404(MyModel, pk=1) + +This example is equivalent to:: + + from django.http import Http404 + + def my_view(request): + try: + my_object = MyModel.object.get(pk=1) + except MyModel.DoesNotExist: + raise Http404 + +Note: As with ``get()``, an ``AssertionError`` will be raised if more than +one object is found. + +.. _get(): ../db-api/#get-kwargs + +``get_list_or_404`` +=================== + +``django.shortcuts.get_list_or_404`` returns the result of `filter()`_ on a +given model manager, raising ``django.http.Http404`` if the resulting list is +empty. + +Required arguments +------------------ + +``klass`` + A ``Model``, ``Manager`` or ``QuerySet`` instance from which to get the + object. + +``**kwargs`` + Lookup parameters, which should be in the format accepted by ``get()`` and + ``filter()``. + +Example +------- + +The following example gets all published objects from ``MyModel``:: + + from django.shortcuts import get_list_or_404 + + def my_view(request): + my_objects = get_list_or_404(MyModel, published=True) + +This example is equivalent to:: + + from django.http import Http404 + + def my_view(request): + my_objects = MyModels.object.filter(published=True) + if not my_objects: + raise Http404 + +.. _filter(): ../db-api/#filter-kwargs diff --git a/docs/sites.txt b/docs/sites.txt index 90a9d0f90f..5896afcf41 100644 --- a/docs/sites.txt +++ b/docs/sites.txt @@ -213,6 +213,31 @@ To do this, you can use the sites framework. A simple example:: >>> 'http://%s%s' % (Site.objects.get_current().domain, obj.get_absolute_url()) 'http://example.com/mymodel/objects/3/' +Caching the current ``Site`` object +=================================== + +**New in Django development version** + +As the current site is stored in the database, each call to +``Site.objects.get_current()`` could result in a database query. But Django is a +little cleverer than that: on the first request, the current site is cached, and +any subsequent call returns the cached data instead of hitting the database. + +If for any reason you want to force a database query, you can tell Django to +clear the cache using ``Site.objects.clear_cache()``:: + + # First call; current site fetched from database. + current_site = Site.objects.get_current() + # ... + + # Second call; current site fetched from cache. + current_site = Site.objects.get_current() + # ... + + # Force a database query for the third call. + Site.objects.clear_cache() + current_site = Site.objects.get_current() + The ``CurrentSiteManager`` ========================== @@ -316,6 +341,9 @@ Here's how Django uses the sites framework: * The shortcut view (``django.views.defaults.shortcut``) uses the domain of the current ``Site`` object when calculating an object's URL. + * In the admin framework, the ''view on site'' link uses the current + ``Site`` to work out the domain for the site that it will redirect to. + .. _redirects framework: ../redirects/ .. _flatpages framework: ../flatpages/ .. _syndication framework: ../syndication_feeds/ diff --git a/docs/templates.txt b/docs/templates.txt index 8bfa40dc5f..cd436a987d 100644 --- a/docs/templates.txt +++ b/docs/templates.txt @@ -366,25 +366,36 @@ Ignore everything between ``{% comment %}`` and ``{% endcomment %}`` cycle ~~~~~ -Cycle among the given strings each time this tag is encountered. +**Changed in Django development version** +Cycle among the given strings or variables each time this tag is encountered. -Within a loop, cycles among the given strings each time through the loop:: +Within a loop, cycles among the given strings/variables each time through the +loop:: {% for o in some_list %} - <tr class="{% cycle row1,row2 %}"> + <tr class="{% cycle 'row1' 'row2' rowvar %}"> ... </tr> {% endfor %} - + Outside of a loop, give the values a unique name the first time you call it, then use that name each successive time through:: - <tr class="{% cycle row1,row2,row3 as rowcolors %}">...</tr> + <tr class="{% cycle 'row1' 'row2' rowvar as rowcolors %}">...</tr> <tr class="{% cycle rowcolors %}">...</tr> <tr class="{% cycle rowcolors %}">...</tr> -You can use any number of values, separated by commas. Make sure not to put -spaces between the values -- only commas. +You can use any number of values, separated by spaces. Values enclosed in +single (') or double quotes (") are treated as string literals, while values +without quotes are assumed to refer to context variables. + +You can also separate values with commas:: + + {% cycle row1,row2,row3 %} + +In this syntax, each value will be interpreted as literal text. The +comma-based syntax exists for backwards-compatibility, and should not be +used for new projects. debug ~~~~~ @@ -1124,12 +1135,15 @@ Returns a boolean of whether the value's length is the argument. linebreaks ~~~~~~~~~~ -Converts newlines into ``<p>`` and ``<br />`` tags. +Replaces line breaks in plain text with appropriate HTML; a single +newline becomes an HTML line break (``<br />``) and a new line +followed by a blank line becomes a paragraph break (``</p>``). linebreaksbr ~~~~~~~~~~~~ -Converts newlines into ``<br />`` tags. +Converts all newlines in a piece of plain text to HTML line breaks +(``<br />``). linenumbers ~~~~~~~~~~~ @@ -1261,17 +1275,23 @@ For example, if ``blog_date`` is a date instance representing midnight on 1 June 2006, and ``comment_date`` is a date instance for 08:00 on 1 June 2006, then ``{{ comment_date|timesince:blog_date }}`` would return "8 hours". +Minutes is the smallest unit used, and "0 minutes" will be returned for any +date that is in the future relative to the comparison point. + timeuntil ~~~~~~~~~ Similar to ``timesince``, except that it measures the time from now until the given date or datetime. For example, if today is 1 June 2006 and ``conference_date`` is a date instance holding 29 June 2006, then -``{{ conference_date|timeuntil }}`` will return "28 days". +``{{ conference_date|timeuntil }}`` will return "4 weeks". Takes an optional argument that is a variable containing the date to use as the comparison point (instead of *now*). If ``from_date`` contains 22 June -2006, then ``{{ conference_date|timeuntil:from_date }}`` will return "7 days". +2006, then ``{{ conference_date|timeuntil:from_date }}`` will return "1 week". + +Minutes is the smallest unit used, and "0 minutes" will be returned for any +date that is in the past relative to the comparison point. title ~~~~~ @@ -1405,6 +1425,12 @@ A collection of template filters that implement these common markup languages: * Markdown * ReST (ReStructured Text) +See the `markup section`_ of the `add-ons documentation`_ for more +information. + +.. _markup section: ../add_ons/#markup +.. _add-ons documentation: ../add_ons/ + django.contrib.webdesign ------------------------ @@ -1412,3 +1438,12 @@ A collection of template tags that can be useful while designing a website, such as a generator of Lorem Ipsum text. See the `webdesign documentation`_. .. _webdesign documentation: ../webdesign/ + +Next steps +========== + +Read the document `The Django template language: For Python programmers`_ if +you're interested in learning the template system from a technical +perspective -- how it works and how to extend it. + +.. _The Django template language\: For Python programmers: ../templates_python/ diff --git a/docs/templates_python.txt b/docs/templates_python.txt index 261eaedf74..232f54061f 100644 --- a/docs/templates_python.txt +++ b/docs/templates_python.txt @@ -555,6 +555,38 @@ template loaders that come with Django: Django uses the template loaders in order according to the ``TEMPLATE_LOADERS`` setting. It uses each loader until a loader finds a match. +The ``render_to_string()`` shortcut +=================================== + +To cut down on the repetitive nature of loading and rendering +templates, Django provides a shortcut function which largely +automates the process: ``render_to_string()`` in +``django.template.loader``, which loads a template, renders it and +returns the resulting string:: + + from django.template.loader import render_to_string + rendered = render_to_string('my_template.html', { 'foo': 'bar' }) + +The ``render_to_string`` shortcut takes one required argument -- +``template_name``, which should be the name of the template to load +and render -- and two optional arguments:: + + dictionary + A dictionary to be used as variables and values for the + template's context. This can also be passed as the second + positional argument. + + context_instance + An instance of ``Context`` or a subclass (e.g., an instance of + ``RequestContext``) to use as the template's context. This can + also be passed as the third positional argument. + +See also the `render_to_response()`_ shortcut, which calls +``render_to_string`` and feeds the result into an ``HttpResponse`` +suitable for returning directly from a view. + +.. _render_to_response(): ../shortcuts/#render-to-response + Extending the template system ============================= @@ -642,7 +674,27 @@ your function. Example:: "Converts a string into all lowercase" return value.lower() -When you've written your filter definition, you need to register it with +Template filters that expect strings +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you're writing a template filter that only expects a string as the first +argument, you should use the decorator ``stringfilter``. This will +convert an object to its string value before being passed to your function:: + + from django.template.defaultfilters import stringfilter + + @stringfilter + def lower(value): + return value.lower() + +This way, you'll be able to pass, say, an integer to this filter, and it +won't cause an ``AttributeError`` (because integers don't have ``lower()`` +methods). + +Registering a custom filters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Once you've written your filter definition, you need to register it with your ``Library`` instance, to make it available to Django's template language:: register.filter('cut', cut) @@ -658,28 +710,18 @@ If you're using Python 2.4 or above, you can use ``register.filter()`` as a decorator instead:: @register.filter(name='cut') + @stringfilter def cut(value, arg): return value.replace(arg, '') @register.filter + @stringfilter def lower(value): return value.lower() If you leave off the ``name`` argument, as in the second example above, Django will use the function's name as the filter name. -Template filters which expect strings -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -If you are writing a template filter which only expects a string as the first -argument, you should use the included decorator ``stringfilter`` which will convert -an object to it's string value before being passed to your function:: - - from django.template.defaultfilters import stringfilter - - @stringfilter - def lower(value): - return value.lower() - Writing custom template tags ---------------------------- diff --git a/docs/testing.txt b/docs/testing.txt index e27479cc34..04c999cda8 100644 --- a/docs/testing.txt +++ b/docs/testing.txt @@ -137,12 +137,14 @@ When you `run your tests`_, the test runner will find this docstring, notice that portions of it look like an interactive Python session, and execute those lines while checking that the results match. -In the case of model tests, note that the test runner takes care of creating -its own test database. That is, any test that accesses a database -- by -creating and saving model instances, for example -- will not affect your -production database. Each doctest begins with a "blank slate" -- a fresh -database containing an empty table for each model. (See the section on -fixtures, below, for more on this.) +In the case of model tests, note that the test runner takes care of +creating its own test database. That is, any test that accesses a +database -- by creating and saving model instances, for example -- +will not affect your production database. Each doctest begins with a +"blank slate" -- a fresh database containing an empty table for each +model. (See the section on fixtures, below, for more on this.) Note +that to use this feature, the database user Django is connecting as +must have ``CREATE DATABASE`` rights. For more details about how doctest works, see the `standard library documentation for doctest`_ @@ -569,20 +571,34 @@ Testing responses The ``get()`` and ``post()`` methods both return a ``Response`` object. This ``Response`` object is *not* the same as the ``HttpResponse`` object returned -Django views; this object is simpler and has some additional data useful for -tests. +Django views; the test response object has some additional data useful for +test code to verify. Specifically, a ``Response`` object has the following attributes: =============== ========================================================== Attribute Description =============== ========================================================== - ``status_code`` The HTTP status of the response, as an integer. See - RFC2616_ for a full list of HTTP status codes. + ``client`` The test client that was used to make the request that + resulted in the response. ``content`` The body of the response, as a string. This is the final page content as rendered by the view, or any error - message (such as the URL for a 302 redirect). + message. + + ``context`` The template ``Context`` instance that was used to render + the template that produced the response content. + + If the rendered page used multiple templates, then + ``context`` will be a list of ``Context`` + objects, in the order in which they were rendered. + + ``headers`` The HTTP headers of the response. This is a dictionary. + + ``request`` The request data that stimulated the response. + + ``status_code`` The HTTP status of the response, as an integer. See + RFC2616_ for a full list of HTTP status codes. ``template`` The ``Template`` instance that was used to render the final content. Use ``template.name`` to get the @@ -594,13 +610,6 @@ Specifically, a ``Response`` object has the following attributes: using `template inheritance`_ -- then ``template`` will be a list of ``Template`` instances, in the order in which they were rendered. - - ``context`` The template ``Context`` instance that was used to render - the template that produced the response content. - - As with ``template``, if the rendered page used multiple - templates, then ``context`` will be a list of ``Context`` - objects, in the order in which they were rendered. =============== ========================================================== .. _RFC2616: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html @@ -826,10 +835,10 @@ useful for testing Web applications: Asserts that the template with the given name was *not* used in rendering the response. -``assertRedirects(response, expected_path, status_code=302, target_status_code=200)`` +``assertRedirects(response, expected_url, status_code=302, target_status_code=200)`` Asserts that the response return a ``status_code`` redirect status, - it redirected to ``expected_path`` and the subsequent page was received with - ``target_status_code``. + it redirected to ``expected_url`` (including any GET data), and the subsequent + page was received with ``target_status_code``. ``assertTemplateUsed(response, template_name)`` Asserts that the template with the given name was used in rendering the diff --git a/docs/tutorial01.txt b/docs/tutorial01.txt index 60c527216b..4e97dcd541 100644 --- a/docs/tutorial01.txt +++ b/docs/tutorial01.txt @@ -41,6 +41,16 @@ From the command line, ``cd`` into a directory where you'd like to store your code, then run the command ``django-admin.py startproject mysite``. This will create a ``mysite`` directory in your current directory. +.. admonition:: Max OS X permissions + + If you're using Mac OS X, you may see the message "permission + denied" when you try to run ``django-admin.py startproject``. This + is because, on Unix-based systems like OS X, a file must be marked + as "executable" before it can be run as a program. To do this, open + Terminal.app and navigate (using the `cd` command) to the directory + where ``django-admin.py`` is installed, then run the command + ``chmod +x django-admin.py``. + .. note:: You'll need to avoid naming projects after built-in Python or Django @@ -383,7 +393,7 @@ Note the following: the SQL to the database. If you're interested, also run the following commands: - * ``python manage.py validate polls`` -- Checks for any errors in the + * ``python manage.py validate`` -- Checks for any errors in the construction of your models. * ``python manage.py sqlcustom polls`` -- Outputs any custom SQL statements diff --git a/tests/modeltests/basic/models.py b/tests/modeltests/basic/models.py index 0a09579761..58770ef2ce 100644 --- a/tests/modeltests/basic/models.py +++ b/tests/modeltests/basic/models.py @@ -33,6 +33,11 @@ __test__ = {'API_TESTS': """ >>> a.id 1L +# Models have a pk property that is an alias for the primary key attribute (by +# default, the 'id' attribute). +>>> a.pk +1L + # Access database columns via Python attributes. >>> a.headline 'Area man programs in Python' diff --git a/tests/modeltests/custom_pk/models.py b/tests/modeltests/custom_pk/models.py index 53bbadbfd4..381d81b987 100644 --- a/tests/modeltests/custom_pk/models.py +++ b/tests/modeltests/custom_pk/models.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- """ 14. Using a custom primary key @@ -55,6 +56,15 @@ DoesNotExist: Employee matching query does not exist. >>> Employee.objects.filter(pk__in=['ABC123','XYZ456']) [<Employee: Fran Bones>, <Employee: Dan Jones>] +# The primary key can be accessed via the pk property on the model. +>>> e = Employee.objects.get(pk='ABC123') +>>> e.pk +u'ABC123' + +# Or we can use the real attribute name for the primary key: +>>> e.employee_code +u'ABC123' + # Fran got married and changed her last name. >>> fran = Employee.objects.get(pk='XYZ456') >>> fran.last_name = 'Jones' @@ -92,4 +102,8 @@ DoesNotExist: Employee matching query does not exist. >>> Business.objects.filter(employees__first_name__startswith='Fran') [<Business: Sears>] +# Primary key may be unicode string +>>> emp = Employee(employee_code='jaźń') +>>> emp.save() + """} diff --git a/tests/modeltests/fixtures/models.py b/tests/modeltests/fixtures/models.py index b59c388bbd..5b53115733 100644 --- a/tests/modeltests/fixtures/models.py +++ b/tests/modeltests/fixtures/models.py @@ -9,6 +9,7 @@ FIXTURE_DIRS setting. """ from django.db import models +from django.conf import settings class Article(models.Model): headline = models.CharField(max_length=100, default='Default headline') @@ -53,7 +54,13 @@ __test__ = {'API_TESTS': """ # object list is unaffected >>> Article.objects.all() [<Article: XML identified as leading cause of cancer>, <Article: Django conquers world!>, <Article: Copyright is fine the way it is>, <Article: Poker on TV is great!>, <Article: Python program becomes self aware>] +"""} +# Database flushing does not work on MySQL with the default storage engine +# because it requires transaction support. +if settings.DATABASE_ENGINE not in ('mysql', 'mysql_old'): + __test__['API_TESTS'] += \ +""" # Reset the database representation of this app. This will delete all data. >>> management.call_command('flush', verbosity=0, interactive=False) >>> Article.objects.all() @@ -74,8 +81,8 @@ Multiple fixtures named 'fixture2' in '...fixtures'. Aborting. # Dump the current contents of the database as a JSON fixture >>> management.call_command('dumpdata', 'fixtures', format='json') -[{"pk": "3", "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}, {"pk": "2", "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16 12:00:00"}}, {"pk": "1", "model": "fixtures.article", "fields": {"headline": "Python program becomes self aware", "pub_date": "2006-06-16 11:00:00"}}] -"""} +[{"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16 12:00:00"}}, {"pk": 1, "model": "fixtures.article", "fields": {"headline": "Python program becomes self aware", "pub_date": "2006-06-16 11:00:00"}}] +""" from django.test import TestCase diff --git a/tests/modeltests/model_forms/models.py b/tests/modeltests/model_forms/models.py index d27f0b0e54..bc14c117d5 100644 --- a/tests/modeltests/model_forms/models.py +++ b/tests/modeltests/model_forms/models.py @@ -32,6 +32,7 @@ ARTICLE_STATUS = ( class Category(models.Model): name = models.CharField(max_length=20) + slug = models.SlugField(max_length=20) url = models.CharField('The URL', max_length=40) def __unicode__(self): @@ -45,6 +46,7 @@ class Writer(models.Model): class Article(models.Model): headline = models.CharField(max_length=50) + slug = models.SlugField() pub_date = models.DateField() created = models.DateField(editable=False) writer = models.ForeignKey(Writer) @@ -79,9 +81,11 @@ __test__ = {'API_TESTS': """ >>> f = CategoryForm() >>> print f <tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" name="name" maxlength="20" /></td></tr> +<tr><th><label for="id_slug">Slug:</label></th><td><input id="id_slug" type="text" name="slug" maxlength="20" /></td></tr> <tr><th><label for="id_url">The URL:</label></th><td><input id="id_url" type="text" name="url" maxlength="40" /></td></tr> >>> print f.as_ul() <li><label for="id_name">Name:</label> <input id="id_name" type="text" name="name" maxlength="20" /></li> +<li><label for="id_slug">Slug:</label> <input id="id_slug" type="text" name="slug" maxlength="20" /></li> <li><label for="id_url">The URL:</label> <input id="id_url" type="text" name="url" maxlength="40" /></li> >>> print f['name'] <input id="id_name" type="text" name="name" maxlength="20" /> @@ -89,51 +93,52 @@ __test__ = {'API_TESTS': """ >>> f = CategoryForm(auto_id=False) >>> print f.as_ul() <li>Name: <input type="text" name="name" maxlength="20" /></li> +<li>Slug: <input type="text" name="slug" maxlength="20" /></li> <li>The URL: <input type="text" name="url" maxlength="40" /></li> ->>> f = CategoryForm({'name': 'Entertainment', 'url': 'entertainment'}) +>>> f = CategoryForm({'name': 'Entertainment', 'slug': 'entertainment', 'url': 'entertainment'}) >>> f.is_valid() True >>> f.cleaned_data -{'url': u'entertainment', 'name': u'Entertainment'} +{'url': u'entertainment', 'name': u'Entertainment', 'slug': u'entertainment'} >>> obj = f.save() >>> obj <Category: Entertainment> >>> Category.objects.all() [<Category: Entertainment>] ->>> f = CategoryForm({'name': "It's a test", 'url': 'test'}) +>>> f = CategoryForm({'name': "It's a test", 'slug': 'its-test', 'url': 'test'}) >>> f.is_valid() True >>> f.cleaned_data -{'url': u'test', 'name': u"It's a test"} +{'url': u'test', 'name': u"It's a test", 'slug': u'its-test'} >>> obj = f.save() >>> obj <Category: It's a test> ->>> Category.objects.all() +>>> Category.objects.order_by('name') [<Category: Entertainment>, <Category: It's a test>] If you call save() with commit=False, then it will return an object that hasn't yet been saved to the database. In this case, it's up to you to call save() on the resulting model instance. ->>> f = CategoryForm({'name': 'Third test', 'url': 'third'}) +>>> f = CategoryForm({'name': 'Third test', 'slug': 'third-test', 'url': 'third'}) >>> f.is_valid() True >>> f.cleaned_data -{'url': u'third', 'name': u'Third test'} +{'url': u'third', 'name': u'Third test', 'slug': u'third-test'} >>> obj = f.save(commit=False) >>> obj <Category: Third test> ->>> Category.objects.all() +>>> Category.objects.order_by('name') [<Category: Entertainment>, <Category: It's a test>] >>> obj.save() ->>> Category.objects.all() +>>> Category.objects.order_by('name') [<Category: Entertainment>, <Category: It's a test>, <Category: Third test>] If you call save() with invalid data, you'll get a ValueError. ->>> f = CategoryForm({'name': '', 'url': 'foo'}) +>>> f = CategoryForm({'name': '', 'slug': '', 'url': 'foo'}) >>> f.errors -{'name': [u'This field is required.']} +{'name': [u'This field is required.'], 'slug': [u'This field is required.']} >>> f.cleaned_data Traceback (most recent call last): ... @@ -142,7 +147,7 @@ AttributeError: 'CategoryForm' object has no attribute 'cleaned_data' Traceback (most recent call last): ... ValueError: The Category could not be created because the data didn't validate. ->>> f = CategoryForm({'name': '', 'url': 'foo'}) +>>> f = CategoryForm({'name': '', 'slug': '', 'url': 'foo'}) >>> f.save() Traceback (most recent call last): ... @@ -160,6 +165,7 @@ fields with the 'choices' attribute are represented by a ChoiceField. >>> f = ArticleForm(auto_id=False) >>> print f <tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr> +<tr><th>Slug:</th><td><input type="text" name="slug" maxlength="50" /></td></tr> <tr><th>Pub date:</th><td><input type="text" name="pub_date" /></td></tr> <tr><th>Writer:</th><td><select name="writer"> <option value="" selected="selected">---------</option> @@ -210,7 +216,7 @@ current values are inserted as 'initial' data in each Field. >>> print f <tr><th>Name:</th><td><input type="text" name="name" value="Mike Royko" maxlength="50" /><br />Use both first and last names.</td></tr> ->>> art = Article(headline='Test article', pub_date=datetime.date(1988, 1, 4), writer=w, article='Hello.') +>>> art = Article(headline='Test article', slug='test-article', pub_date=datetime.date(1988, 1, 4), writer=w, article='Hello.') >>> art.save() >>> art.id 1 @@ -218,6 +224,7 @@ current values are inserted as 'initial' data in each Field. >>> f = TestArticleForm(auto_id=False) >>> print f.as_ul() <li>Headline: <input type="text" name="headline" value="Test article" maxlength="50" /></li> +<li>Slug: <input type="text" name="slug" value="test-article" maxlength="50" /></li> <li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li> <li>Writer: <select name="writer"> <option value="">---------</option> @@ -236,7 +243,7 @@ current values are inserted as 'initial' data in each Field. <option value="2">It's a test</option> <option value="3">Third test</option> </select> Hold down "Control", or "Command" on a Mac, to select more than one.</li> ->>> f = TestArticleForm({'headline': u'Test headline', 'pub_date': u'1984-02-06', 'writer': u'1', 'article': 'Hello.'}) +>>> f = TestArticleForm({'headline': u'Test headline', 'slug': 'test-headline', 'pub_date': u'1984-02-06', 'writer': u'1', 'article': 'Hello.'}) >>> f.is_valid() True >>> test_art = f.save() @@ -248,10 +255,11 @@ u'Test headline' You can create a form over a subset of the available fields by specifying a 'fields' argument to form_for_instance. ->>> PartialArticleForm = form_for_instance(art, fields=('headline','pub_date')) ->>> f = PartialArticleForm({'headline': u'New headline', 'pub_date': u'1988-01-04'}, auto_id=False) +>>> PartialArticleForm = form_for_instance(art, fields=('headline', 'slug', 'pub_date')) +>>> f = PartialArticleForm({'headline': u'New headline', 'slug': 'new-headline', 'pub_date': u'1988-01-04'}, auto_id=False) >>> print f.as_ul() <li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li> +<li>Slug: <input type="text" name="slug" value="new-headline" maxlength="50" /></li> <li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li> >>> f.is_valid() True @@ -272,6 +280,7 @@ Add some categories and test the many-to-many form output. >>> f = TestArticleForm(auto_id=False) >>> print f.as_ul() <li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li> +<li>Slug: <input type="text" name="slug" value="new-headline" maxlength="50" /></li> <li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li> <li>Writer: <select name="writer"> <option value="">---------</option> @@ -291,17 +300,17 @@ Add some categories and test the many-to-many form output. <option value="3">Third test</option> </select> Hold down "Control", or "Command" on a Mac, to select more than one.</li> ->>> f = TestArticleForm({'headline': u'New headline', 'pub_date': u'1988-01-04', +>>> f = TestArticleForm({'headline': u'New headline', 'slug': u'new-headline', 'pub_date': u'1988-01-04', ... 'writer': u'1', 'article': u'Hello.', 'categories': [u'1', u'2']}) >>> new_art = f.save() >>> new_art.id 1 >>> new_art = Article.objects.get(id=1) ->>> new_art.categories.all() +>>> new_art.categories.order_by('name') [<Category: Entertainment>, <Category: It's a test>] Now, submit form data with no categories. This deletes the existing categories. ->>> f = TestArticleForm({'headline': u'New headline', 'pub_date': u'1988-01-04', +>>> f = TestArticleForm({'headline': u'New headline', 'slug': u'new-headline', 'pub_date': u'1988-01-04', ... 'writer': u'1', 'article': u'Hello.'}) >>> new_art = f.save() >>> new_art.id @@ -312,18 +321,18 @@ Now, submit form data with no categories. This deletes the existing categories. Create a new article, with categories, via the form. >>> ArticleForm = form_for_model(Article) ->>> f = ArticleForm({'headline': u'The walrus was Paul', 'pub_date': u'1967-11-01', +>>> f = ArticleForm({'headline': u'The walrus was Paul', 'slug': u'walrus-was-paul', 'pub_date': u'1967-11-01', ... 'writer': u'1', 'article': u'Test.', 'categories': [u'1', u'2']}) >>> new_art = f.save() >>> new_art.id 2 >>> new_art = Article.objects.get(id=2) ->>> new_art.categories.all() +>>> new_art.categories.order_by('name') [<Category: Entertainment>, <Category: It's a test>] Create a new article, with no categories, via the form. >>> ArticleForm = form_for_model(Article) ->>> f = ArticleForm({'headline': u'The walrus was Paul', 'pub_date': u'1967-11-01', +>>> f = ArticleForm({'headline': u'The walrus was Paul', 'slug': u'walrus-was-paul', 'pub_date': u'1967-11-01', ... 'writer': u'1', 'article': u'Test.'}) >>> new_art = f.save() >>> new_art.id @@ -335,11 +344,11 @@ Create a new article, with no categories, via the form. Create a new article, with categories, via the form, but use commit=False. The m2m data won't be saved until save_m2m() is invoked on the form. >>> ArticleForm = form_for_model(Article) ->>> f = ArticleForm({'headline': u'The walrus was Paul', 'pub_date': u'1967-11-01', +>>> f = ArticleForm({'headline': u'The walrus was Paul', 'slug': 'walrus-was-paul', 'pub_date': u'1967-11-01', ... 'writer': u'1', 'article': u'Test.', 'categories': [u'1', u'2']}) >>> new_art = f.save(commit=False) -# Manually save the instance +# Manually save the instance >>> new_art.save() >>> new_art.id 4 @@ -351,7 +360,7 @@ The m2m data won't be saved until save_m2m() is invoked on the form. # Save the m2m data on the form >>> f.save_m2m() ->>> new_art.categories.all() +>>> new_art.categories.order_by('name') [<Category: Entertainment>, <Category: It's a test>] Here, we define a custom Form. Because it happens to have the same fields as @@ -359,13 +368,14 @@ the Category model, we can use save_instance() to apply its changes to an existing Category instance. >>> class ShortCategory(Form): ... name = CharField(max_length=5) +... slug = CharField(max_length=5) ... url = CharField(max_length=3) >>> cat = Category.objects.get(name='Third test') >>> cat <Category: Third test> >>> cat.id 3 ->>> sc = ShortCategory({'name': 'Third', 'url': '3rd'}) +>>> sc = ShortCategory({'name': 'Third', 'slug': 'third', 'url': '3rd'}) >>> save_instance(sc, cat) <Category: Third> >>> Category.objects.get(id=3) @@ -378,6 +388,7 @@ the data in the database when the form is instantiated. >>> f = ArticleForm(auto_id=False) >>> print f.as_ul() <li>Headline: <input type="text" name="headline" maxlength="50" /></li> +<li>Slug: <input type="text" name="slug" maxlength="50" /></li> <li>Pub date: <input type="text" name="pub_date" /></li> <li>Writer: <select name="writer"> <option value="" selected="selected">---------</option> @@ -402,6 +413,7 @@ the data in the database when the form is instantiated. <Writer: Carl Bernstein> >>> print f.as_ul() <li>Headline: <input type="text" name="headline" maxlength="50" /></li> +<li>Slug: <input type="text" name="slug" maxlength="50" /></li> <li>Pub date: <input type="text" name="pub_date" /></li> <li>Writer: <select name="writer"> <option value="" selected="selected">---------</option> diff --git a/tests/modeltests/pagination/models.py b/tests/modeltests/pagination/models.py index a7af2a7089..1dcec00a32 100644 --- a/tests/modeltests/pagination/models.py +++ b/tests/modeltests/pagination/models.py @@ -77,4 +77,8 @@ True >>> paginator = ObjectPaginator(Article.objects.all(), 10, orphans=1) >>> paginator.pages 2 + +# The paginator can provide a list of all available pages +>>> paginator.page_range +[1, 2] """} diff --git a/tests/modeltests/serializers/models.py b/tests/modeltests/serializers/models.py index 2ee6cfce67..a0a68d4bcc 100644 --- a/tests/modeltests/serializers/models.py +++ b/tests/modeltests/serializers/models.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- """ 41. Serialization @@ -43,6 +44,25 @@ class AuthorProfile(models.Model): def __unicode__(self): return u"Profile of %s" % self.author + +class Actor(models.Model): + name = models.CharField(max_length=20, primary_key=True) + + class Meta: + ordering = ('name',) + + def __unicode__(self): + return self.name + +class Movie(models.Model): + actor = models.ForeignKey(Actor) + title = models.CharField(max_length=50) + + class Meta: + ordering = ('title',) + + def __unicode__(self): + return self.title __test__ = {'API_TESTS':""" # Create some data: @@ -101,7 +121,7 @@ __test__ = {'API_TESTS':""" # Django also ships with a built-in JSON serializers >>> json = serializers.serialize("json", Category.objects.filter(pk=2)) >>> json -'[{"pk": "2", "model": "serializers.category", "fields": {"name": "Music"}}]' +'[{"pk": 2, "model": "serializers.category", "fields": {"name": "Music"}}]' # You can easily create new objects by deserializing data with an empty PK # (It's easier to demo this with JSON...) @@ -133,7 +153,7 @@ __test__ = {'API_TESTS':""" >>> json = serializers.serialize("json", AuthorProfile.objects.all()) >>> json -'[{"pk": "1", "model": "serializers.authorprofile", "fields": {"date_of_birth": "1970-01-01"}}]' +'[{"pk": 1, "model": "serializers.authorprofile", "fields": {"date_of_birth": "1970-01-01"}}]' >>> for obj in serializers.deserialize("json", json): ... print obj @@ -141,7 +161,7 @@ __test__ = {'API_TESTS':""" # Objects ids can be referenced before they are defined in the serialization data # However, the deserialization process will need to be contained within a transaction ->>> json = '[{"pk": "3", "model": "serializers.article", "fields": {"headline": "Forward references pose no problem", "pub_date": "2006-06-16 15:00:00", "categories": [4, 1], "author": 4}}, {"pk": "4", "model": "serializers.category", "fields": {"name": "Reference"}}, {"pk": "4", "model": "serializers.author", "fields": {"name": "Agnes"}}]' +>>> json = '[{"pk": 3, "model": "serializers.article", "fields": {"headline": "Forward references pose no problem", "pub_date": "2006-06-16 15:00:00", "categories": [4, 1], "author": 4}}, {"pk": 4, "model": "serializers.category", "fields": {"name": "Reference"}}, {"pk": 4, "model": "serializers.author", "fields": {"name": "Agnes"}}]' >>> from django.db import transaction >>> transaction.enter_transaction_management() >>> transaction.managed(True) @@ -161,6 +181,30 @@ __test__ = {'API_TESTS':""" # Serializer output can be restricted to a subset of fields >>> print serializers.serialize("json", Article.objects.all(), fields=('headline','pub_date')) -[{"pk": "1", "model": "serializers.article", "fields": {"headline": "Just kidding; I love TV poker", "pub_date": "2006-06-16 11:00:00"}}, {"pk": "2", "model": "serializers.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}, {"pk": "3", "model": "serializers.article", "fields": {"headline": "Forward references pose no problem", "pub_date": "2006-06-16 15:00:00"}}] +[{"pk": 1, "model": "serializers.article", "fields": {"headline": "Just kidding; I love TV poker", "pub_date": "2006-06-16 11:00:00"}}, {"pk": 2, "model": "serializers.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}, {"pk": 3, "model": "serializers.article", "fields": {"headline": "Forward references pose no problem", "pub_date": "2006-06-16 15:00:00"}}] + +# Every string is serialized as a unicode object, also primary key +# which is 'varchar' +>>> ac = Actor(name="Zażółć") +>>> mv = Movie(title="Gęślą jaźń", actor=ac) +>>> ac.save(); mv.save() + +# Let's serialize our movie +>>> print serializers.serialize("json", [mv]) +[{"pk": 1, "model": "serializers.movie", "fields": {"actor": "Za\u017c\u00f3\u0142\u0107", "title": "G\u0119\u015bl\u0105 ja\u017a\u0144"}}] + +# Deserialization of movie +>>> list(serializers.deserialize('json', serializers.serialize('json', [mv])))[0].object.title +u'G\u0119\u015bl\u0105 ja\u017a\u0144' + +# None is null after serialization to json +# Primary key is None in case of not saved model +>>> mv2 = Movie(title="Movie 2", actor=ac) +>>> print serializers.serialize("json", [mv2]) +[{"pk": null, "model": "serializers.movie", "fields": {"actor": "Za\u017c\u00f3\u0142\u0107", "title": "Movie 2"}}] + +# Deserialization of null returns None for pk +>>> print list(serializers.deserialize('json', serializers.serialize('json', [mv2])))[0].object.id +None """} diff --git a/tests/modeltests/signals/__init__.py b/tests/modeltests/signals/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/modeltests/signals/__init__.py diff --git a/tests/modeltests/signals/models.py b/tests/modeltests/signals/models.py new file mode 100644 index 0000000000..d41142135e --- /dev/null +++ b/tests/modeltests/signals/models.py @@ -0,0 +1,85 @@ +""" +Testing signals before/after saving and deleting. +""" + +from django.db import models +from django.dispatch import dispatcher + +class Person(models.Model): + first_name = models.CharField(max_length=20) + last_name = models.CharField(max_length=20) + + def __unicode__(self): + return u"%s %s" % (self.first_name, self.last_name) + + +def pre_save_test(sender, instance, **kwargs): + print 'pre_save signal,', instance + +def post_save_test(sender, instance, **kwargs): + print 'post_save signal,', instance + if 'created' in kwargs: + if kwargs['created']: + print 'Is created' + else: + print 'Is updated' + +def pre_delete_test(sender, instance, **kwargs): + print 'pre_delete signal,', instance + print 'instance.id is not None: %s' % (instance.id != None) + +def post_delete_test(sender, instance, **kwargs): + print 'post_delete signal,', instance + print 'instance.id is None: %s' % (instance.id == None) + +__test__ = {'API_TESTS':""" +>>> dispatcher.connect(pre_save_test, signal=models.signals.pre_save) +>>> dispatcher.connect(post_save_test, signal=models.signals.post_save) +>>> dispatcher.connect(pre_delete_test, signal=models.signals.pre_delete) +>>> dispatcher.connect(post_delete_test, signal=models.signals.post_delete) + +>>> p1 = Person(first_name='John', last_name='Smith') +>>> p1.save() +pre_save signal, John Smith +post_save signal, John Smith +Is created + +>>> p1.first_name = 'Tom' +>>> p1.save() +pre_save signal, Tom Smith +post_save signal, Tom Smith +Is updated + +>>> p1.delete() +pre_delete signal, Tom Smith +instance.id is not None: True +post_delete signal, Tom Smith +instance.id is None: True + +>>> p2 = Person(first_name='James', last_name='Jones') +>>> p2.id = 99999 +>>> p2.save() +pre_save signal, James Jones +post_save signal, James Jones +Is created + +>>> p2.id = 99998 +>>> p2.save() +pre_save signal, James Jones +post_save signal, James Jones +Is created + +>>> p2.delete() +pre_delete signal, James Jones +instance.id is not None: True +post_delete signal, James Jones +instance.id is None: True + +>>> Person.objects.all() +[<Person: James Jones>] + +>>> dispatcher.disconnect(post_delete_test, signal=models.signals.post_delete) +>>> dispatcher.disconnect(pre_delete_test, signal=models.signals.pre_delete) +>>> dispatcher.disconnect(post_save_test, signal=models.signals.post_save) +>>> dispatcher.disconnect(pre_save_test, signal=models.signals.pre_save) +"""} diff --git a/tests/modeltests/test_client/models.py b/tests/modeltests/test_client/models.py index e1f3987847..2df5d3cf77 100644 --- a/tests/modeltests/test_client/models.py +++ b/tests/modeltests/test_client/models.py @@ -83,16 +83,31 @@ class ClientTest(TestCase): def test_redirect(self): "GET a URL that redirects elsewhere" response = self.client.get('/test_client/redirect_view/') - # Check that the response was a 302 (redirect) - self.assertRedirects(response, '/test_client/get_view/') + self.assertRedirects(response, 'http://testserver/test_client/get_view/') + + client_providing_host = Client(HTTP_HOST='django.testserver') + response = client_providing_host.get('/test_client/redirect_view/') + # Check that the response was a 302 (redirect) with absolute URI + self.assertRedirects(response, 'http://django.testserver/test_client/get_view/') + + def test_redirect_with_query(self): + "GET a URL that redirects with given GET parameters" + response = self.client.get('/test_client/redirect_view/', {'var': 'value'}) + + # Check if parameters are intact + self.assertRedirects(response, 'http://testserver/test_client/get_view/?var=value') def test_permanent_redirect(self): "GET a URL that redirects permanently elsewhere" response = self.client.get('/test_client/permanent_redirect_view/') - # Check that the response was a 301 (permanent redirect) - self.assertRedirects(response, '/test_client/get_view/', status_code=301) + self.assertRedirects(response, 'http://testserver/test_client/get_view/', status_code=301) + + client_providing_host = Client(HTTP_HOST='django.testserver') + response = client_providing_host.get('/test_client/permanent_redirect_view/') + # Check that the response was a 301 (permanent redirect) with absolute URI + self.assertRedirects(response, 'http://django.testserver/test_client/get_view/', status_code=301) def test_redirect_to_strange_location(self): "GET a URL that redirects to a non-200 page" @@ -100,7 +115,7 @@ class ClientTest(TestCase): # Check that the response was a 302, and that # the attempt to get the redirection location returned 301 when retrieved - self.assertRedirects(response, '/test_client/permanent_redirect_view/', target_status_code=301) + self.assertRedirects(response, 'http://testserver/test_client/permanent_redirect_view/', target_status_code=301) def test_notfound_response(self): "GET a URL that responds as '404:Not Found'" @@ -224,16 +239,33 @@ class ClientTest(TestCase): # Get the page without logging in. Should result in 302. response = self.client.get('/test_client/login_protected_view/') - self.assertRedirects(response, '/accounts/login/') + self.assertRedirects(response, 'http://testserver/accounts/login/?next=/test_client/login_protected_view/') # Log in - self.client.login(username='testclient', password='password') + login = self.client.login(username='testclient', password='password') + self.failUnless(login, 'Could not log in') # Request a page that requires a login response = self.client.get('/test_client/login_protected_view/') self.assertEqual(response.status_code, 200) self.assertEqual(response.context['user'].username, 'testclient') + def test_view_with_login_and_custom_redirect(self): + "Request a page that is protected with @login_required(redirect_field_name='redirect_to')" + + # Get the page without logging in. Should result in 302. + response = self.client.get('/test_client/login_protected_view_custom_redirect/') + self.assertRedirects(response, 'http://testserver/accounts/login/?redirect_to=/test_client/login_protected_view_custom_redirect/') + + # Log in + login = self.client.login(username='testclient', password='password') + self.failUnless(login, 'Could not log in') + + # Request a page that requires a login + response = self.client.get('/test_client/login_protected_view_custom_redirect/') + self.assertEqual(response.status_code, 200) + self.assertEqual(response.context['user'].username, 'testclient') + def test_view_with_bad_login(self): "Request a page that is protected with @login, but use bad credentials" @@ -261,7 +293,7 @@ class ClientTest(TestCase): # Request a page that requires a login response = self.client.get('/test_client/login_protected_view/') - self.assertRedirects(response, '/accounts/login/') + self.assertRedirects(response, 'http://testserver/accounts/login/?next=/test_client/login_protected_view/') def test_session_modifying_view(self): "Request a page that modifies the session" diff --git a/tests/modeltests/test_client/urls.py b/tests/modeltests/test_client/urls.py index 538c0e4b43..3779a0ecd1 100644 --- a/tests/modeltests/test_client/urls.py +++ b/tests/modeltests/test_client/urls.py @@ -13,6 +13,7 @@ urlpatterns = patterns('', (r'^form_view/$', views.form_view), (r'^form_view_with_template/$', views.form_view_with_template), (r'^login_protected_view/$', views.login_protected_view), + (r'^login_protected_view_custom_redirect/$', views.login_protected_view_changed_redirect), (r'^session_view/$', views.session_view), (r'^broken_view/$', views.broken_view), (r'^mail_sending_view/$', views.mail_sending_view), diff --git a/tests/modeltests/test_client/views.py b/tests/modeltests/test_client/views.py index 81b4a2f283..c406e17d30 100644 --- a/tests/modeltests/test_client/views.py +++ b/tests/modeltests/test_client/views.py @@ -1,4 +1,5 @@ from xml.dom.minidom import parseString + from django.core.mail import EmailMessage, SMTPConnection from django.template import Context, Template from django.http import HttpResponse, HttpResponseRedirect, HttpResponseNotFound @@ -11,7 +12,7 @@ def get_view(request): "A simple view that expects a GET request, and returns a rendered template" t = Template('This is a test. {{ var }} is the value.', name='GET Template') c = Context({'var': request.GET.get('var', 42)}) - + return HttpResponse(t.render(c)) def post_view(request): @@ -28,9 +29,9 @@ def post_view(request): else: t = Template('Viewing GET page.', name='Empty GET Template') c = Context() - + return HttpResponse(t.render(c)) - + def raw_post_view(request): """A view which expects raw XML to be posted and returns content extracted from the XML""" @@ -48,7 +49,12 @@ def raw_post_view(request): def redirect_view(request): "A view that redirects all requests to the GET view" - return HttpResponseRedirect('/test_client/get_view/') + if request.GET: + from urllib import urlencode + query = '?' + urlencode(request.GET, True) + else: + query = '' + return HttpResponseRedirect('/test_client/get_view/' + query) def double_redirect_view(request): "A view that redirects all requests to a redirection view" @@ -72,7 +78,7 @@ class TestForm(Form): value = fields.IntegerField() single = fields.ChoiceField(choices=TestChoices) multi = fields.MultipleChoiceField(choices=TestChoices) - + def form_view(request): "A view that tests a simple form" if request.method == 'POST': @@ -87,7 +93,7 @@ def form_view(request): form = TestForm(request.GET) t = Template('Viewing base form. {{ form }}.', name='Form GET Template') c = Context({'form': form}) - + return HttpResponse(t.render(c)) def form_view_with_template(request): @@ -101,26 +107,34 @@ def form_view_with_template(request): else: form = TestForm() message = 'GET form page' - return render_to_response('form_view.html', - { + return render_to_response('form_view.html', + { 'form': form, 'message': message } ) - + def login_protected_view(request): "A simple view that is login protected." t = Template('This is a login protected test. Username is {{ user.username }}.', name='Login Template') c = Context({'user': request.user}) - + return HttpResponse(t.render(c)) login_protected_view = login_required(login_protected_view) +def login_protected_view_changed_redirect(request): + "A simple view that is login protected with a custom redirect field set" + t = Template('This is a login protected test. Username is {{ user.username }}.', name='Login Template') + c = Context({'user': request.user}) + + return HttpResponse(t.render(c)) +login_protected_view_changed_redirect = login_required(redirect_field_name="redirect_to")(login_protected_view_changed_redirect) + def session_view(request): "A view that modifies the session" request.session['tobacconist'] = 'hovercraft' - - t = Template('This is a view that modifies the session.', + + t = Template('This is a view that modifies the session.', name='Session Modifying View Template') c = Context() return HttpResponse(t.render(c)) @@ -131,25 +145,25 @@ def broken_view(request): def mail_sending_view(request): EmailMessage( - "Test message", - "This is a test email", - "from@example.com", + "Test message", + "This is a test email", + "from@example.com", ['first@example.com', 'second@example.com']).send() return HttpResponse("Mail sent") def mass_mail_sending_view(request): m1 = EmailMessage( - 'First Test message', - 'This is the first test email', - 'from@example.com', + 'First Test message', + 'This is the first test email', + 'from@example.com', ['first@example.com', 'second@example.com']) m2 = EmailMessage( - 'Second Test message', - 'This is the second test email', - 'from@example.com', + 'Second Test message', + 'This is the second test email', + 'from@example.com', ['second@example.com', 'third@example.com']) - + c = SMTPConnection() c.send_messages([m1,m2]) - + return HttpResponse("Mail sent") diff --git a/tests/regressiontests/auth_backends/__init__.py b/tests/regressiontests/auth_backends/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/regressiontests/auth_backends/__init__.py diff --git a/tests/regressiontests/auth_backends/models.py b/tests/regressiontests/auth_backends/models.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/regressiontests/auth_backends/models.py diff --git a/tests/regressiontests/auth_backends/tests.py b/tests/regressiontests/auth_backends/tests.py new file mode 100644 index 0000000000..71e58442e7 --- /dev/null +++ b/tests/regressiontests/auth_backends/tests.py @@ -0,0 +1,66 @@ +""" +>>> from django.contrib.auth.models import User, Group, Permission +>>> from django.contrib.contenttypes.models import ContentType + +# No Permissions assigned yet, should return False except for superuser + +>>> user = User.objects.create_user('test', 'test@example.com', 'test') +>>> user.has_perm("auth.test") +False +>>> user.is_staff=True +>>> user.save() +>>> user.has_perm("auth.test") +False +>>> user.is_superuser=True +>>> user.save() +>>> user.has_perm("auth.test") +True +>>> user.is_staff = False +>>> user.is_superuser = False +>>> user.save() +>>> user.has_perm("auth.test") +False +>>> content_type=ContentType.objects.get_for_model(Group) +>>> perm = Permission.objects.create(name="test", content_type=content_type, codename="test") +>>> user.user_permissions.add(perm) +>>> user.save() + +# reloading user to purge the _perm_cache + +>>> user = User.objects.get(username="test") +>>> user.get_all_permissions() +set([u'auth.test']) +>>> user.get_group_permissions() +set([]) +>>> user.has_module_perms("Group") +False +>>> user.has_module_perms("auth") +True +>>> perm = Permission.objects.create(name="test2", content_type=content_type, codename="test2") +>>> user.user_permissions.add(perm) +>>> user.save() +>>> perm = Permission.objects.create(name="test3", content_type=content_type, codename="test3") +>>> user.user_permissions.add(perm) +>>> user.save() +>>> user = User.objects.get(username="test") +>>> user.get_all_permissions() +set([u'auth.test2', u'auth.test', u'auth.test3']) +>>> user.has_perm('test') +False +>>> user.has_perm('auth.test') +True +>>> user.has_perms(['auth.test2', 'auth.test3']) +True +>>> perm = Permission.objects.create(name="test_group", content_type=content_type, codename="test_group") +>>> group = Group.objects.create(name='test_group') +>>> group.permissions.add(perm) +>>> group.save() +>>> user.groups.add(group) +>>> user = User.objects.get(username="test") +>>> user.get_all_permissions() +set([u'auth.test2', u'auth.test', u'auth.test3', u'auth.test_group']) +>>> user.get_group_permissions() +set([u'auth.test_group']) +>>> user.has_perms(['auth.test3', 'auth.test_group']) +True +"""
\ No newline at end of file diff --git a/tests/regressiontests/backends/__init__.py b/tests/regressiontests/backends/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/regressiontests/backends/__init__.py diff --git a/tests/regressiontests/backends/models.py b/tests/regressiontests/backends/models.py new file mode 100644 index 0000000000..db16d2c198 --- /dev/null +++ b/tests/regressiontests/backends/models.py @@ -0,0 +1,35 @@ +from django.db import models +from django.db import connection + +class Square(models.Model): + root = models.IntegerField() + square = models.PositiveIntegerField() + + def __unicode__(self): + return "%s ** 2 == %s" % (self.root, self.square) + +if connection.features.uses_case_insensitive_names: + t_convert = lambda x: x.upper() +else: + t_convert = lambda x: x +qn = connection.ops.quote_name + +__test__ = {'API_TESTS': """ + +#4896: Test cursor.executemany +>>> from django.db import connection +>>> cursor = connection.cursor() +>>> opts = Square._meta +>>> f1, f2 = opts.get_field('root'), opts.get_field('square') +>>> query = ('INSERT INTO %s (%s, %s) VALUES (%%s, %%s)' +... % (t_convert(opts.db_table), qn(f1.column), qn(f2.column))) +>>> cursor.executemany(query, [(i, i**2) for i in range(-5, 6)]) and None or None +>>> Square.objects.order_by('root') +[<Square: -5 ** 2 == 25>, <Square: -4 ** 2 == 16>, <Square: -3 ** 2 == 9>, <Square: -2 ** 2 == 4>, <Square: -1 ** 2 == 1>, <Square: 0 ** 2 == 0>, <Square: 1 ** 2 == 1>, <Square: 2 ** 2 == 4>, <Square: 3 ** 2 == 9>, <Square: 4 ** 2 == 16>, <Square: 5 ** 2 == 25>] + +#4765: executemany with params=[] does nothing +>>> cursor.executemany(query, []) and None or None +>>> Square.objects.count() +11 + +"""} diff --git a/tests/regressiontests/fixtures_regress/models.py b/tests/regressiontests/fixtures_regress/models.py index c6a50f73ce..a62925eb37 100644 --- a/tests/regressiontests/fixtures_regress/models.py +++ b/tests/regressiontests/fixtures_regress/models.py @@ -1,5 +1,6 @@ from django.db import models from django.contrib.auth.models import User +from django.conf import settings class Animal(models.Model): name = models.CharField(max_length=150) @@ -20,7 +21,12 @@ class Stuff(models.Model): owner = models.ForeignKey(User, null=True) def __unicode__(self): - return unicode(self.name) + u' is owned by ' + unicode(self.owner) + # Oracle doesn't distinguish between None and the empty string. + # This hack makes the test case pass using Oracle. + name = self.name + if settings.DATABASE_ENGINE == 'oracle' and name == u'': + name = None + return unicode(name) + u' is owned by ' + unicode(self.owner) __test__ = {'API_TESTS':""" >>> from django.core import management diff --git a/tests/regressiontests/forms/extra.py b/tests/regressiontests/forms/extra.py new file mode 100644 index 0000000000..7f6175f649 --- /dev/null +++ b/tests/regressiontests/forms/extra.py @@ -0,0 +1,398 @@ +# -*- coding: utf-8 -*- +tests = r""" +>>> from django.newforms import * +>>> import datetime +>>> import time +>>> import re +>>> try: +... from decimal import Decimal +... except ImportError: +... from django.utils._decimal import Decimal + +############### +# Extra stuff # +############### + +The newforms library comes with some extra, higher-level Field and Widget +classes that demonstrate some of the library's abilities. + +# SelectDateWidget ############################################################ + +>>> from django.newforms.extras import SelectDateWidget +>>> w = SelectDateWidget(years=('2007','2008','2009','2010','2011','2012','2013','2014','2015','2016')) +>>> print w.render('mydate', '') +<select name="mydate_month"> +<option value="1">January</option> +<option value="2">February</option> +<option value="3">March</option> +<option value="4">April</option> +<option value="5">May</option> +<option value="6">June</option> +<option value="7">July</option> +<option value="8">August</option> +<option value="9">September</option> +<option value="10">October</option> +<option value="11">November</option> +<option value="12">December</option> +</select> +<select name="mydate_day"> +<option value="1">1</option> +<option value="2">2</option> +<option value="3">3</option> +<option value="4">4</option> +<option value="5">5</option> +<option value="6">6</option> +<option value="7">7</option> +<option value="8">8</option> +<option value="9">9</option> +<option value="10">10</option> +<option value="11">11</option> +<option value="12">12</option> +<option value="13">13</option> +<option value="14">14</option> +<option value="15">15</option> +<option value="16">16</option> +<option value="17">17</option> +<option value="18">18</option> +<option value="19">19</option> +<option value="20">20</option> +<option value="21">21</option> +<option value="22">22</option> +<option value="23">23</option> +<option value="24">24</option> +<option value="25">25</option> +<option value="26">26</option> +<option value="27">27</option> +<option value="28">28</option> +<option value="29">29</option> +<option value="30">30</option> +<option value="31">31</option> +</select> +<select name="mydate_year"> +<option value="2007">2007</option> +<option value="2008">2008</option> +<option value="2009">2009</option> +<option value="2010">2010</option> +<option value="2011">2011</option> +<option value="2012">2012</option> +<option value="2013">2013</option> +<option value="2014">2014</option> +<option value="2015">2015</option> +<option value="2016">2016</option> +</select> +>>> w.render('mydate', None) == w.render('mydate', '') +True +>>> print w.render('mydate', '2010-04-15') +<select name="mydate_month"> +<option value="1">January</option> +<option value="2">February</option> +<option value="3">March</option> +<option value="4" selected="selected">April</option> +<option value="5">May</option> +<option value="6">June</option> +<option value="7">July</option> +<option value="8">August</option> +<option value="9">September</option> +<option value="10">October</option> +<option value="11">November</option> +<option value="12">December</option> +</select> +<select name="mydate_day"> +<option value="1">1</option> +<option value="2">2</option> +<option value="3">3</option> +<option value="4">4</option> +<option value="5">5</option> +<option value="6">6</option> +<option value="7">7</option> +<option value="8">8</option> +<option value="9">9</option> +<option value="10">10</option> +<option value="11">11</option> +<option value="12">12</option> +<option value="13">13</option> +<option value="14">14</option> +<option value="15" selected="selected">15</option> +<option value="16">16</option> +<option value="17">17</option> +<option value="18">18</option> +<option value="19">19</option> +<option value="20">20</option> +<option value="21">21</option> +<option value="22">22</option> +<option value="23">23</option> +<option value="24">24</option> +<option value="25">25</option> +<option value="26">26</option> +<option value="27">27</option> +<option value="28">28</option> +<option value="29">29</option> +<option value="30">30</option> +<option value="31">31</option> +</select> +<select name="mydate_year"> +<option value="2007">2007</option> +<option value="2008">2008</option> +<option value="2009">2009</option> +<option value="2010" selected="selected">2010</option> +<option value="2011">2011</option> +<option value="2012">2012</option> +<option value="2013">2013</option> +<option value="2014">2014</option> +<option value="2015">2015</option> +<option value="2016">2016</option> +</select> + +Using a SelectDateWidget in a form: + +>>> class GetDate(Form): +... mydate = DateField(widget=SelectDateWidget) +>>> a = GetDate({'mydate_month':'4', 'mydate_day':'1', 'mydate_year':'2008'}) +>>> print a.is_valid() +True +>>> print a.cleaned_data['mydate'] +2008-04-01 + +As with any widget that implements get_value_from_datadict, +we must be prepared to accept the input from the "as_hidden" +rendering as well. + +>>> print a['mydate'].as_hidden() +<input type="hidden" name="mydate" value="2008-4-1" id="id_mydate" /> +>>> b=GetDate({'mydate':'2008-4-1'}) +>>> print b.is_valid() +True +>>> print b.cleaned_data['mydate'] +2008-04-01 + + +# MultiWidget and MultiValueField ############################################# +# MultiWidgets are widgets composed of other widgets. They are usually +# combined with MultiValueFields - a field that is composed of other fields. +# MulitWidgets can themselved be composed of other MultiWidgets. +# SplitDateTimeWidget is one example of a MultiWidget. + +>>> class ComplexMultiWidget(MultiWidget): +... def __init__(self, attrs=None): +... widgets = ( +... TextInput(), +... SelectMultiple(choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))), +... SplitDateTimeWidget(), +... ) +... super(ComplexMultiWidget, self).__init__(widgets, attrs) +... +... def decompress(self, value): +... if value: +... data = value.split(',') +... return [data[0], data[1], datetime.datetime(*time.strptime(data[2], "%Y-%m-%d %H:%M:%S")[0:6])] +... return [None, None, None] +... def format_output(self, rendered_widgets): +... return u'\n'.join(rendered_widgets) +>>> w = ComplexMultiWidget() +>>> print w.render('name', 'some text,JP,2007-04-25 06:24:00') +<input type="text" name="name_0" value="some text" /> +<select multiple="multiple" name="name_1"> +<option value="J" selected="selected">John</option> +<option value="P" selected="selected">Paul</option> +<option value="G">George</option> +<option value="R">Ringo</option> +</select> +<input type="text" name="name_2_0" value="2007-04-25" /><input type="text" name="name_2_1" value="06:24:00" /> + +>>> class ComplexField(MultiValueField): +... def __init__(self, required=True, widget=None, label=None, initial=None): +... fields = ( +... CharField(), +... MultipleChoiceField(choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))), +... SplitDateTimeField() +... ) +... super(ComplexField, self).__init__(fields, required, widget, label, initial) +... +... def compress(self, data_list): +... if data_list: +... return '%s,%s,%s' % (data_list[0],''.join(data_list[1]),data_list[2]) +... return None + +>>> f = ComplexField(widget=w) +>>> f.clean(['some text', ['J','P'], ['2007-04-25','6:24:00']]) +u'some text,JP,2007-04-25 06:24:00' +>>> f.clean(['some text',['X'], ['2007-04-25','6:24:00']]) +Traceback (most recent call last): +... +ValidationError: [u'Select a valid choice. X is not one of the available choices.'] + +# If insufficient data is provided, None is substituted +>>> f.clean(['some text',['JP']]) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] + +>>> class ComplexFieldForm(Form): +... field1 = ComplexField(widget=w) +>>> f = ComplexFieldForm() +>>> print f +<tr><th><label for="id_field1_0">Field1:</label></th><td><input type="text" name="field1_0" id="id_field1_0" /> +<select multiple="multiple" name="field1_1" id="id_field1_1"> +<option value="J">John</option> +<option value="P">Paul</option> +<option value="G">George</option> +<option value="R">Ringo</option> +</select> +<input type="text" name="field1_2_0" id="id_field1_2_0" /><input type="text" name="field1_2_1" id="id_field1_2_1" /></td></tr> + +>>> f = ComplexFieldForm({'field1_0':'some text','field1_1':['J','P'], 'field1_2_0':'2007-04-25', 'field1_2_1':'06:24:00'}) +>>> print f +<tr><th><label for="id_field1_0">Field1:</label></th><td><input type="text" name="field1_0" value="some text" id="id_field1_0" /> +<select multiple="multiple" name="field1_1" id="id_field1_1"> +<option value="J" selected="selected">John</option> +<option value="P" selected="selected">Paul</option> +<option value="G">George</option> +<option value="R">Ringo</option> +</select> +<input type="text" name="field1_2_0" value="2007-04-25" id="id_field1_2_0" /><input type="text" name="field1_2_1" value="06:24:00" id="id_field1_2_1" /></td></tr> + +>>> f.cleaned_data +{'field1': u'some text,JP,2007-04-25 06:24:00'} + + +# IPAddressField ################################################################## + +>>> f = IPAddressField() +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('127.0.0.1') +u'127.0.0.1' +>>> f.clean('foo') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid IPv4 address.'] +>>> f.clean('127.0.0.') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid IPv4 address.'] +>>> f.clean('1.2.3.4.5') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid IPv4 address.'] +>>> f.clean('256.125.1.5') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid IPv4 address.'] + +>>> f = IPAddressField(required=False) +>>> f.clean('') +u'' +>>> f.clean(None) +u'' +>>> f.clean('127.0.0.1') +u'127.0.0.1' +>>> f.clean('foo') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid IPv4 address.'] +>>> f.clean('127.0.0.') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid IPv4 address.'] +>>> f.clean('1.2.3.4.5') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid IPv4 address.'] +>>> f.clean('256.125.1.5') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid IPv4 address.'] + +################################# +# Tests of underlying functions # +################################# + +# smart_unicode tests +>>> from django.utils.encoding import smart_unicode +>>> class Test: +... def __str__(self): +... return 'ŠĐĆŽćžšđ' +>>> class TestU: +... def __str__(self): +... return 'Foo' +... def __unicode__(self): +... return u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111' +>>> smart_unicode(Test()) +u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111' +>>> smart_unicode(TestU()) +u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111' +>>> smart_unicode(1) +u'1' +>>> smart_unicode('foo') +u'foo' + + +#################################### +# Test accessing errors in clean() # +#################################### + +>>> class UserForm(Form): +... username = CharField(max_length=10) +... password = CharField(widget=PasswordInput) +... def clean(self): +... data = self.cleaned_data +... if not self.errors: +... data['username'] = data['username'].lower() +... return data + +>>> f = UserForm({'username': 'SirRobin', 'password': 'blue'}) +>>> f.is_valid() +True +>>> f.cleaned_data['username'] +u'sirrobin' + +####################################### +# Test overriding ErrorList in a form # +####################################### + +>>> from django.newforms.util import ErrorList +>>> class DivErrorList(ErrorList): +... def __unicode__(self): +... return self.as_divs() +... def as_divs(self): +... if not self: return u'' +... return u'<div class="errorlist">%s</div>' % ''.join([u'<div class="error">%s</div>' % e for e in self]) +>>> class CommentForm(Form): +... name = CharField(max_length=50, required=False) +... email = EmailField() +... comment = CharField() +>>> data = dict(email='invalid') +>>> f = CommentForm(data, auto_id=False, error_class=DivErrorList) +>>> print f.as_p() +<p>Name: <input type="text" name="name" maxlength="50" /></p> +<div class="errorlist"><div class="error">Enter a valid e-mail address.</div></div> +<p>Email: <input type="text" name="email" value="invalid" /></p> +<div class="errorlist"><div class="error">This field is required.</div></div> +<p>Comment: <input type="text" name="comment" /></p> + +################################# +# Test multipart-encoded form # +################################# + +>>> class FormWithoutFile(Form): +... username = CharField() +>>> class FormWithFile(Form): +... username = CharField() +... file = FileField() +>>> class FormWithImage(Form): +... image = ImageField() + +>>> FormWithoutFile().is_multipart() +False +>>> FormWithFile().is_multipart() +True +>>> FormWithImage().is_multipart() +True + +""" diff --git a/tests/regressiontests/forms/fields.py b/tests/regressiontests/forms/fields.py new file mode 100644 index 0000000000..3b93d70338 --- /dev/null +++ b/tests/regressiontests/forms/fields.py @@ -0,0 +1,1162 @@ +# -*- coding: utf-8 -*- +tests = r""" +>>> from django.newforms import * +>>> from django.newforms.widgets import RadioFieldRenderer +>>> import datetime +>>> import time +>>> import re +>>> try: +... from decimal import Decimal +... except ImportError: +... from django.utils._decimal import Decimal + + +########## +# Fields # +########## + +Each Field class does some sort of validation. Each Field has a clean() method, +which either raises django.newforms.ValidationError or returns the "clean" +data -- usually a Unicode object, but, in some rare cases, a list. + +Each Field's __init__() takes at least these parameters: + required -- Boolean that specifies whether the field is required. + True by default. + widget -- A Widget class, or instance of a Widget class, that should be + used for this Field when displaying it. Each Field has a default + Widget that it'll use if you don't specify this. In most cases, + the default widget is TextInput. + label -- A verbose name for this field, for use in displaying this field in + a form. By default, Django will use a "pretty" version of the form + field name, if the Field is part of a Form. + initial -- A value to use in this Field's initial display. This value is + *not* used as a fallback if data isn't given. + +Other than that, the Field subclasses have class-specific options for +__init__(). For example, CharField has a max_length option. + +# CharField ################################################################### + +>>> f = CharField() +>>> f.clean(1) +u'1' +>>> f.clean('hello') +u'hello' +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean([1, 2, 3]) +u'[1, 2, 3]' + +>>> f = CharField(required=False) +>>> f.clean(1) +u'1' +>>> f.clean('hello') +u'hello' +>>> f.clean(None) +u'' +>>> f.clean('') +u'' +>>> f.clean([1, 2, 3]) +u'[1, 2, 3]' + +CharField accepts an optional max_length parameter: +>>> f = CharField(max_length=10, required=False) +>>> f.clean('12345') +u'12345' +>>> f.clean('1234567890') +u'1234567890' +>>> f.clean('1234567890a') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value has at most 10 characters (it has 11).'] + +CharField accepts an optional min_length parameter: +>>> f = CharField(min_length=10, required=False) +>>> f.clean('') +u'' +>>> f.clean('12345') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value has at least 10 characters (it has 5).'] +>>> f.clean('1234567890') +u'1234567890' +>>> f.clean('1234567890a') +u'1234567890a' + +>>> f = CharField(min_length=10, required=True) +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('12345') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value has at least 10 characters (it has 5).'] +>>> f.clean('1234567890') +u'1234567890' +>>> f.clean('1234567890a') +u'1234567890a' + +# IntegerField ################################################################ + +>>> f = IntegerField() +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('1') +1 +>>> isinstance(f.clean('1'), int) +True +>>> f.clean('23') +23 +>>> f.clean('a') +Traceback (most recent call last): +... +ValidationError: [u'Enter a whole number.'] +>>> f.clean(42) +42 +>>> f.clean(3.14) +Traceback (most recent call last): +... +ValidationError: [u'Enter a whole number.'] +>>> f.clean('1 ') +1 +>>> f.clean(' 1') +1 +>>> f.clean(' 1 ') +1 +>>> f.clean('1a') +Traceback (most recent call last): +... +ValidationError: [u'Enter a whole number.'] + +>>> f = IntegerField(required=False) +>>> f.clean('') +>>> repr(f.clean('')) +'None' +>>> f.clean(None) +>>> repr(f.clean(None)) +'None' +>>> f.clean('1') +1 +>>> isinstance(f.clean('1'), int) +True +>>> f.clean('23') +23 +>>> f.clean('a') +Traceback (most recent call last): +... +ValidationError: [u'Enter a whole number.'] +>>> f.clean('1 ') +1 +>>> f.clean(' 1') +1 +>>> f.clean(' 1 ') +1 +>>> f.clean('1a') +Traceback (most recent call last): +... +ValidationError: [u'Enter a whole number.'] + +IntegerField accepts an optional max_value parameter: +>>> f = IntegerField(max_value=10) +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean(1) +1 +>>> f.clean(10) +10 +>>> f.clean(11) +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value is less than or equal to 10.'] +>>> f.clean('10') +10 +>>> f.clean('11') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value is less than or equal to 10.'] + +IntegerField accepts an optional min_value parameter: +>>> f = IntegerField(min_value=10) +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean(1) +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value is greater than or equal to 10.'] +>>> f.clean(10) +10 +>>> f.clean(11) +11 +>>> f.clean('10') +10 +>>> f.clean('11') +11 + +min_value and max_value can be used together: +>>> f = IntegerField(min_value=10, max_value=20) +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean(1) +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value is greater than or equal to 10.'] +>>> f.clean(10) +10 +>>> f.clean(11) +11 +>>> f.clean('10') +10 +>>> f.clean('11') +11 +>>> f.clean(20) +20 +>>> f.clean(21) +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value is less than or equal to 20.'] + +# FloatField ################################################################## + +>>> f = FloatField() +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('1') +1.0 +>>> isinstance(f.clean('1'), float) +True +>>> f.clean('23') +23.0 +>>> f.clean('3.14') +3.1400000000000001 +>>> f.clean(3.14) +3.1400000000000001 +>>> f.clean(42) +42.0 +>>> f.clean('a') +Traceback (most recent call last): +... +ValidationError: [u'Enter a number.'] +>>> f.clean('1.0 ') +1.0 +>>> f.clean(' 1.0') +1.0 +>>> f.clean(' 1.0 ') +1.0 +>>> f.clean('1.0a') +Traceback (most recent call last): +... +ValidationError: [u'Enter a number.'] + +>>> f = FloatField(required=False) +>>> f.clean('') + +>>> f.clean(None) + +>>> f.clean('1') +1.0 + +FloatField accepts min_value and max_value just like IntegerField: +>>> f = FloatField(max_value=1.5, min_value=0.5) + +>>> f.clean('1.6') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value is less than or equal to 1.5.'] +>>> f.clean('0.4') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value is greater than or equal to 0.5.'] +>>> f.clean('1.5') +1.5 +>>> f.clean('0.5') +0.5 + +# DecimalField ################################################################ + +>>> f = DecimalField(max_digits=4, decimal_places=2) +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('1') +Decimal("1") +>>> isinstance(f.clean('1'), Decimal) +True +>>> f.clean('23') +Decimal("23") +>>> f.clean('3.14') +Decimal("3.14") +>>> f.clean(3.14) +Decimal("3.14") +>>> f.clean(Decimal('3.14')) +Decimal("3.14") +>>> f.clean('a') +Traceback (most recent call last): +... +ValidationError: [u'Enter a number.'] +>>> f.clean('1.0 ') +Decimal("1.0") +>>> f.clean(' 1.0') +Decimal("1.0") +>>> f.clean(' 1.0 ') +Decimal("1.0") +>>> f.clean('1.0a') +Traceback (most recent call last): +... +ValidationError: [u'Enter a number.'] +>>> f.clean('123.45') +Traceback (most recent call last): +... +ValidationError: [u'Ensure that there are no more than 4 digits in total.'] +>>> f.clean('1.234') +Traceback (most recent call last): +... +ValidationError: [u'Ensure that there are no more than 2 decimal places.'] +>>> f.clean('123.4') +Traceback (most recent call last): +... +ValidationError: [u'Ensure that there are no more than 2 digits before the decimal point.'] +>>> f.clean('-12.34') +Decimal("-12.34") +>>> f.clean('-123.45') +Traceback (most recent call last): +... +ValidationError: [u'Ensure that there are no more than 4 digits in total.'] +>>> f.clean('-.12') +Decimal("-0.12") +>>> f.clean('-00.12') +Decimal("-0.12") +>>> f.clean('-000.12') +Decimal("-0.12") +>>> f.clean('-000.123') +Traceback (most recent call last): +... +ValidationError: [u'Ensure that there are no more than 2 decimal places.'] +>>> f.clean('-000.1234') +Traceback (most recent call last): +... +ValidationError: [u'Ensure that there are no more than 4 digits in total.'] +>>> f.clean('--0.12') +Traceback (most recent call last): +... +ValidationError: [u'Enter a number.'] + +>>> f = DecimalField(max_digits=4, decimal_places=2, required=False) +>>> f.clean('') + +>>> f.clean(None) + +>>> f.clean('1') +Decimal("1") + +DecimalField accepts min_value and max_value just like IntegerField: +>>> f = DecimalField(max_digits=4, decimal_places=2, max_value=Decimal('1.5'), min_value=Decimal('0.5')) + +>>> f.clean('1.6') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value is less than or equal to 1.5.'] +>>> f.clean('0.4') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value is greater than or equal to 0.5.'] +>>> f.clean('1.5') +Decimal("1.5") +>>> f.clean('0.5') +Decimal("0.5") +>>> f.clean('.5') +Decimal("0.5") +>>> f.clean('00.50') +Decimal("0.50") + +# DateField ################################################################### + +>>> import datetime +>>> f = DateField() +>>> f.clean(datetime.date(2006, 10, 25)) +datetime.date(2006, 10, 25) +>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30)) +datetime.date(2006, 10, 25) +>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59)) +datetime.date(2006, 10, 25) +>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59, 200)) +datetime.date(2006, 10, 25) +>>> f.clean('2006-10-25') +datetime.date(2006, 10, 25) +>>> f.clean('10/25/2006') +datetime.date(2006, 10, 25) +>>> f.clean('10/25/06') +datetime.date(2006, 10, 25) +>>> f.clean('Oct 25 2006') +datetime.date(2006, 10, 25) +>>> f.clean('October 25 2006') +datetime.date(2006, 10, 25) +>>> f.clean('October 25, 2006') +datetime.date(2006, 10, 25) +>>> f.clean('25 October 2006') +datetime.date(2006, 10, 25) +>>> f.clean('25 October, 2006') +datetime.date(2006, 10, 25) +>>> f.clean('2006-4-31') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid date.'] +>>> f.clean('200a-10-25') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid date.'] +>>> f.clean('25/10/06') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid date.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] + +>>> f = DateField(required=False) +>>> f.clean(None) +>>> repr(f.clean(None)) +'None' +>>> f.clean('') +>>> repr(f.clean('')) +'None' + +DateField accepts an optional input_formats parameter: +>>> f = DateField(input_formats=['%Y %m %d']) +>>> f.clean(datetime.date(2006, 10, 25)) +datetime.date(2006, 10, 25) +>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30)) +datetime.date(2006, 10, 25) +>>> f.clean('2006 10 25') +datetime.date(2006, 10, 25) + +The input_formats parameter overrides all default input formats, +so the default formats won't work unless you specify them: +>>> f.clean('2006-10-25') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid date.'] +>>> f.clean('10/25/2006') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid date.'] +>>> f.clean('10/25/06') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid date.'] + +# TimeField ################################################################### + +>>> import datetime +>>> f = TimeField() +>>> f.clean(datetime.time(14, 25)) +datetime.time(14, 25) +>>> f.clean(datetime.time(14, 25, 59)) +datetime.time(14, 25, 59) +>>> f.clean('14:25') +datetime.time(14, 25) +>>> f.clean('14:25:59') +datetime.time(14, 25, 59) +>>> f.clean('hello') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid time.'] +>>> f.clean('1:24 p.m.') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid time.'] + +TimeField accepts an optional input_formats parameter: +>>> f = TimeField(input_formats=['%I:%M %p']) +>>> f.clean(datetime.time(14, 25)) +datetime.time(14, 25) +>>> f.clean(datetime.time(14, 25, 59)) +datetime.time(14, 25, 59) +>>> f.clean('4:25 AM') +datetime.time(4, 25) +>>> f.clean('4:25 PM') +datetime.time(16, 25) + +The input_formats parameter overrides all default input formats, +so the default formats won't work unless you specify them: +>>> f.clean('14:30:45') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid time.'] + +# DateTimeField ############################################################### + +>>> import datetime +>>> f = DateTimeField() +>>> f.clean(datetime.date(2006, 10, 25)) +datetime.datetime(2006, 10, 25, 0, 0) +>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30)) +datetime.datetime(2006, 10, 25, 14, 30) +>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59)) +datetime.datetime(2006, 10, 25, 14, 30, 59) +>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59, 200)) +datetime.datetime(2006, 10, 25, 14, 30, 59, 200) +>>> f.clean('2006-10-25 14:30:45') +datetime.datetime(2006, 10, 25, 14, 30, 45) +>>> f.clean('2006-10-25 14:30:00') +datetime.datetime(2006, 10, 25, 14, 30) +>>> f.clean('2006-10-25 14:30') +datetime.datetime(2006, 10, 25, 14, 30) +>>> f.clean('2006-10-25') +datetime.datetime(2006, 10, 25, 0, 0) +>>> f.clean('10/25/2006 14:30:45') +datetime.datetime(2006, 10, 25, 14, 30, 45) +>>> f.clean('10/25/2006 14:30:00') +datetime.datetime(2006, 10, 25, 14, 30) +>>> f.clean('10/25/2006 14:30') +datetime.datetime(2006, 10, 25, 14, 30) +>>> f.clean('10/25/2006') +datetime.datetime(2006, 10, 25, 0, 0) +>>> f.clean('10/25/06 14:30:45') +datetime.datetime(2006, 10, 25, 14, 30, 45) +>>> f.clean('10/25/06 14:30:00') +datetime.datetime(2006, 10, 25, 14, 30) +>>> f.clean('10/25/06 14:30') +datetime.datetime(2006, 10, 25, 14, 30) +>>> f.clean('10/25/06') +datetime.datetime(2006, 10, 25, 0, 0) +>>> f.clean('hello') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid date/time.'] +>>> f.clean('2006-10-25 4:30 p.m.') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid date/time.'] + +DateField accepts an optional input_formats parameter: +>>> f = DateTimeField(input_formats=['%Y %m %d %I:%M %p']) +>>> f.clean(datetime.date(2006, 10, 25)) +datetime.datetime(2006, 10, 25, 0, 0) +>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30)) +datetime.datetime(2006, 10, 25, 14, 30) +>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59)) +datetime.datetime(2006, 10, 25, 14, 30, 59) +>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59, 200)) +datetime.datetime(2006, 10, 25, 14, 30, 59, 200) +>>> f.clean('2006 10 25 2:30 PM') +datetime.datetime(2006, 10, 25, 14, 30) + +The input_formats parameter overrides all default input formats, +so the default formats won't work unless you specify them: +>>> f.clean('2006-10-25 14:30:45') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid date/time.'] + +>>> f = DateTimeField(required=False) +>>> f.clean(None) +>>> repr(f.clean(None)) +'None' +>>> f.clean('') +>>> repr(f.clean('')) +'None' + +# RegexField ################################################################## + +>>> f = RegexField('^\d[A-F]\d$') +>>> f.clean('2A2') +u'2A2' +>>> f.clean('3F3') +u'3F3' +>>> f.clean('3G3') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid value.'] +>>> f.clean(' 2A2') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid value.'] +>>> f.clean('2A2 ') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid value.'] +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] + +>>> f = RegexField('^\d[A-F]\d$', required=False) +>>> f.clean('2A2') +u'2A2' +>>> f.clean('3F3') +u'3F3' +>>> f.clean('3G3') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid value.'] +>>> f.clean('') +u'' + +Alternatively, RegexField can take a compiled regular expression: +>>> f = RegexField(re.compile('^\d[A-F]\d$')) +>>> f.clean('2A2') +u'2A2' +>>> f.clean('3F3') +u'3F3' +>>> f.clean('3G3') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid value.'] +>>> f.clean(' 2A2') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid value.'] +>>> f.clean('2A2 ') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid value.'] + +RegexField takes an optional error_message argument: +>>> f = RegexField('^\d\d\d\d$', error_message='Enter a four-digit number.') +>>> f.clean('1234') +u'1234' +>>> f.clean('123') +Traceback (most recent call last): +... +ValidationError: [u'Enter a four-digit number.'] +>>> f.clean('abcd') +Traceback (most recent call last): +... +ValidationError: [u'Enter a four-digit number.'] + +RegexField also access min_length and max_length parameters, for convenience. +>>> f = RegexField('^\d+$', min_length=5, max_length=10) +>>> f.clean('123') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value has at least 5 characters (it has 3).'] +>>> f.clean('abc') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value has at least 5 characters (it has 3).'] +>>> f.clean('12345') +u'12345' +>>> f.clean('1234567890') +u'1234567890' +>>> f.clean('12345678901') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value has at most 10 characters (it has 11).'] +>>> f.clean('12345a') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid value.'] + +# EmailField ################################################################## + +>>> f = EmailField() +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('person@example.com') +u'person@example.com' +>>> f.clean('foo') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid e-mail address.'] +>>> f.clean('foo@') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid e-mail address.'] +>>> f.clean('foo@bar') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid e-mail address.'] + +>>> f = EmailField(required=False) +>>> f.clean('') +u'' +>>> f.clean(None) +u'' +>>> f.clean('person@example.com') +u'person@example.com' +>>> f.clean('foo') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid e-mail address.'] +>>> f.clean('foo@') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid e-mail address.'] +>>> f.clean('foo@bar') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid e-mail address.'] + +EmailField also access min_length and max_length parameters, for convenience. +>>> f = EmailField(min_length=10, max_length=15) +>>> f.clean('a@foo.com') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value has at least 10 characters (it has 9).'] +>>> f.clean('alf@foo.com') +u'alf@foo.com' +>>> f.clean('alf123456788@foo.com') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value has at most 15 characters (it has 20).'] + +# FileField ################################################################## + +>>> f = FileField() +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] + +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] + +>>> f.clean({}) +Traceback (most recent call last): +... +ValidationError: [u'No file was submitted.'] + +>>> f.clean('some content that is not a file') +Traceback (most recent call last): +... +ValidationError: [u'No file was submitted. Check the encoding type on the form.'] + +>>> f.clean({'filename': 'name', 'content':None}) +Traceback (most recent call last): +... +ValidationError: [u'The submitted file is empty.'] + +>>> f.clean({'filename': 'name', 'content':''}) +Traceback (most recent call last): +... +ValidationError: [u'The submitted file is empty.'] + +>>> type(f.clean({'filename': 'name', 'content':'Some File Content'})) +<class 'django.newforms.fields.UploadedFile'> + +# URLField ################################################################## + +>>> f = URLField() +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('http://localhost') +u'http://localhost' +>>> f.clean('http://example.com') +u'http://example.com' +>>> f.clean('http://www.example.com') +u'http://www.example.com' +>>> f.clean('http://www.example.com:8000/test') +u'http://www.example.com:8000/test' +>>> f.clean('http://200.8.9.10') +u'http://200.8.9.10' +>>> f.clean('http://200.8.9.10:8000/test') +u'http://200.8.9.10:8000/test' +>>> f.clean('foo') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid URL.'] +>>> f.clean('http://') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid URL.'] +>>> f.clean('http://example') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid URL.'] +>>> f.clean('http://example.') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid URL.'] +>>> f.clean('http://.com') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid URL.'] + +>>> f = URLField(required=False) +>>> f.clean('') +u'' +>>> f.clean(None) +u'' +>>> f.clean('http://example.com') +u'http://example.com' +>>> f.clean('http://www.example.com') +u'http://www.example.com' +>>> f.clean('foo') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid URL.'] +>>> f.clean('http://') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid URL.'] +>>> f.clean('http://example') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid URL.'] +>>> f.clean('http://example.') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid URL.'] +>>> f.clean('http://.com') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid URL.'] + +URLField takes an optional verify_exists parameter, which is False by default. +This verifies that the URL is live on the Internet and doesn't return a 404 or 500: +>>> f = URLField(verify_exists=True) +>>> f.clean('http://www.google.com') # This will fail if there's no Internet connection +u'http://www.google.com' +>>> f.clean('http://example') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid URL.'] +>>> f.clean('http://www.jfoiwjfoi23jfoijoaijfoiwjofiwjefewl.com') # bad domain +Traceback (most recent call last): +... +ValidationError: [u'This URL appears to be a broken link.'] +>>> f.clean('http://google.com/we-love-microsoft.html') # good domain, bad page +Traceback (most recent call last): +... +ValidationError: [u'This URL appears to be a broken link.'] +>>> f = URLField(verify_exists=True, required=False) +>>> f.clean('') +u'' +>>> f.clean('http://www.google.com') # This will fail if there's no Internet connection +u'http://www.google.com' + +URLField also access min_length and max_length parameters, for convenience. +>>> f = URLField(min_length=15, max_length=20) +>>> f.clean('http://f.com') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value has at least 15 characters (it has 12).'] +>>> f.clean('http://example.com') +u'http://example.com' +>>> f.clean('http://abcdefghijklmnopqrstuvwxyz.com') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value has at most 20 characters (it has 37).'] + +URLField should prepend 'http://' if no scheme was given +>>> f = URLField(required=False) +>>> f.clean('example.com') +u'http://example.com' +>>> f.clean('') +u'' +>>> f.clean('https://example.com') +u'https://example.com' + +# BooleanField ################################################################ + +>>> f = BooleanField() +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean(True) +True +>>> f.clean(False) +False +>>> f.clean(1) +True +>>> f.clean(0) +False +>>> f.clean('Django rocks') +True + +>>> f = BooleanField(required=False) +>>> f.clean('') +False +>>> f.clean(None) +False +>>> f.clean(True) +True +>>> f.clean(False) +False +>>> f.clean(1) +True +>>> f.clean(0) +False +>>> f.clean('Django rocks') +True + +# ChoiceField ################################################################# + +>>> f = ChoiceField(choices=[('1', '1'), ('2', '2')]) +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean(1) +u'1' +>>> f.clean('1') +u'1' +>>> f.clean('3') +Traceback (most recent call last): +... +ValidationError: [u'Select a valid choice. That choice is not one of the available choices.'] + +>>> f = ChoiceField(choices=[('1', '1'), ('2', '2')], required=False) +>>> f.clean('') +u'' +>>> f.clean(None) +u'' +>>> f.clean(1) +u'1' +>>> f.clean('1') +u'1' +>>> f.clean('3') +Traceback (most recent call last): +... +ValidationError: [u'Select a valid choice. That choice is not one of the available choices.'] + +>>> f = ChoiceField(choices=[('J', 'John'), ('P', 'Paul')]) +>>> f.clean('J') +u'J' +>>> f.clean('John') +Traceback (most recent call last): +... +ValidationError: [u'Select a valid choice. That choice is not one of the available choices.'] + +# NullBooleanField ############################################################ + +>>> f = NullBooleanField() +>>> f.clean('') +>>> f.clean(True) +True +>>> f.clean(False) +False +>>> f.clean(None) +>>> f.clean('1') +>>> f.clean('2') +>>> f.clean('3') +>>> f.clean('hello') + +# MultipleChoiceField ######################################################### + +>>> f = MultipleChoiceField(choices=[('1', '1'), ('2', '2')]) +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean([1]) +[u'1'] +>>> f.clean(['1']) +[u'1'] +>>> f.clean(['1', '2']) +[u'1', u'2'] +>>> f.clean([1, '2']) +[u'1', u'2'] +>>> f.clean((1, '2')) +[u'1', u'2'] +>>> f.clean('hello') +Traceback (most recent call last): +... +ValidationError: [u'Enter a list of values.'] +>>> f.clean([]) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean(()) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean(['3']) +Traceback (most recent call last): +... +ValidationError: [u'Select a valid choice. 3 is not one of the available choices.'] + +>>> f = MultipleChoiceField(choices=[('1', '1'), ('2', '2')], required=False) +>>> f.clean('') +[] +>>> f.clean(None) +[] +>>> f.clean([1]) +[u'1'] +>>> f.clean(['1']) +[u'1'] +>>> f.clean(['1', '2']) +[u'1', u'2'] +>>> f.clean([1, '2']) +[u'1', u'2'] +>>> f.clean((1, '2')) +[u'1', u'2'] +>>> f.clean('hello') +Traceback (most recent call last): +... +ValidationError: [u'Enter a list of values.'] +>>> f.clean([]) +[] +>>> f.clean(()) +[] +>>> f.clean(['3']) +Traceback (most recent call last): +... +ValidationError: [u'Select a valid choice. 3 is not one of the available choices.'] + +# ComboField ################################################################## + +ComboField takes a list of fields that should be used to validate a value, +in that order. +>>> f = ComboField(fields=[CharField(max_length=20), EmailField()]) +>>> f.clean('test@example.com') +u'test@example.com' +>>> f.clean('longemailaddress@example.com') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value has at most 20 characters (it has 28).'] +>>> f.clean('not an e-mail') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid e-mail address.'] +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] + +>>> f = ComboField(fields=[CharField(max_length=20), EmailField()], required=False) +>>> f.clean('test@example.com') +u'test@example.com' +>>> f.clean('longemailaddress@example.com') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value has at most 20 characters (it has 28).'] +>>> f.clean('not an e-mail') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid e-mail address.'] +>>> f.clean('') +u'' +>>> f.clean(None) +u'' + +# SplitDateTimeField ########################################################## + +>>> f = SplitDateTimeField() +>>> f.clean([datetime.date(2006, 1, 10), datetime.time(7, 30)]) +datetime.datetime(2006, 1, 10, 7, 30) +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('hello') +Traceback (most recent call last): +... +ValidationError: [u'Enter a list of values.'] +>>> f.clean(['hello', 'there']) +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid date.', u'Enter a valid time.'] +>>> f.clean(['2006-01-10', 'there']) +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid time.'] +>>> f.clean(['hello', '07:30']) +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid date.'] + +>>> f = SplitDateTimeField(required=False) +>>> f.clean([datetime.date(2006, 1, 10), datetime.time(7, 30)]) +datetime.datetime(2006, 1, 10, 7, 30) +>>> f.clean(['2006-01-10', '07:30']) +datetime.datetime(2006, 1, 10, 7, 30) +>>> f.clean(None) +>>> f.clean('') +>>> f.clean(['']) +>>> f.clean(['', '']) +>>> f.clean('hello') +Traceback (most recent call last): +... +ValidationError: [u'Enter a list of values.'] +>>> f.clean(['hello', 'there']) +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid date.', u'Enter a valid time.'] +>>> f.clean(['2006-01-10', 'there']) +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid time.'] +>>> f.clean(['hello', '07:30']) +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid date.'] +>>> f.clean(['2006-01-10', '']) +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid time.'] +>>> f.clean(['2006-01-10']) +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid time.'] +>>> f.clean(['', '07:30']) +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid date.'] +""" diff --git a/tests/regressiontests/forms/forms.py b/tests/regressiontests/forms/forms.py new file mode 100644 index 0000000000..ed88e3a6bb --- /dev/null +++ b/tests/regressiontests/forms/forms.py @@ -0,0 +1,1606 @@ +# -*- coding: utf-8 -*- +tests = r""" +>>> from django.newforms import * +>>> import datetime +>>> import time +>>> import re +>>> try: +... from decimal import Decimal +... except ImportError: +... from django.utils._decimal import Decimal + +######### +# Forms # +######### + +A Form is a collection of Fields. It knows how to validate a set of data and it +knows how to render itself in a couple of default ways (e.g., an HTML table). +You can pass it data in __init__(), as a dictionary. + +# Form ######################################################################## + +>>> class Person(Form): +... first_name = CharField() +... last_name = CharField() +... birthday = DateField() + +Pass a dictionary to a Form's __init__(). +>>> p = Person({'first_name': u'John', 'last_name': u'Lennon', 'birthday': u'1940-10-9'}) +>>> p.is_bound +True +>>> p.errors +{} +>>> p.is_valid() +True +>>> p.errors.as_ul() +u'' +>>> p.errors.as_text() +u'' +>>> p.cleaned_data +{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)} +>>> print p['first_name'] +<input type="text" name="first_name" value="John" id="id_first_name" /> +>>> print p['last_name'] +<input type="text" name="last_name" value="Lennon" id="id_last_name" /> +>>> print p['birthday'] +<input type="text" name="birthday" value="1940-10-9" id="id_birthday" /> +>>> print p['nonexistentfield'] +Traceback (most recent call last): +... +KeyError: "Key 'nonexistentfield' not found in Form" + +>>> for boundfield in p: +... print boundfield +<input type="text" name="first_name" value="John" id="id_first_name" /> +<input type="text" name="last_name" value="Lennon" id="id_last_name" /> +<input type="text" name="birthday" value="1940-10-9" id="id_birthday" /> +>>> for boundfield in p: +... print boundfield.label, boundfield.data +First name John +Last name Lennon +Birthday 1940-10-9 +>>> print p +<tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" value="John" id="id_first_name" /></td></tr> +<tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" value="Lennon" id="id_last_name" /></td></tr> +<tr><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" value="1940-10-9" id="id_birthday" /></td></tr> + +Empty dictionaries are valid, too. +>>> p = Person({}) +>>> p.is_bound +True +>>> p.errors +{'first_name': [u'This field is required.'], 'last_name': [u'This field is required.'], 'birthday': [u'This field is required.']} +>>> p.is_valid() +False +>>> p.cleaned_data +Traceback (most recent call last): +... +AttributeError: 'Person' object has no attribute 'cleaned_data' +>>> print p +<tr><th><label for="id_first_name">First name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="first_name" id="id_first_name" /></td></tr> +<tr><th><label for="id_last_name">Last name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="last_name" id="id_last_name" /></td></tr> +<tr><th><label for="id_birthday">Birthday:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="birthday" id="id_birthday" /></td></tr> +>>> print p.as_table() +<tr><th><label for="id_first_name">First name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="first_name" id="id_first_name" /></td></tr> +<tr><th><label for="id_last_name">Last name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="last_name" id="id_last_name" /></td></tr> +<tr><th><label for="id_birthday">Birthday:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="birthday" id="id_birthday" /></td></tr> +>>> print p.as_ul() +<li><ul class="errorlist"><li>This field is required.</li></ul><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></li> +<li><ul class="errorlist"><li>This field is required.</li></ul><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></li> +<li><ul class="errorlist"><li>This field is required.</li></ul><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /></li> +>>> print p.as_p() +<ul class="errorlist"><li>This field is required.</li></ul> +<p><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></p> +<ul class="errorlist"><li>This field is required.</li></ul> +<p><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></p> +<ul class="errorlist"><li>This field is required.</li></ul> +<p><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /></p> + +If you don't pass any values to the Form's __init__(), or if you pass None, +the Form will be considered unbound and won't do any validation. Form.errors +will be an empty dictionary *but* Form.is_valid() will return False. +>>> p = Person() +>>> p.is_bound +False +>>> p.errors +{} +>>> p.is_valid() +False +>>> p.cleaned_data +Traceback (most recent call last): +... +AttributeError: 'Person' object has no attribute 'cleaned_data' +>>> print p +<tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" id="id_first_name" /></td></tr> +<tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" id="id_last_name" /></td></tr> +<tr><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" id="id_birthday" /></td></tr> +>>> print p.as_table() +<tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" id="id_first_name" /></td></tr> +<tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" id="id_last_name" /></td></tr> +<tr><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" id="id_birthday" /></td></tr> +>>> print p.as_ul() +<li><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></li> +<li><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></li> +<li><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /></li> +>>> print p.as_p() +<p><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></p> +<p><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></p> +<p><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /></p> + +Unicode values are handled properly. +>>> p = Person({'first_name': u'John', 'last_name': u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111', 'birthday': '1940-10-9'}) +>>> p.as_table() +u'<tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" value="John" id="id_first_name" /></td></tr>\n<tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" id="id_last_name" /></td></tr>\n<tr><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" value="1940-10-9" id="id_birthday" /></td></tr>' +>>> p.as_ul() +u'<li><label for="id_first_name">First name:</label> <input type="text" name="first_name" value="John" id="id_first_name" /></li>\n<li><label for="id_last_name">Last name:</label> <input type="text" name="last_name" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" id="id_last_name" /></li>\n<li><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" value="1940-10-9" id="id_birthday" /></li>' +>>> p.as_p() +u'<p><label for="id_first_name">First name:</label> <input type="text" name="first_name" value="John" id="id_first_name" /></p>\n<p><label for="id_last_name">Last name:</label> <input type="text" name="last_name" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" id="id_last_name" /></p>\n<p><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" value="1940-10-9" id="id_birthday" /></p>' + +>>> p = Person({'last_name': u'Lennon'}) +>>> p.errors +{'first_name': [u'This field is required.'], 'birthday': [u'This field is required.']} +>>> p.is_valid() +False +>>> p.errors.as_ul() +u'<ul class="errorlist"><li>first_name<ul class="errorlist"><li>This field is required.</li></ul></li><li>birthday<ul class="errorlist"><li>This field is required.</li></ul></li></ul>' +>>> print p.errors.as_text() +* first_name + * This field is required. +* birthday + * This field is required. +>>> p.cleaned_data +Traceback (most recent call last): +... +AttributeError: 'Person' object has no attribute 'cleaned_data' +>>> p['first_name'].errors +[u'This field is required.'] +>>> p['first_name'].errors.as_ul() +u'<ul class="errorlist"><li>This field is required.</li></ul>' +>>> p['first_name'].errors.as_text() +u'* This field is required.' + +>>> p = Person() +>>> print p['first_name'] +<input type="text" name="first_name" id="id_first_name" /> +>>> print p['last_name'] +<input type="text" name="last_name" id="id_last_name" /> +>>> print p['birthday'] +<input type="text" name="birthday" id="id_birthday" /> + +cleaned_data will always *only* contain a key for fields defined in the +Form, even if you pass extra data when you define the Form. In this +example, we pass a bunch of extra fields to the form constructor, +but cleaned_data contains only the form's fields. +>>> data = {'first_name': u'John', 'last_name': u'Lennon', 'birthday': u'1940-10-9', 'extra1': 'hello', 'extra2': 'hello'} +>>> p = Person(data) +>>> p.is_valid() +True +>>> p.cleaned_data +{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)} + +cleaned_data will include a key and value for *all* fields defined in the Form, +even if the Form's data didn't include a value for fields that are not +required. In this example, the data dictionary doesn't include a value for the +"nick_name" field, but cleaned_data includes it. For CharFields, it's set to the +empty string. +>>> class OptionalPersonForm(Form): +... first_name = CharField() +... last_name = CharField() +... nick_name = CharField(required=False) +>>> data = {'first_name': u'John', 'last_name': u'Lennon'} +>>> f = OptionalPersonForm(data) +>>> f.is_valid() +True +>>> f.cleaned_data +{'nick_name': u'', 'first_name': u'John', 'last_name': u'Lennon'} + +For DateFields, it's set to None. +>>> class OptionalPersonForm(Form): +... first_name = CharField() +... last_name = CharField() +... birth_date = DateField(required=False) +>>> data = {'first_name': u'John', 'last_name': u'Lennon'} +>>> f = OptionalPersonForm(data) +>>> f.is_valid() +True +>>> f.cleaned_data +{'birth_date': None, 'first_name': u'John', 'last_name': u'Lennon'} + +"auto_id" tells the Form to add an "id" attribute to each form element. +If it's a string that contains '%s', Django will use that as a format string +into which the field's name will be inserted. It will also put a <label> around +the human-readable labels for a field. +>>> p = Person(auto_id='%s_id') +>>> print p.as_table() +<tr><th><label for="first_name_id">First name:</label></th><td><input type="text" name="first_name" id="first_name_id" /></td></tr> +<tr><th><label for="last_name_id">Last name:</label></th><td><input type="text" name="last_name" id="last_name_id" /></td></tr> +<tr><th><label for="birthday_id">Birthday:</label></th><td><input type="text" name="birthday" id="birthday_id" /></td></tr> +>>> print p.as_ul() +<li><label for="first_name_id">First name:</label> <input type="text" name="first_name" id="first_name_id" /></li> +<li><label for="last_name_id">Last name:</label> <input type="text" name="last_name" id="last_name_id" /></li> +<li><label for="birthday_id">Birthday:</label> <input type="text" name="birthday" id="birthday_id" /></li> +>>> print p.as_p() +<p><label for="first_name_id">First name:</label> <input type="text" name="first_name" id="first_name_id" /></p> +<p><label for="last_name_id">Last name:</label> <input type="text" name="last_name" id="last_name_id" /></p> +<p><label for="birthday_id">Birthday:</label> <input type="text" name="birthday" id="birthday_id" /></p> + +If auto_id is any True value whose str() does not contain '%s', the "id" +attribute will be the name of the field. +>>> p = Person(auto_id=True) +>>> print p.as_ul() +<li><label for="first_name">First name:</label> <input type="text" name="first_name" id="first_name" /></li> +<li><label for="last_name">Last name:</label> <input type="text" name="last_name" id="last_name" /></li> +<li><label for="birthday">Birthday:</label> <input type="text" name="birthday" id="birthday" /></li> + +If auto_id is any False value, an "id" attribute won't be output unless it +was manually entered. +>>> p = Person(auto_id=False) +>>> print p.as_ul() +<li>First name: <input type="text" name="first_name" /></li> +<li>Last name: <input type="text" name="last_name" /></li> +<li>Birthday: <input type="text" name="birthday" /></li> + +In this example, auto_id is False, but the "id" attribute for the "first_name" +field is given. Also note that field gets a <label>, while the others don't. +>>> class PersonNew(Form): +... first_name = CharField(widget=TextInput(attrs={'id': 'first_name_id'})) +... last_name = CharField() +... birthday = DateField() +>>> p = PersonNew(auto_id=False) +>>> print p.as_ul() +<li><label for="first_name_id">First name:</label> <input type="text" id="first_name_id" name="first_name" /></li> +<li>Last name: <input type="text" name="last_name" /></li> +<li>Birthday: <input type="text" name="birthday" /></li> + +If the "id" attribute is specified in the Form and auto_id is True, the "id" +attribute in the Form gets precedence. +>>> p = PersonNew(auto_id=True) +>>> print p.as_ul() +<li><label for="first_name_id">First name:</label> <input type="text" id="first_name_id" name="first_name" /></li> +<li><label for="last_name">Last name:</label> <input type="text" name="last_name" id="last_name" /></li> +<li><label for="birthday">Birthday:</label> <input type="text" name="birthday" id="birthday" /></li> + +>>> class SignupForm(Form): +... email = EmailField() +... get_spam = BooleanField() +>>> f = SignupForm(auto_id=False) +>>> print f['email'] +<input type="text" name="email" /> +>>> print f['get_spam'] +<input type="checkbox" name="get_spam" /> + +>>> f = SignupForm({'email': 'test@example.com', 'get_spam': True}, auto_id=False) +>>> print f['email'] +<input type="text" name="email" value="test@example.com" /> +>>> print f['get_spam'] +<input checked="checked" type="checkbox" name="get_spam" /> + +Any Field can have a Widget class passed to its constructor: +>>> class ContactForm(Form): +... subject = CharField() +... message = CharField(widget=Textarea) +>>> f = ContactForm(auto_id=False) +>>> print f['subject'] +<input type="text" name="subject" /> +>>> print f['message'] +<textarea rows="10" cols="40" name="message"></textarea> + +as_textarea(), as_text() and as_hidden() are shortcuts for changing the output +widget type: +>>> f['subject'].as_textarea() +u'<textarea rows="10" cols="40" name="subject"></textarea>' +>>> f['message'].as_text() +u'<input type="text" name="message" />' +>>> f['message'].as_hidden() +u'<input type="hidden" name="message" />' + +The 'widget' parameter to a Field can also be an instance: +>>> class ContactForm(Form): +... subject = CharField() +... message = CharField(widget=Textarea(attrs={'rows': 80, 'cols': 20})) +>>> f = ContactForm(auto_id=False) +>>> print f['message'] +<textarea rows="80" cols="20" name="message"></textarea> + +Instance-level attrs are *not* carried over to as_textarea(), as_text() and +as_hidden(): +>>> f['message'].as_text() +u'<input type="text" name="message" />' +>>> f = ContactForm({'subject': 'Hello', 'message': 'I love you.'}, auto_id=False) +>>> f['subject'].as_textarea() +u'<textarea rows="10" cols="40" name="subject">Hello</textarea>' +>>> f['message'].as_text() +u'<input type="text" name="message" value="I love you." />' +>>> f['message'].as_hidden() +u'<input type="hidden" name="message" value="I love you." />' + +For a form with a <select>, use ChoiceField: +>>> class FrameworkForm(Form): +... name = CharField() +... language = ChoiceField(choices=[('P', 'Python'), ('J', 'Java')]) +>>> f = FrameworkForm(auto_id=False) +>>> print f['language'] +<select name="language"> +<option value="P">Python</option> +<option value="J">Java</option> +</select> +>>> f = FrameworkForm({'name': 'Django', 'language': 'P'}, auto_id=False) +>>> print f['language'] +<select name="language"> +<option value="P" selected="selected">Python</option> +<option value="J">Java</option> +</select> + +A subtlety: If one of the choices' value is the empty string and the form is +unbound, then the <option> for the empty-string choice will get selected="selected". +>>> class FrameworkForm(Form): +... name = CharField() +... language = ChoiceField(choices=[('', '------'), ('P', 'Python'), ('J', 'Java')]) +>>> f = FrameworkForm(auto_id=False) +>>> print f['language'] +<select name="language"> +<option value="" selected="selected">------</option> +<option value="P">Python</option> +<option value="J">Java</option> +</select> + +You can specify widget attributes in the Widget constructor. +>>> class FrameworkForm(Form): +... name = CharField() +... language = ChoiceField(choices=[('P', 'Python'), ('J', 'Java')], widget=Select(attrs={'class': 'foo'})) +>>> f = FrameworkForm(auto_id=False) +>>> print f['language'] +<select class="foo" name="language"> +<option value="P">Python</option> +<option value="J">Java</option> +</select> +>>> f = FrameworkForm({'name': 'Django', 'language': 'P'}, auto_id=False) +>>> print f['language'] +<select class="foo" name="language"> +<option value="P" selected="selected">Python</option> +<option value="J">Java</option> +</select> + +When passing a custom widget instance to ChoiceField, note that setting +'choices' on the widget is meaningless. The widget will use the choices +defined on the Field, not the ones defined on the Widget. +>>> class FrameworkForm(Form): +... name = CharField() +... language = ChoiceField(choices=[('P', 'Python'), ('J', 'Java')], widget=Select(choices=[('R', 'Ruby'), ('P', 'Perl')], attrs={'class': 'foo'})) +>>> f = FrameworkForm(auto_id=False) +>>> print f['language'] +<select class="foo" name="language"> +<option value="P">Python</option> +<option value="J">Java</option> +</select> +>>> f = FrameworkForm({'name': 'Django', 'language': 'P'}, auto_id=False) +>>> print f['language'] +<select class="foo" name="language"> +<option value="P" selected="selected">Python</option> +<option value="J">Java</option> +</select> + +You can set a ChoiceField's choices after the fact. +>>> class FrameworkForm(Form): +... name = CharField() +... language = ChoiceField() +>>> f = FrameworkForm(auto_id=False) +>>> print f['language'] +<select name="language"> +</select> +>>> f.fields['language'].choices = [('P', 'Python'), ('J', 'Java')] +>>> print f['language'] +<select name="language"> +<option value="P">Python</option> +<option value="J">Java</option> +</select> + +Add widget=RadioSelect to use that widget with a ChoiceField. +>>> class FrameworkForm(Form): +... name = CharField() +... language = ChoiceField(choices=[('P', 'Python'), ('J', 'Java')], widget=RadioSelect) +>>> f = FrameworkForm(auto_id=False) +>>> print f['language'] +<ul> +<li><label><input type="radio" name="language" value="P" /> Python</label></li> +<li><label><input type="radio" name="language" value="J" /> Java</label></li> +</ul> +>>> print f +<tr><th>Name:</th><td><input type="text" name="name" /></td></tr> +<tr><th>Language:</th><td><ul> +<li><label><input type="radio" name="language" value="P" /> Python</label></li> +<li><label><input type="radio" name="language" value="J" /> Java</label></li> +</ul></td></tr> +>>> print f.as_ul() +<li>Name: <input type="text" name="name" /></li> +<li>Language: <ul> +<li><label><input type="radio" name="language" value="P" /> Python</label></li> +<li><label><input type="radio" name="language" value="J" /> Java</label></li> +</ul></li> + +Regarding auto_id and <label>, RadioSelect is a special case. Each radio button +gets a distinct ID, formed by appending an underscore plus the button's +zero-based index. +>>> f = FrameworkForm(auto_id='id_%s') +>>> print f['language'] +<ul> +<li><label><input type="radio" id="id_language_0" value="P" name="language" /> Python</label></li> +<li><label><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li> +</ul> + +When RadioSelect is used with auto_id, and the whole form is printed using +either as_table() or as_ul(), the label for the RadioSelect will point to the +ID of the *first* radio button. +>>> print f +<tr><th><label for="id_name">Name:</label></th><td><input type="text" name="name" id="id_name" /></td></tr> +<tr><th><label for="id_language_0">Language:</label></th><td><ul> +<li><label><input type="radio" id="id_language_0" value="P" name="language" /> Python</label></li> +<li><label><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li> +</ul></td></tr> +>>> print f.as_ul() +<li><label for="id_name">Name:</label> <input type="text" name="name" id="id_name" /></li> +<li><label for="id_language_0">Language:</label> <ul> +<li><label><input type="radio" id="id_language_0" value="P" name="language" /> Python</label></li> +<li><label><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li> +</ul></li> +>>> print f.as_p() +<p><label for="id_name">Name:</label> <input type="text" name="name" id="id_name" /></p> +<p><label for="id_language_0">Language:</label> <ul> +<li><label><input type="radio" id="id_language_0" value="P" name="language" /> Python</label></li> +<li><label><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li> +</ul></p> + +MultipleChoiceField is a special case, as its data is required to be a list: +>>> class SongForm(Form): +... name = CharField() +... composers = MultipleChoiceField() +>>> f = SongForm(auto_id=False) +>>> print f['composers'] +<select multiple="multiple" name="composers"> +</select> +>>> class SongForm(Form): +... name = CharField() +... composers = MultipleChoiceField(choices=[('J', 'John Lennon'), ('P', 'Paul McCartney')]) +>>> f = SongForm(auto_id=False) +>>> print f['composers'] +<select multiple="multiple" name="composers"> +<option value="J">John Lennon</option> +<option value="P">Paul McCartney</option> +</select> +>>> f = SongForm({'name': 'Yesterday', 'composers': ['P']}, auto_id=False) +>>> print f['name'] +<input type="text" name="name" value="Yesterday" /> +>>> print f['composers'] +<select multiple="multiple" name="composers"> +<option value="J">John Lennon</option> +<option value="P" selected="selected">Paul McCartney</option> +</select> + +MultipleChoiceField rendered as_hidden() is a special case. Because it can +have multiple values, its as_hidden() renders multiple <input type="hidden"> +tags. +>>> f = SongForm({'name': 'Yesterday', 'composers': ['P']}, auto_id=False) +>>> print f['composers'].as_hidden() +<input type="hidden" name="composers" value="P" /> +>>> f = SongForm({'name': 'From Me To You', 'composers': ['P', 'J']}, auto_id=False) +>>> print f['composers'].as_hidden() +<input type="hidden" name="composers" value="P" /> +<input type="hidden" name="composers" value="J" /> + +MultipleChoiceField can also be used with the CheckboxSelectMultiple widget. +>>> class SongForm(Form): +... name = CharField() +... composers = MultipleChoiceField(choices=[('J', 'John Lennon'), ('P', 'Paul McCartney')], widget=CheckboxSelectMultiple) +>>> f = SongForm(auto_id=False) +>>> print f['composers'] +<ul> +<li><label><input type="checkbox" name="composers" value="J" /> John Lennon</label></li> +<li><label><input type="checkbox" name="composers" value="P" /> Paul McCartney</label></li> +</ul> +>>> f = SongForm({'composers': ['J']}, auto_id=False) +>>> print f['composers'] +<ul> +<li><label><input checked="checked" type="checkbox" name="composers" value="J" /> John Lennon</label></li> +<li><label><input type="checkbox" name="composers" value="P" /> Paul McCartney</label></li> +</ul> +>>> f = SongForm({'composers': ['J', 'P']}, auto_id=False) +>>> print f['composers'] +<ul> +<li><label><input checked="checked" type="checkbox" name="composers" value="J" /> John Lennon</label></li> +<li><label><input checked="checked" type="checkbox" name="composers" value="P" /> Paul McCartney</label></li> +</ul> + +Regarding auto_id, CheckboxSelectMultiple is a special case. Each checkbox +gets a distinct ID, formed by appending an underscore plus the checkbox's +zero-based index. +>>> f = SongForm(auto_id='%s_id') +>>> print f['composers'] +<ul> +<li><label><input type="checkbox" name="composers" value="J" id="composers_id_0" /> John Lennon</label></li> +<li><label><input type="checkbox" name="composers" value="P" id="composers_id_1" /> Paul McCartney</label></li> +</ul> + +Data for a MultipleChoiceField should be a list. QueryDict and MultiValueDict +conveniently work with this. +>>> data = {'name': 'Yesterday', 'composers': ['J', 'P']} +>>> f = SongForm(data) +>>> f.errors +{} +>>> from django.http import QueryDict +>>> data = QueryDict('name=Yesterday&composers=J&composers=P') +>>> f = SongForm(data) +>>> f.errors +{} +>>> from django.utils.datastructures import MultiValueDict +>>> data = MultiValueDict(dict(name=['Yesterday'], composers=['J', 'P'])) +>>> f = SongForm(data) +>>> f.errors +{} + +The MultipleHiddenInput widget renders multiple values as hidden fields. +>>> class SongFormHidden(Form): +... name = CharField() +... composers = MultipleChoiceField(choices=[('J', 'John Lennon'), ('P', 'Paul McCartney')], widget=MultipleHiddenInput) +>>> f = SongFormHidden(MultiValueDict(dict(name=['Yesterday'], composers=['J', 'P'])), auto_id=False) +>>> print f.as_ul() +<li>Name: <input type="text" name="name" value="Yesterday" /><input type="hidden" name="composers" value="J" /> +<input type="hidden" name="composers" value="P" /></li> + +When using CheckboxSelectMultiple, the framework expects a list of input and +returns a list of input. +>>> f = SongForm({'name': 'Yesterday'}, auto_id=False) +>>> f.errors +{'composers': [u'This field is required.']} +>>> f = SongForm({'name': 'Yesterday', 'composers': ['J']}, auto_id=False) +>>> f.errors +{} +>>> f.cleaned_data +{'composers': [u'J'], 'name': u'Yesterday'} +>>> f = SongForm({'name': 'Yesterday', 'composers': ['J', 'P']}, auto_id=False) +>>> f.errors +{} +>>> f.cleaned_data +{'composers': [u'J', u'P'], 'name': u'Yesterday'} + +Validation errors are HTML-escaped when output as HTML. +>>> class EscapingForm(Form): +... special_name = CharField() +... def clean_special_name(self): +... raise ValidationError("Something's wrong with '%s'" % self.cleaned_data['special_name']) + +>>> f = EscapingForm({'special_name': "Nothing to escape"}, auto_id=False) +>>> print f +<tr><th>Special name:</th><td><ul class="errorlist"><li>Something's wrong with 'Nothing to escape'</li></ul><input type="text" name="special_name" value="Nothing to escape" /></td></tr> +>>> f = EscapingForm({'special_name': "Should escape < & > and <script>alert('xss')</script>"}, auto_id=False) +>>> print f +<tr><th>Special name:</th><td><ul class="errorlist"><li>Something's wrong with 'Should escape < & > and <script>alert('xss')</script>'</li></ul><input type="text" name="special_name" value="Should escape < & > and <script>alert('xss')</script>" /></td></tr> + +""" + \ +r""" # [This concatenation is to keep the string below the jython's 32K limit]. +# Validating multiple fields in relation to another ########################### + +There are a couple of ways to do multiple-field validation. If you want the +validation message to be associated with a particular field, implement the +clean_XXX() method on the Form, where XXX is the field name. As in +Field.clean(), the clean_XXX() method should return the cleaned value. In the +clean_XXX() method, you have access to self.cleaned_data, which is a dictionary +of all the data that has been cleaned *so far*, in order by the fields, +including the current field (e.g., the field XXX if you're in clean_XXX()). +>>> class UserRegistration(Form): +... username = CharField(max_length=10) +... password1 = CharField(widget=PasswordInput) +... password2 = CharField(widget=PasswordInput) +... def clean_password2(self): +... if self.cleaned_data.get('password1') and self.cleaned_data.get('password2') and self.cleaned_data['password1'] != self.cleaned_data['password2']: +... raise ValidationError(u'Please make sure your passwords match.') +... return self.cleaned_data['password2'] +>>> f = UserRegistration(auto_id=False) +>>> f.errors +{} +>>> f = UserRegistration({}, auto_id=False) +>>> f.errors +{'username': [u'This field is required.'], 'password1': [u'This field is required.'], 'password2': [u'This field is required.']} +>>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'bar'}, auto_id=False) +>>> f.errors +{'password2': [u'Please make sure your passwords match.']} +>>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'foo'}, auto_id=False) +>>> f.errors +{} +>>> f.cleaned_data +{'username': u'adrian', 'password1': u'foo', 'password2': u'foo'} + +Another way of doing multiple-field validation is by implementing the +Form's clean() method. If you do this, any ValidationError raised by that +method will not be associated with a particular field; it will have a +special-case association with the field named '__all__'. +Note that in Form.clean(), you have access to self.cleaned_data, a dictionary of +all the fields/values that have *not* raised a ValidationError. Also note +Form.clean() is required to return a dictionary of all clean data. +>>> class UserRegistration(Form): +... username = CharField(max_length=10) +... password1 = CharField(widget=PasswordInput) +... password2 = CharField(widget=PasswordInput) +... def clean(self): +... if self.cleaned_data.get('password1') and self.cleaned_data.get('password2') and self.cleaned_data['password1'] != self.cleaned_data['password2']: +... raise ValidationError(u'Please make sure your passwords match.') +... return self.cleaned_data +>>> f = UserRegistration(auto_id=False) +>>> f.errors +{} +>>> f = UserRegistration({}, auto_id=False) +>>> print f.as_table() +<tr><th>Username:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="username" maxlength="10" /></td></tr> +<tr><th>Password1:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="password" name="password1" /></td></tr> +<tr><th>Password2:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="password" name="password2" /></td></tr> +>>> f.errors +{'username': [u'This field is required.'], 'password1': [u'This field is required.'], 'password2': [u'This field is required.']} +>>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'bar'}, auto_id=False) +>>> f.errors +{'__all__': [u'Please make sure your passwords match.']} +>>> print f.as_table() +<tr><td colspan="2"><ul class="errorlist"><li>Please make sure your passwords match.</li></ul></td></tr> +<tr><th>Username:</th><td><input type="text" name="username" value="adrian" maxlength="10" /></td></tr> +<tr><th>Password1:</th><td><input type="password" name="password1" value="foo" /></td></tr> +<tr><th>Password2:</th><td><input type="password" name="password2" value="bar" /></td></tr> +>>> print f.as_ul() +<li><ul class="errorlist"><li>Please make sure your passwords match.</li></ul></li> +<li>Username: <input type="text" name="username" value="adrian" maxlength="10" /></li> +<li>Password1: <input type="password" name="password1" value="foo" /></li> +<li>Password2: <input type="password" name="password2" value="bar" /></li> +>>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'foo'}, auto_id=False) +>>> f.errors +{} +>>> f.cleaned_data +{'username': u'adrian', 'password1': u'foo', 'password2': u'foo'} + +# Dynamic construction ######################################################## + +It's possible to construct a Form dynamically by adding to the self.fields +dictionary in __init__(). Don't forget to call Form.__init__() within the +subclass' __init__(). +>>> class Person(Form): +... first_name = CharField() +... last_name = CharField() +... def __init__(self, *args, **kwargs): +... super(Person, self).__init__(*args, **kwargs) +... self.fields['birthday'] = DateField() +>>> p = Person(auto_id=False) +>>> print p +<tr><th>First name:</th><td><input type="text" name="first_name" /></td></tr> +<tr><th>Last name:</th><td><input type="text" name="last_name" /></td></tr> +<tr><th>Birthday:</th><td><input type="text" name="birthday" /></td></tr> + +Instances of a dynamic Form do not persist fields from one Form instance to +the next. +>>> class MyForm(Form): +... def __init__(self, data=None, auto_id=False, field_list=[]): +... Form.__init__(self, data, auto_id=auto_id) +... for field in field_list: +... self.fields[field[0]] = field[1] +>>> field_list = [('field1', CharField()), ('field2', CharField())] +>>> my_form = MyForm(field_list=field_list) +>>> print my_form +<tr><th>Field1:</th><td><input type="text" name="field1" /></td></tr> +<tr><th>Field2:</th><td><input type="text" name="field2" /></td></tr> +>>> field_list = [('field3', CharField()), ('field4', CharField())] +>>> my_form = MyForm(field_list=field_list) +>>> print my_form +<tr><th>Field3:</th><td><input type="text" name="field3" /></td></tr> +<tr><th>Field4:</th><td><input type="text" name="field4" /></td></tr> + +>>> class MyForm(Form): +... default_field_1 = CharField() +... default_field_2 = CharField() +... def __init__(self, data=None, auto_id=False, field_list=[]): +... Form.__init__(self, data, auto_id=auto_id) +... for field in field_list: +... self.fields[field[0]] = field[1] +>>> field_list = [('field1', CharField()), ('field2', CharField())] +>>> my_form = MyForm(field_list=field_list) +>>> print my_form +<tr><th>Default field 1:</th><td><input type="text" name="default_field_1" /></td></tr> +<tr><th>Default field 2:</th><td><input type="text" name="default_field_2" /></td></tr> +<tr><th>Field1:</th><td><input type="text" name="field1" /></td></tr> +<tr><th>Field2:</th><td><input type="text" name="field2" /></td></tr> +>>> field_list = [('field3', CharField()), ('field4', CharField())] +>>> my_form = MyForm(field_list=field_list) +>>> print my_form +<tr><th>Default field 1:</th><td><input type="text" name="default_field_1" /></td></tr> +<tr><th>Default field 2:</th><td><input type="text" name="default_field_2" /></td></tr> +<tr><th>Field3:</th><td><input type="text" name="field3" /></td></tr> +<tr><th>Field4:</th><td><input type="text" name="field4" /></td></tr> + +Similarly, changes to field attributes do not persist from one Form instance +to the next. +>>> class Person(Form): +... first_name = CharField(required=False) +... last_name = CharField(required=False) +... def __init__(self, names_required=False, *args, **kwargs): +... super(Person, self).__init__(*args, **kwargs) +... if names_required: +... self.fields['first_name'].required = True +... self.fields['first_name'].widget.attrs['class'] = 'required' +... self.fields['last_name'].required = True +... self.fields['last_name'].widget.attrs['class'] = 'required' +>>> f = Person(names_required=False) +>>> f['first_name'].field.required, f['last_name'].field.required +(False, False) +>>> f['first_name'].field.widget.attrs, f['last_name'].field.widget.attrs +({}, {}) +>>> f = Person(names_required=True) +>>> f['first_name'].field.required, f['last_name'].field.required +(True, True) +>>> f['first_name'].field.widget.attrs, f['last_name'].field.widget.attrs +({'class': 'required'}, {'class': 'required'}) +>>> f = Person(names_required=False) +>>> f['first_name'].field.required, f['last_name'].field.required +(False, False) +>>> f['first_name'].field.widget.attrs, f['last_name'].field.widget.attrs +({}, {}) +>>> class Person(Form): +... first_name = CharField(max_length=30) +... last_name = CharField(max_length=30) +... def __init__(self, name_max_length=None, *args, **kwargs): +... super(Person, self).__init__(*args, **kwargs) +... if name_max_length: +... self.fields['first_name'].max_length = name_max_length +... self.fields['last_name'].max_length = name_max_length +>>> f = Person(name_max_length=None) +>>> f['first_name'].field.max_length, f['last_name'].field.max_length +(30, 30) +>>> f = Person(name_max_length=20) +>>> f['first_name'].field.max_length, f['last_name'].field.max_length +(20, 20) +>>> f = Person(name_max_length=None) +>>> f['first_name'].field.max_length, f['last_name'].field.max_length +(30, 30) + +HiddenInput widgets are displayed differently in the as_table(), as_ul() +and as_p() output of a Form -- their verbose names are not displayed, and a +separate row is not displayed. They're displayed in the last row of the +form, directly after that row's form element. +>>> class Person(Form): +... first_name = CharField() +... last_name = CharField() +... hidden_text = CharField(widget=HiddenInput) +... birthday = DateField() +>>> p = Person(auto_id=False) +>>> print p +<tr><th>First name:</th><td><input type="text" name="first_name" /></td></tr> +<tr><th>Last name:</th><td><input type="text" name="last_name" /></td></tr> +<tr><th>Birthday:</th><td><input type="text" name="birthday" /><input type="hidden" name="hidden_text" /></td></tr> +>>> print p.as_ul() +<li>First name: <input type="text" name="first_name" /></li> +<li>Last name: <input type="text" name="last_name" /></li> +<li>Birthday: <input type="text" name="birthday" /><input type="hidden" name="hidden_text" /></li> +>>> print p.as_p() +<p>First name: <input type="text" name="first_name" /></p> +<p>Last name: <input type="text" name="last_name" /></p> +<p>Birthday: <input type="text" name="birthday" /><input type="hidden" name="hidden_text" /></p> + +With auto_id set, a HiddenInput still gets an ID, but it doesn't get a label. +>>> p = Person(auto_id='id_%s') +>>> print p +<tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" id="id_first_name" /></td></tr> +<tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" id="id_last_name" /></td></tr> +<tr><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" id="id_birthday" /><input type="hidden" name="hidden_text" id="id_hidden_text" /></td></tr> +>>> print p.as_ul() +<li><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></li> +<li><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></li> +<li><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /><input type="hidden" name="hidden_text" id="id_hidden_text" /></li> +>>> print p.as_p() +<p><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></p> +<p><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></p> +<p><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /><input type="hidden" name="hidden_text" id="id_hidden_text" /></p> + +If a field with a HiddenInput has errors, the as_table() and as_ul() output +will include the error message(s) with the text "(Hidden field [fieldname]) " +prepended. This message is displayed at the top of the output, regardless of +its field's order in the form. +>>> p = Person({'first_name': 'John', 'last_name': 'Lennon', 'birthday': '1940-10-9'}, auto_id=False) +>>> print p +<tr><td colspan="2"><ul class="errorlist"><li>(Hidden field hidden_text) This field is required.</li></ul></td></tr> +<tr><th>First name:</th><td><input type="text" name="first_name" value="John" /></td></tr> +<tr><th>Last name:</th><td><input type="text" name="last_name" value="Lennon" /></td></tr> +<tr><th>Birthday:</th><td><input type="text" name="birthday" value="1940-10-9" /><input type="hidden" name="hidden_text" /></td></tr> +>>> print p.as_ul() +<li><ul class="errorlist"><li>(Hidden field hidden_text) This field is required.</li></ul></li> +<li>First name: <input type="text" name="first_name" value="John" /></li> +<li>Last name: <input type="text" name="last_name" value="Lennon" /></li> +<li>Birthday: <input type="text" name="birthday" value="1940-10-9" /><input type="hidden" name="hidden_text" /></li> +>>> print p.as_p() +<ul class="errorlist"><li>(Hidden field hidden_text) This field is required.</li></ul> +<p>First name: <input type="text" name="first_name" value="John" /></p> +<p>Last name: <input type="text" name="last_name" value="Lennon" /></p> +<p>Birthday: <input type="text" name="birthday" value="1940-10-9" /><input type="hidden" name="hidden_text" /></p> + +A corner case: It's possible for a form to have only HiddenInputs. +>>> class TestForm(Form): +... foo = CharField(widget=HiddenInput) +... bar = CharField(widget=HiddenInput) +>>> p = TestForm(auto_id=False) +>>> print p.as_table() +<input type="hidden" name="foo" /><input type="hidden" name="bar" /> +>>> print p.as_ul() +<input type="hidden" name="foo" /><input type="hidden" name="bar" /> +>>> print p.as_p() +<input type="hidden" name="foo" /><input type="hidden" name="bar" /> + +A Form's fields are displayed in the same order in which they were defined. +>>> class TestForm(Form): +... field1 = CharField() +... field2 = CharField() +... field3 = CharField() +... field4 = CharField() +... field5 = CharField() +... field6 = CharField() +... field7 = CharField() +... field8 = CharField() +... field9 = CharField() +... field10 = CharField() +... field11 = CharField() +... field12 = CharField() +... field13 = CharField() +... field14 = CharField() +>>> p = TestForm(auto_id=False) +>>> print p +<tr><th>Field1:</th><td><input type="text" name="field1" /></td></tr> +<tr><th>Field2:</th><td><input type="text" name="field2" /></td></tr> +<tr><th>Field3:</th><td><input type="text" name="field3" /></td></tr> +<tr><th>Field4:</th><td><input type="text" name="field4" /></td></tr> +<tr><th>Field5:</th><td><input type="text" name="field5" /></td></tr> +<tr><th>Field6:</th><td><input type="text" name="field6" /></td></tr> +<tr><th>Field7:</th><td><input type="text" name="field7" /></td></tr> +<tr><th>Field8:</th><td><input type="text" name="field8" /></td></tr> +<tr><th>Field9:</th><td><input type="text" name="field9" /></td></tr> +<tr><th>Field10:</th><td><input type="text" name="field10" /></td></tr> +<tr><th>Field11:</th><td><input type="text" name="field11" /></td></tr> +<tr><th>Field12:</th><td><input type="text" name="field12" /></td></tr> +<tr><th>Field13:</th><td><input type="text" name="field13" /></td></tr> +<tr><th>Field14:</th><td><input type="text" name="field14" /></td></tr> + +Some Field classes have an effect on the HTML attributes of their associated +Widget. If you set max_length in a CharField and its associated widget is +either a TextInput or PasswordInput, then the widget's rendered HTML will +include the "maxlength" attribute. +>>> class UserRegistration(Form): +... username = CharField(max_length=10) # uses TextInput by default +... password = CharField(max_length=10, widget=PasswordInput) +... realname = CharField(max_length=10, widget=TextInput) # redundantly define widget, just to test +... address = CharField() # no max_length defined here +>>> p = UserRegistration(auto_id=False) +>>> print p.as_ul() +<li>Username: <input type="text" name="username" maxlength="10" /></li> +<li>Password: <input type="password" name="password" maxlength="10" /></li> +<li>Realname: <input type="text" name="realname" maxlength="10" /></li> +<li>Address: <input type="text" name="address" /></li> + +If you specify a custom "attrs" that includes the "maxlength" attribute, +the Field's max_length attribute will override whatever "maxlength" you specify +in "attrs". +>>> class UserRegistration(Form): +... username = CharField(max_length=10, widget=TextInput(attrs={'maxlength': 20})) +... password = CharField(max_length=10, widget=PasswordInput) +>>> p = UserRegistration(auto_id=False) +>>> print p.as_ul() +<li>Username: <input type="text" name="username" maxlength="10" /></li> +<li>Password: <input type="password" name="password" maxlength="10" /></li> + +# Specifying labels ########################################################### + +You can specify the label for a field by using the 'label' argument to a Field +class. If you don't specify 'label', Django will use the field name with +underscores converted to spaces, and the initial letter capitalized. +>>> class UserRegistration(Form): +... username = CharField(max_length=10, label='Your username') +... password1 = CharField(widget=PasswordInput) +... password2 = CharField(widget=PasswordInput, label='Password (again)') +>>> p = UserRegistration(auto_id=False) +>>> print p.as_ul() +<li>Your username: <input type="text" name="username" maxlength="10" /></li> +<li>Password1: <input type="password" name="password1" /></li> +<li>Password (again): <input type="password" name="password2" /></li> + +Labels for as_* methods will only end in a colon if they don't end in other +punctuation already. +>>> class Questions(Form): +... q1 = CharField(label='The first question') +... q2 = CharField(label='What is your name?') +... q3 = CharField(label='The answer to life is:') +... q4 = CharField(label='Answer this question!') +... q5 = CharField(label='The last question. Period.') +>>> print Questions(auto_id=False).as_p() +<p>The first question: <input type="text" name="q1" /></p> +<p>What is your name? <input type="text" name="q2" /></p> +<p>The answer to life is: <input type="text" name="q3" /></p> +<p>Answer this question! <input type="text" name="q4" /></p> +<p>The last question. Period. <input type="text" name="q5" /></p> +>>> print Questions().as_p() +<p><label for="id_q1">The first question:</label> <input type="text" name="q1" id="id_q1" /></p> +<p><label for="id_q2">What is your name?</label> <input type="text" name="q2" id="id_q2" /></p> +<p><label for="id_q3">The answer to life is:</label> <input type="text" name="q3" id="id_q3" /></p> +<p><label for="id_q4">Answer this question!</label> <input type="text" name="q4" id="id_q4" /></p> +<p><label for="id_q5">The last question. Period.</label> <input type="text" name="q5" id="id_q5" /></p> + +A label can be a Unicode object or a bytestring with special characters. +>>> class UserRegistration(Form): +... username = CharField(max_length=10, label='ŠĐĆŽćžšđ') +... password = CharField(widget=PasswordInput, label=u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111') +>>> p = UserRegistration(auto_id=False) +>>> p.as_ul() +u'<li>\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111: <input type="text" name="username" maxlength="10" /></li>\n<li>\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111: <input type="password" name="password" /></li>' + +If a label is set to the empty string for a field, that field won't get a label. +>>> class UserRegistration(Form): +... username = CharField(max_length=10, label='') +... password = CharField(widget=PasswordInput) +>>> p = UserRegistration(auto_id=False) +>>> print p.as_ul() +<li> <input type="text" name="username" maxlength="10" /></li> +<li>Password: <input type="password" name="password" /></li> +>>> p = UserRegistration(auto_id='id_%s') +>>> print p.as_ul() +<li> <input id="id_username" type="text" name="username" maxlength="10" /></li> +<li><label for="id_password">Password:</label> <input type="password" name="password" id="id_password" /></li> + +If label is None, Django will auto-create the label from the field name. This +is default behavior. +>>> class UserRegistration(Form): +... username = CharField(max_length=10, label=None) +... password = CharField(widget=PasswordInput) +>>> p = UserRegistration(auto_id=False) +>>> print p.as_ul() +<li>Username: <input type="text" name="username" maxlength="10" /></li> +<li>Password: <input type="password" name="password" /></li> +>>> p = UserRegistration(auto_id='id_%s') +>>> print p.as_ul() +<li><label for="id_username">Username:</label> <input id="id_username" type="text" name="username" maxlength="10" /></li> +<li><label for="id_password">Password:</label> <input type="password" name="password" id="id_password" /></li> + + +# Label Suffix ################################################################ + +You can specify the 'label_suffix' argument to a Form class to modify the +punctuation symbol used at the end of a label. By default, the colon (:) is +used, and is only appended to the label if the label doesn't already end with a +punctuation symbol: ., !, ? or :. If you specify a different suffix, it will +be appended regardless of the last character of the label. + +>>> class FavoriteForm(Form): +... color = CharField(label='Favorite color?') +... animal = CharField(label='Favorite animal') +... +>>> f = FavoriteForm(auto_id=False) +>>> print f.as_ul() +<li>Favorite color? <input type="text" name="color" /></li> +<li>Favorite animal: <input type="text" name="animal" /></li> +>>> f = FavoriteForm(auto_id=False, label_suffix='?') +>>> print f.as_ul() +<li>Favorite color? <input type="text" name="color" /></li> +<li>Favorite animal? <input type="text" name="animal" /></li> +>>> f = FavoriteForm(auto_id=False, label_suffix='') +>>> print f.as_ul() +<li>Favorite color? <input type="text" name="color" /></li> +<li>Favorite animal <input type="text" name="animal" /></li> +>>> f = FavoriteForm(auto_id=False, label_suffix=u'\u2192') +>>> f.as_ul() +u'<li>Favorite color? <input type="text" name="color" /></li>\n<li>Favorite animal\u2192 <input type="text" name="animal" /></li>' + +""" + \ +r""" # [This concatenation is to keep the string below the jython's 32K limit]. + +# Initial data ################################################################ + +You can specify initial data for a field by using the 'initial' argument to a +Field class. This initial data is displayed when a Form is rendered with *no* +data. It is not displayed when a Form is rendered with any data (including an +empty dictionary). Also, the initial value is *not* used if data for a +particular required field isn't provided. +>>> class UserRegistration(Form): +... username = CharField(max_length=10, initial='django') +... password = CharField(widget=PasswordInput) + +Here, we're not submitting any data, so the initial value will be displayed. +>>> p = UserRegistration(auto_id=False) +>>> print p.as_ul() +<li>Username: <input type="text" name="username" value="django" maxlength="10" /></li> +<li>Password: <input type="password" name="password" /></li> + +Here, we're submitting data, so the initial value will *not* be displayed. +>>> p = UserRegistration({}, auto_id=False) +>>> print p.as_ul() +<li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li> +<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li> +>>> p = UserRegistration({'username': u''}, auto_id=False) +>>> print p.as_ul() +<li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li> +<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li> +>>> p = UserRegistration({'username': u'foo'}, auto_id=False) +>>> print p.as_ul() +<li>Username: <input type="text" name="username" value="foo" maxlength="10" /></li> +<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li> + +An 'initial' value is *not* used as a fallback if data is not provided. In this +example, we don't provide a value for 'username', and the form raises a +validation error rather than using the initial value for 'username'. +>>> p = UserRegistration({'password': 'secret'}) +>>> p.errors +{'username': [u'This field is required.']} +>>> p.is_valid() +False + +# Dynamic initial data ######################################################## + +The previous technique dealt with "hard-coded" initial data, but it's also +possible to specify initial data after you've already created the Form class +(i.e., at runtime). Use the 'initial' parameter to the Form constructor. This +should be a dictionary containing initial values for one or more fields in the +form, keyed by field name. + +>>> class UserRegistration(Form): +... username = CharField(max_length=10) +... password = CharField(widget=PasswordInput) + +Here, we're not submitting any data, so the initial value will be displayed. +>>> p = UserRegistration(initial={'username': 'django'}, auto_id=False) +>>> print p.as_ul() +<li>Username: <input type="text" name="username" value="django" maxlength="10" /></li> +<li>Password: <input type="password" name="password" /></li> +>>> p = UserRegistration(initial={'username': 'stephane'}, auto_id=False) +>>> print p.as_ul() +<li>Username: <input type="text" name="username" value="stephane" maxlength="10" /></li> +<li>Password: <input type="password" name="password" /></li> + +The 'initial' parameter is meaningless if you pass data. +>>> p = UserRegistration({}, initial={'username': 'django'}, auto_id=False) +>>> print p.as_ul() +<li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li> +<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li> +>>> p = UserRegistration({'username': u''}, initial={'username': 'django'}, auto_id=False) +>>> print p.as_ul() +<li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li> +<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li> +>>> p = UserRegistration({'username': u'foo'}, initial={'username': 'django'}, auto_id=False) +>>> print p.as_ul() +<li>Username: <input type="text" name="username" value="foo" maxlength="10" /></li> +<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li> + +A dynamic 'initial' value is *not* used as a fallback if data is not provided. +In this example, we don't provide a value for 'username', and the form raises a +validation error rather than using the initial value for 'username'. +>>> p = UserRegistration({'password': 'secret'}, initial={'username': 'django'}) +>>> p.errors +{'username': [u'This field is required.']} +>>> p.is_valid() +False + +If a Form defines 'initial' *and* 'initial' is passed as a parameter to Form(), +then the latter will get precedence. +>>> class UserRegistration(Form): +... username = CharField(max_length=10, initial='django') +... password = CharField(widget=PasswordInput) +>>> p = UserRegistration(initial={'username': 'babik'}, auto_id=False) +>>> print p.as_ul() +<li>Username: <input type="text" name="username" value="babik" maxlength="10" /></li> +<li>Password: <input type="password" name="password" /></li> + +# Callable initial data ######################################################## + +The previous technique dealt with raw values as initial data, but it's also +possible to specify callable data. + +>>> class UserRegistration(Form): +... username = CharField(max_length=10) +... password = CharField(widget=PasswordInput) + +We need to define functions that get called later. +>>> def initial_django(): +... return 'django' +>>> def initial_stephane(): +... return 'stephane' + +Here, we're not submitting any data, so the initial value will be displayed. +>>> p = UserRegistration(initial={'username': initial_django}, auto_id=False) +>>> print p.as_ul() +<li>Username: <input type="text" name="username" value="django" maxlength="10" /></li> +<li>Password: <input type="password" name="password" /></li> + +The 'initial' parameter is meaningless if you pass data. +>>> p = UserRegistration({}, initial={'username': initial_django}, auto_id=False) +>>> print p.as_ul() +<li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li> +<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li> +>>> p = UserRegistration({'username': u''}, initial={'username': initial_django}, auto_id=False) +>>> print p.as_ul() +<li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li> +<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li> +>>> p = UserRegistration({'username': u'foo'}, initial={'username': initial_django}, auto_id=False) +>>> print p.as_ul() +<li>Username: <input type="text" name="username" value="foo" maxlength="10" /></li> +<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li> + +A callable 'initial' value is *not* used as a fallback if data is not provided. +In this example, we don't provide a value for 'username', and the form raises a +validation error rather than using the initial value for 'username'. +>>> p = UserRegistration({'password': 'secret'}, initial={'username': initial_django}) +>>> p.errors +{'username': [u'This field is required.']} +>>> p.is_valid() +False + +If a Form defines 'initial' *and* 'initial' is passed as a parameter to Form(), +then the latter will get precedence. +>>> class UserRegistration(Form): +... username = CharField(max_length=10, initial=initial_django) +... password = CharField(widget=PasswordInput) +>>> p = UserRegistration(auto_id=False) +>>> print p.as_ul() +<li>Username: <input type="text" name="username" value="django" maxlength="10" /></li> +<li>Password: <input type="password" name="password" /></li> +>>> p = UserRegistration(initial={'username': initial_stephane}, auto_id=False) +>>> print p.as_ul() +<li>Username: <input type="text" name="username" value="stephane" maxlength="10" /></li> +<li>Password: <input type="password" name="password" /></li> + +# Help text ################################################################### + +You can specify descriptive text for a field by using the 'help_text' argument +to a Field class. This help text is displayed when a Form is rendered. +>>> class UserRegistration(Form): +... username = CharField(max_length=10, help_text='e.g., user@example.com') +... password = CharField(widget=PasswordInput, help_text='Choose wisely.') +>>> p = UserRegistration(auto_id=False) +>>> print p.as_ul() +<li>Username: <input type="text" name="username" maxlength="10" /> e.g., user@example.com</li> +<li>Password: <input type="password" name="password" /> Choose wisely.</li> +>>> print p.as_p() +<p>Username: <input type="text" name="username" maxlength="10" /> e.g., user@example.com</p> +<p>Password: <input type="password" name="password" /> Choose wisely.</p> +>>> print p.as_table() +<tr><th>Username:</th><td><input type="text" name="username" maxlength="10" /><br />e.g., user@example.com</td></tr> +<tr><th>Password:</th><td><input type="password" name="password" /><br />Choose wisely.</td></tr> + +The help text is displayed whether or not data is provided for the form. +>>> p = UserRegistration({'username': u'foo'}, auto_id=False) +>>> print p.as_ul() +<li>Username: <input type="text" name="username" value="foo" maxlength="10" /> e.g., user@example.com</li> +<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /> Choose wisely.</li> + +help_text is not displayed for hidden fields. It can be used for documentation +purposes, though. +>>> class UserRegistration(Form): +... username = CharField(max_length=10, help_text='e.g., user@example.com') +... password = CharField(widget=PasswordInput) +... next = CharField(widget=HiddenInput, initial='/', help_text='Redirect destination') +>>> p = UserRegistration(auto_id=False) +>>> print p.as_ul() +<li>Username: <input type="text" name="username" maxlength="10" /> e.g., user@example.com</li> +<li>Password: <input type="password" name="password" /><input type="hidden" name="next" value="/" /></li> + +Help text can include arbitrary Unicode characters. +>>> class UserRegistration(Form): +... username = CharField(max_length=10, help_text='ŠĐĆŽćžšđ') +>>> p = UserRegistration(auto_id=False) +>>> p.as_ul() +u'<li>Username: <input type="text" name="username" maxlength="10" /> \u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111</li>' + +# Subclassing forms ########################################################### + +You can subclass a Form to add fields. The resulting form subclass will have +all of the fields of the parent Form, plus whichever fields you define in the +subclass. +>>> class Person(Form): +... first_name = CharField() +... last_name = CharField() +... birthday = DateField() +>>> class Musician(Person): +... instrument = CharField() +>>> p = Person(auto_id=False) +>>> print p.as_ul() +<li>First name: <input type="text" name="first_name" /></li> +<li>Last name: <input type="text" name="last_name" /></li> +<li>Birthday: <input type="text" name="birthday" /></li> +>>> m = Musician(auto_id=False) +>>> print m.as_ul() +<li>First name: <input type="text" name="first_name" /></li> +<li>Last name: <input type="text" name="last_name" /></li> +<li>Birthday: <input type="text" name="birthday" /></li> +<li>Instrument: <input type="text" name="instrument" /></li> + +Yes, you can subclass multiple forms. The fields are added in the order in +which the parent classes are listed. +>>> class Person(Form): +... first_name = CharField() +... last_name = CharField() +... birthday = DateField() +>>> class Instrument(Form): +... instrument = CharField() +>>> class Beatle(Person, Instrument): +... haircut_type = CharField() +>>> b = Beatle(auto_id=False) +>>> print b.as_ul() +<li>First name: <input type="text" name="first_name" /></li> +<li>Last name: <input type="text" name="last_name" /></li> +<li>Birthday: <input type="text" name="birthday" /></li> +<li>Instrument: <input type="text" name="instrument" /></li> +<li>Haircut type: <input type="text" name="haircut_type" /></li> + +# Forms with prefixes ######################################################### + +Sometimes it's necessary to have multiple forms display on the same HTML page, +or multiple copies of the same form. We can accomplish this with form prefixes. +Pass the keyword argument 'prefix' to the Form constructor to use this feature. +This value will be prepended to each HTML form field name. One way to think +about this is "namespaces for HTML forms". Notice that in the data argument, +each field's key has the prefix, in this case 'person1', prepended to the +actual field name. +>>> class Person(Form): +... first_name = CharField() +... last_name = CharField() +... birthday = DateField() +>>> data = { +... 'person1-first_name': u'John', +... 'person1-last_name': u'Lennon', +... 'person1-birthday': u'1940-10-9' +... } +>>> p = Person(data, prefix='person1') +>>> print p.as_ul() +<li><label for="id_person1-first_name">First name:</label> <input type="text" name="person1-first_name" value="John" id="id_person1-first_name" /></li> +<li><label for="id_person1-last_name">Last name:</label> <input type="text" name="person1-last_name" value="Lennon" id="id_person1-last_name" /></li> +<li><label for="id_person1-birthday">Birthday:</label> <input type="text" name="person1-birthday" value="1940-10-9" id="id_person1-birthday" /></li> +>>> print p['first_name'] +<input type="text" name="person1-first_name" value="John" id="id_person1-first_name" /> +>>> print p['last_name'] +<input type="text" name="person1-last_name" value="Lennon" id="id_person1-last_name" /> +>>> print p['birthday'] +<input type="text" name="person1-birthday" value="1940-10-9" id="id_person1-birthday" /> +>>> p.errors +{} +>>> p.is_valid() +True +>>> p.cleaned_data +{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)} + +Let's try submitting some bad data to make sure form.errors and field.errors +work as expected. +>>> data = { +... 'person1-first_name': u'', +... 'person1-last_name': u'', +... 'person1-birthday': u'' +... } +>>> p = Person(data, prefix='person1') +>>> p.errors +{'first_name': [u'This field is required.'], 'last_name': [u'This field is required.'], 'birthday': [u'This field is required.']} +>>> p['first_name'].errors +[u'This field is required.'] +>>> p['person1-first_name'].errors +Traceback (most recent call last): +... +KeyError: "Key 'person1-first_name' not found in Form" + +In this example, the data doesn't have a prefix, but the form requires it, so +the form doesn't "see" the fields. +>>> data = { +... 'first_name': u'John', +... 'last_name': u'Lennon', +... 'birthday': u'1940-10-9' +... } +>>> p = Person(data, prefix='person1') +>>> p.errors +{'first_name': [u'This field is required.'], 'last_name': [u'This field is required.'], 'birthday': [u'This field is required.']} + +With prefixes, a single data dictionary can hold data for multiple instances +of the same form. +>>> data = { +... 'person1-first_name': u'John', +... 'person1-last_name': u'Lennon', +... 'person1-birthday': u'1940-10-9', +... 'person2-first_name': u'Jim', +... 'person2-last_name': u'Morrison', +... 'person2-birthday': u'1943-12-8' +... } +>>> p1 = Person(data, prefix='person1') +>>> p1.is_valid() +True +>>> p1.cleaned_data +{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)} +>>> p2 = Person(data, prefix='person2') +>>> p2.is_valid() +True +>>> p2.cleaned_data +{'first_name': u'Jim', 'last_name': u'Morrison', 'birthday': datetime.date(1943, 12, 8)} + +By default, forms append a hyphen between the prefix and the field name, but a +form can alter that behavior by implementing the add_prefix() method. This +method takes a field name and returns the prefixed field, according to +self.prefix. +>>> class Person(Form): +... first_name = CharField() +... last_name = CharField() +... birthday = DateField() +... def add_prefix(self, field_name): +... return self.prefix and '%s-prefix-%s' % (self.prefix, field_name) or field_name +>>> p = Person(prefix='foo') +>>> print p.as_ul() +<li><label for="id_foo-prefix-first_name">First name:</label> <input type="text" name="foo-prefix-first_name" id="id_foo-prefix-first_name" /></li> +<li><label for="id_foo-prefix-last_name">Last name:</label> <input type="text" name="foo-prefix-last_name" id="id_foo-prefix-last_name" /></li> +<li><label for="id_foo-prefix-birthday">Birthday:</label> <input type="text" name="foo-prefix-birthday" id="id_foo-prefix-birthday" /></li> +>>> data = { +... 'foo-prefix-first_name': u'John', +... 'foo-prefix-last_name': u'Lennon', +... 'foo-prefix-birthday': u'1940-10-9' +... } +>>> p = Person(data, prefix='foo') +>>> p.is_valid() +True +>>> p.cleaned_data +{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)} + +# Forms with NullBooleanFields ################################################ + +NullBooleanField is a bit of a special case because its presentation (widget) +is different than its data. This is handled transparently, though. + +>>> class Person(Form): +... name = CharField() +... is_cool = NullBooleanField() +>>> p = Person({'name': u'Joe'}, auto_id=False) +>>> print p['is_cool'] +<select name="is_cool"> +<option value="1" selected="selected">Unknown</option> +<option value="2">Yes</option> +<option value="3">No</option> +</select> +>>> p = Person({'name': u'Joe', 'is_cool': u'1'}, auto_id=False) +>>> print p['is_cool'] +<select name="is_cool"> +<option value="1" selected="selected">Unknown</option> +<option value="2">Yes</option> +<option value="3">No</option> +</select> +>>> p = Person({'name': u'Joe', 'is_cool': u'2'}, auto_id=False) +>>> print p['is_cool'] +<select name="is_cool"> +<option value="1">Unknown</option> +<option value="2" selected="selected">Yes</option> +<option value="3">No</option> +</select> +>>> p = Person({'name': u'Joe', 'is_cool': u'3'}, auto_id=False) +>>> print p['is_cool'] +<select name="is_cool"> +<option value="1">Unknown</option> +<option value="2">Yes</option> +<option value="3" selected="selected">No</option> +</select> +>>> p = Person({'name': u'Joe', 'is_cool': True}, auto_id=False) +>>> print p['is_cool'] +<select name="is_cool"> +<option value="1">Unknown</option> +<option value="2" selected="selected">Yes</option> +<option value="3">No</option> +</select> +>>> p = Person({'name': u'Joe', 'is_cool': False}, auto_id=False) +>>> print p['is_cool'] +<select name="is_cool"> +<option value="1">Unknown</option> +<option value="2">Yes</option> +<option value="3" selected="selected">No</option> +</select> + +# Forms with FileFields ################################################ + +FileFields are a special case because they take their data from the request.FILES, +not request.POST. + +>>> class FileForm(Form): +... file1 = FileField() +>>> f = FileForm(auto_id=False) +>>> print f +<tr><th>File1:</th><td><input type="file" name="file1" /></td></tr> + +>>> f = FileForm(data={}, files={}, auto_id=False) +>>> print f +<tr><th>File1:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="file" name="file1" /></td></tr> + +>>> f = FileForm(data={}, files={'file1': {'filename': 'name', 'content':''}}, auto_id=False) +>>> print f +<tr><th>File1:</th><td><ul class="errorlist"><li>The submitted file is empty.</li></ul><input type="file" name="file1" /></td></tr> + +>>> f = FileForm(data={}, files={'file1': 'something that is not a file'}, auto_id=False) +>>> print f +<tr><th>File1:</th><td><ul class="errorlist"><li>No file was submitted. Check the encoding type on the form.</li></ul><input type="file" name="file1" /></td></tr> + +>>> f = FileForm(data={}, files={'file1': {'filename': 'name', 'content':'some content'}}, auto_id=False) +>>> print f +<tr><th>File1:</th><td><input type="file" name="file1" /></td></tr> +>>> f.is_valid() +True + +# Basic form processing in a view ############################################# + +>>> from django.template import Template, Context +>>> class UserRegistration(Form): +... username = CharField(max_length=10) +... password1 = CharField(widget=PasswordInput) +... password2 = CharField(widget=PasswordInput) +... def clean(self): +... if self.cleaned_data.get('password1') and self.cleaned_data.get('password2') and self.cleaned_data['password1'] != self.cleaned_data['password2']: +... raise ValidationError(u'Please make sure your passwords match.') +... return self.cleaned_data +>>> def my_function(method, post_data): +... if method == 'POST': +... form = UserRegistration(post_data, auto_id=False) +... else: +... form = UserRegistration(auto_id=False) +... if form.is_valid(): +... return 'VALID: %r' % form.cleaned_data +... t = Template('<form action="" method="post">\n<table>\n{{ form }}\n</table>\n<input type="submit" />\n</form>') +... return t.render(Context({'form': form})) + +Case 1: GET (an empty form, with no errors). +>>> print my_function('GET', {}) +<form action="" method="post"> +<table> +<tr><th>Username:</th><td><input type="text" name="username" maxlength="10" /></td></tr> +<tr><th>Password1:</th><td><input type="password" name="password1" /></td></tr> +<tr><th>Password2:</th><td><input type="password" name="password2" /></td></tr> +</table> +<input type="submit" /> +</form> + +Case 2: POST with erroneous data (a redisplayed form, with errors). +>>> print my_function('POST', {'username': 'this-is-a-long-username', 'password1': 'foo', 'password2': 'bar'}) +<form action="" method="post"> +<table> +<tr><td colspan="2"><ul class="errorlist"><li>Please make sure your passwords match.</li></ul></td></tr> +<tr><th>Username:</th><td><ul class="errorlist"><li>Ensure this value has at most 10 characters (it has 23).</li></ul><input type="text" name="username" value="this-is-a-long-username" maxlength="10" /></td></tr> +<tr><th>Password1:</th><td><input type="password" name="password1" value="foo" /></td></tr> +<tr><th>Password2:</th><td><input type="password" name="password2" value="bar" /></td></tr> +</table> +<input type="submit" /> +</form> + +Case 3: POST with valid data (the success message). +>>> print my_function('POST', {'username': 'adrian', 'password1': 'secret', 'password2': 'secret'}) +VALID: {'username': u'adrian', 'password1': u'secret', 'password2': u'secret'} + +# Some ideas for using templates with forms ################################### + +>>> class UserRegistration(Form): +... username = CharField(max_length=10, help_text="Good luck picking a username that doesn't already exist.") +... password1 = CharField(widget=PasswordInput) +... password2 = CharField(widget=PasswordInput) +... def clean(self): +... if self.cleaned_data.get('password1') and self.cleaned_data.get('password2') and self.cleaned_data['password1'] != self.cleaned_data['password2']: +... raise ValidationError(u'Please make sure your passwords match.') +... return self.cleaned_data + +You have full flexibility in displaying form fields in a template. Just pass a +Form instance to the template, and use "dot" access to refer to individual +fields. Note, however, that this flexibility comes with the responsibility of +displaying all the errors, including any that might not be associated with a +particular field. +>>> t = Template('''<form action=""> +... {{ form.username.errors.as_ul }}<p><label>Your username: {{ form.username }}</label></p> +... {{ form.password1.errors.as_ul }}<p><label>Password: {{ form.password1 }}</label></p> +... {{ form.password2.errors.as_ul }}<p><label>Password (again): {{ form.password2 }}</label></p> +... <input type="submit" /> +... </form>''') +>>> print t.render(Context({'form': UserRegistration(auto_id=False)})) +<form action=""> +<p><label>Your username: <input type="text" name="username" maxlength="10" /></label></p> +<p><label>Password: <input type="password" name="password1" /></label></p> +<p><label>Password (again): <input type="password" name="password2" /></label></p> +<input type="submit" /> +</form> +>>> print t.render(Context({'form': UserRegistration({'username': 'django'}, auto_id=False)})) +<form action=""> +<p><label>Your username: <input type="text" name="username" value="django" maxlength="10" /></label></p> +<ul class="errorlist"><li>This field is required.</li></ul><p><label>Password: <input type="password" name="password1" /></label></p> +<ul class="errorlist"><li>This field is required.</li></ul><p><label>Password (again): <input type="password" name="password2" /></label></p> +<input type="submit" /> +</form> + +Use form.[field].label to output a field's label. You can specify the label for +a field by using the 'label' argument to a Field class. If you don't specify +'label', Django will use the field name with underscores converted to spaces, +and the initial letter capitalized. +>>> t = Template('''<form action=""> +... <p><label>{{ form.username.label }}: {{ form.username }}</label></p> +... <p><label>{{ form.password1.label }}: {{ form.password1 }}</label></p> +... <p><label>{{ form.password2.label }}: {{ form.password2 }}</label></p> +... <input type="submit" /> +... </form>''') +>>> print t.render(Context({'form': UserRegistration(auto_id=False)})) +<form action=""> +<p><label>Username: <input type="text" name="username" maxlength="10" /></label></p> +<p><label>Password1: <input type="password" name="password1" /></label></p> +<p><label>Password2: <input type="password" name="password2" /></label></p> +<input type="submit" /> +</form> + +User form.[field].label_tag to output a field's label with a <label> tag +wrapped around it, but *only* if the given field has an "id" attribute. +Recall from above that passing the "auto_id" argument to a Form gives each +field an "id" attribute. +>>> t = Template('''<form action=""> +... <p>{{ form.username.label_tag }}: {{ form.username }}</p> +... <p>{{ form.password1.label_tag }}: {{ form.password1 }}</p> +... <p>{{ form.password2.label_tag }}: {{ form.password2 }}</p> +... <input type="submit" /> +... </form>''') +>>> print t.render(Context({'form': UserRegistration(auto_id=False)})) +<form action=""> +<p>Username: <input type="text" name="username" maxlength="10" /></p> +<p>Password1: <input type="password" name="password1" /></p> +<p>Password2: <input type="password" name="password2" /></p> +<input type="submit" /> +</form> +>>> print t.render(Context({'form': UserRegistration(auto_id='id_%s')})) +<form action=""> +<p><label for="id_username">Username</label>: <input id="id_username" type="text" name="username" maxlength="10" /></p> +<p><label for="id_password1">Password1</label>: <input type="password" name="password1" id="id_password1" /></p> +<p><label for="id_password2">Password2</label>: <input type="password" name="password2" id="id_password2" /></p> +<input type="submit" /> +</form> + +User form.[field].help_text to output a field's help text. If the given field +does not have help text, nothing will be output. +>>> t = Template('''<form action=""> +... <p>{{ form.username.label_tag }}: {{ form.username }}<br />{{ form.username.help_text }}</p> +... <p>{{ form.password1.label_tag }}: {{ form.password1 }}</p> +... <p>{{ form.password2.label_tag }}: {{ form.password2 }}</p> +... <input type="submit" /> +... </form>''') +>>> print t.render(Context({'form': UserRegistration(auto_id=False)})) +<form action=""> +<p>Username: <input type="text" name="username" maxlength="10" /><br />Good luck picking a username that doesn't already exist.</p> +<p>Password1: <input type="password" name="password1" /></p> +<p>Password2: <input type="password" name="password2" /></p> +<input type="submit" /> +</form> +>>> Template('{{ form.password1.help_text }}').render(Context({'form': UserRegistration(auto_id=False)})) +u'' + +The label_tag() method takes an optional attrs argument: a dictionary of HTML +attributes to add to the <label> tag. +>>> f = UserRegistration(auto_id='id_%s') +>>> for bf in f: +... print bf.label_tag(attrs={'class': 'pretty'}) +<label for="id_username" class="pretty">Username</label> +<label for="id_password1" class="pretty">Password1</label> +<label for="id_password2" class="pretty">Password2</label> + +To display the errors that aren't associated with a particular field -- e.g., +the errors caused by Form.clean() -- use {{ form.non_field_errors }} in the +template. If used on its own, it is displayed as a <ul> (or an empty string, if +the list of errors is empty). You can also use it in {% if %} statements. +>>> t = Template('''<form action=""> +... {{ form.username.errors.as_ul }}<p><label>Your username: {{ form.username }}</label></p> +... {{ form.password1.errors.as_ul }}<p><label>Password: {{ form.password1 }}</label></p> +... {{ form.password2.errors.as_ul }}<p><label>Password (again): {{ form.password2 }}</label></p> +... <input type="submit" /> +... </form>''') +>>> print t.render(Context({'form': UserRegistration({'username': 'django', 'password1': 'foo', 'password2': 'bar'}, auto_id=False)})) +<form action=""> +<p><label>Your username: <input type="text" name="username" value="django" maxlength="10" /></label></p> +<p><label>Password: <input type="password" name="password1" value="foo" /></label></p> +<p><label>Password (again): <input type="password" name="password2" value="bar" /></label></p> +<input type="submit" /> +</form> +>>> t = Template('''<form action=""> +... {{ form.non_field_errors }} +... {{ form.username.errors.as_ul }}<p><label>Your username: {{ form.username }}</label></p> +... {{ form.password1.errors.as_ul }}<p><label>Password: {{ form.password1 }}</label></p> +... {{ form.password2.errors.as_ul }}<p><label>Password (again): {{ form.password2 }}</label></p> +... <input type="submit" /> +... </form>''') +>>> print t.render(Context({'form': UserRegistration({'username': 'django', 'password1': 'foo', 'password2': 'bar'}, auto_id=False)})) +<form action=""> +<ul class="errorlist"><li>Please make sure your passwords match.</li></ul> +<p><label>Your username: <input type="text" name="username" value="django" maxlength="10" /></label></p> +<p><label>Password: <input type="password" name="password1" value="foo" /></label></p> +<p><label>Password (again): <input type="password" name="password2" value="bar" /></label></p> +<input type="submit" /> +</form> +""" diff --git a/tests/regressiontests/forms/localflavor.py b/tests/regressiontests/forms/localflavor.py deleted file mode 100644 index a896013b0d..0000000000 --- a/tests/regressiontests/forms/localflavor.py +++ /dev/null @@ -1,1449 +0,0 @@ -# -*- coding: utf-8 -*- -# Tests for the different contrib/localflavor/ form fields. - -localflavor_tests = r""" -# USZipCodeField ############################################################## - -USZipCodeField validates that the data is either a five-digit U.S. zip code or -a zip+4. ->>> from django.contrib.localflavor.us.forms import USZipCodeField ->>> f = USZipCodeField() ->>> f.clean('60606') -u'60606' ->>> f.clean(60606) -u'60606' ->>> f.clean('04000') -u'04000' ->>> f.clean('4000') -Traceback (most recent call last): -... -ValidationError: [u'Enter a zip code in the format XXXXX or XXXXX-XXXX.'] ->>> f.clean('60606-1234') -u'60606-1234' ->>> f.clean('6060-1234') -Traceback (most recent call last): -... -ValidationError: [u'Enter a zip code in the format XXXXX or XXXXX-XXXX.'] ->>> f.clean('60606-') -Traceback (most recent call last): -... -ValidationError: [u'Enter a zip code in the format XXXXX or XXXXX-XXXX.'] ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] - ->>> f = USZipCodeField(required=False) ->>> f.clean('60606') -u'60606' ->>> f.clean(60606) -u'60606' ->>> f.clean('04000') -u'04000' ->>> f.clean('4000') -Traceback (most recent call last): -... -ValidationError: [u'Enter a zip code in the format XXXXX or XXXXX-XXXX.'] ->>> f.clean('60606-1234') -u'60606-1234' ->>> f.clean('6060-1234') -Traceback (most recent call last): -... -ValidationError: [u'Enter a zip code in the format XXXXX or XXXXX-XXXX.'] ->>> f.clean('60606-') -Traceback (most recent call last): -... -ValidationError: [u'Enter a zip code in the format XXXXX or XXXXX-XXXX.'] ->>> f.clean(None) -u'' ->>> f.clean('') -u'' - -# USPhoneNumberField ########################################################## - -USPhoneNumberField validates that the data is a valid U.S. phone number, -including the area code. It's normalized to XXX-XXX-XXXX format. ->>> from django.contrib.localflavor.us.forms import USPhoneNumberField ->>> f = USPhoneNumberField() ->>> f.clean('312-555-1212') -u'312-555-1212' ->>> f.clean('3125551212') -u'312-555-1212' ->>> f.clean('312 555-1212') -u'312-555-1212' ->>> f.clean('(312) 555-1212') -u'312-555-1212' ->>> f.clean('312 555 1212') -u'312-555-1212' ->>> f.clean('312.555.1212') -u'312-555-1212' ->>> f.clean('312.555-1212') -u'312-555-1212' ->>> f.clean(' (312) 555.1212 ') -u'312-555-1212' ->>> f.clean('555-1212') -Traceback (most recent call last): -... -ValidationError: [u'Phone numbers must be in XXX-XXX-XXXX format.'] ->>> f.clean('312-55-1212') -Traceback (most recent call last): -... -ValidationError: [u'Phone numbers must be in XXX-XXX-XXXX format.'] ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] - ->>> f = USPhoneNumberField(required=False) ->>> f.clean('312-555-1212') -u'312-555-1212' ->>> f.clean('3125551212') -u'312-555-1212' ->>> f.clean('312 555-1212') -u'312-555-1212' ->>> f.clean('(312) 555-1212') -u'312-555-1212' ->>> f.clean('312 555 1212') -u'312-555-1212' ->>> f.clean('312.555.1212') -u'312-555-1212' ->>> f.clean('312.555-1212') -u'312-555-1212' ->>> f.clean(' (312) 555.1212 ') -u'312-555-1212' ->>> f.clean('555-1212') -Traceback (most recent call last): -... -ValidationError: [u'Phone numbers must be in XXX-XXX-XXXX format.'] ->>> f.clean('312-55-1212') -Traceback (most recent call last): -... -ValidationError: [u'Phone numbers must be in XXX-XXX-XXXX format.'] ->>> f.clean(None) -u'' ->>> f.clean('') -u'' - -# USStateField ################################################################ - -USStateField validates that the data is either an abbreviation or name of a -U.S. state. ->>> from django.contrib.localflavor.us.forms import USStateField ->>> f = USStateField() ->>> f.clean('il') -u'IL' ->>> f.clean('IL') -u'IL' ->>> f.clean('illinois') -u'IL' ->>> f.clean(' illinois ') -u'IL' ->>> f.clean(60606) -Traceback (most recent call last): -... -ValidationError: [u'Enter a U.S. state or territory.'] ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] - ->>> f = USStateField(required=False) ->>> f.clean('il') -u'IL' ->>> f.clean('IL') -u'IL' ->>> f.clean('illinois') -u'IL' ->>> f.clean(' illinois ') -u'IL' ->>> f.clean(60606) -Traceback (most recent call last): -... -ValidationError: [u'Enter a U.S. state or territory.'] ->>> f.clean(None) -u'' ->>> f.clean('') -u'' - -# USStateSelect ############################################################### - -USStateSelect is a Select widget that uses a list of U.S. states/territories -as its choices. ->>> from django.contrib.localflavor.us.forms import USStateSelect ->>> w = USStateSelect() ->>> print w.render('state', 'IL') -<select name="state"> -<option value="AL">Alabama</option> -<option value="AK">Alaska</option> -<option value="AS">American Samoa</option> -<option value="AZ">Arizona</option> -<option value="AR">Arkansas</option> -<option value="CA">California</option> -<option value="CO">Colorado</option> -<option value="CT">Connecticut</option> -<option value="DE">Delaware</option> -<option value="DC">District of Columbia</option> -<option value="FM">Federated States of Micronesia</option> -<option value="FL">Florida</option> -<option value="GA">Georgia</option> -<option value="GU">Guam</option> -<option value="HI">Hawaii</option> -<option value="ID">Idaho</option> -<option value="IL" selected="selected">Illinois</option> -<option value="IN">Indiana</option> -<option value="IA">Iowa</option> -<option value="KS">Kansas</option> -<option value="KY">Kentucky</option> -<option value="LA">Louisiana</option> -<option value="ME">Maine</option> -<option value="MH">Marshall Islands</option> -<option value="MD">Maryland</option> -<option value="MA">Massachusetts</option> -<option value="MI">Michigan</option> -<option value="MN">Minnesota</option> -<option value="MS">Mississippi</option> -<option value="MO">Missouri</option> -<option value="MT">Montana</option> -<option value="NE">Nebraska</option> -<option value="NV">Nevada</option> -<option value="NH">New Hampshire</option> -<option value="NJ">New Jersey</option> -<option value="NM">New Mexico</option> -<option value="NY">New York</option> -<option value="NC">North Carolina</option> -<option value="ND">North Dakota</option> -<option value="MP">Northern Mariana Islands</option> -<option value="OH">Ohio</option> -<option value="OK">Oklahoma</option> -<option value="OR">Oregon</option> -<option value="PW">Palau</option> -<option value="PA">Pennsylvania</option> -<option value="PR">Puerto Rico</option> -<option value="RI">Rhode Island</option> -<option value="SC">South Carolina</option> -<option value="SD">South Dakota</option> -<option value="TN">Tennessee</option> -<option value="TX">Texas</option> -<option value="UT">Utah</option> -<option value="VT">Vermont</option> -<option value="VI">Virgin Islands</option> -<option value="VA">Virginia</option> -<option value="WA">Washington</option> -<option value="WV">West Virginia</option> -<option value="WI">Wisconsin</option> -<option value="WY">Wyoming</option> -</select> - -# USSocialSecurityNumberField ################################################# ->>> from django.contrib.localflavor.us.forms import USSocialSecurityNumberField ->>> f = USSocialSecurityNumberField() ->>> f.clean('987-65-4330') -u'987-65-4330' ->>> f.clean('987654330') -u'987-65-4330' ->>> f.clean('078-05-1120') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid U.S. Social Security number in XXX-XX-XXXX format.'] - -# UKPostcodeField ############################################################# - -UKPostcodeField validates that the data is a valid UK postcode. ->>> from django.contrib.localflavor.uk.forms import UKPostcodeField ->>> f = UKPostcodeField() ->>> f.clean('BT32 4PX') -u'BT32 4PX' ->>> f.clean('GIR 0AA') -u'GIR 0AA' ->>> f.clean('BT324PX') -Traceback (most recent call last): -... -ValidationError: [u'Enter a postcode. A space is required between the two postcode parts.'] ->>> f.clean('1NV 4L1D') -Traceback (most recent call last): -... -ValidationError: [u'Enter a postcode. A space is required between the two postcode parts.'] ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] - ->>> f = UKPostcodeField(required=False) ->>> f.clean('BT32 4PX') -u'BT32 4PX' ->>> f.clean('GIR 0AA') -u'GIR 0AA' ->>> f.clean('1NV 4L1D') -Traceback (most recent call last): -... -ValidationError: [u'Enter a postcode. A space is required between the two postcode parts.'] ->>> f.clean('BT324PX') -Traceback (most recent call last): -... -ValidationError: [u'Enter a postcode. A space is required between the two postcode parts.'] ->>> f.clean(None) -u'' ->>> f.clean('') -u'' - -# FRZipCodeField ############################################################# - -FRZipCodeField validates that the data is a valid FR zipcode. ->>> from django.contrib.localflavor.fr.forms import FRZipCodeField ->>> f = FRZipCodeField() ->>> f.clean('75001') -u'75001' ->>> f.clean('93200') -u'93200' ->>> f.clean('2A200') -Traceback (most recent call last): -... -ValidationError: [u'Enter a zip code in the format XXXXX.'] ->>> f.clean('980001') -Traceback (most recent call last): -... -ValidationError: [u'Enter a zip code in the format XXXXX.'] ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] - ->>> f = FRZipCodeField(required=False) ->>> f.clean('75001') -u'75001' ->>> f.clean('93200') -u'93200' ->>> f.clean('2A200') -Traceback (most recent call last): -... -ValidationError: [u'Enter a zip code in the format XXXXX.'] ->>> f.clean('980001') -Traceback (most recent call last): -... -ValidationError: [u'Enter a zip code in the format XXXXX.'] ->>> f.clean(None) -u'' ->>> f.clean('') -u'' - - -# FRPhoneNumberField ########################################################## - -FRPhoneNumberField validates that the data is a valid french phone number. -It's normalized to 0X XX XX XX XX format. Dots are valid too. ->>> from django.contrib.localflavor.fr.forms import FRPhoneNumberField ->>> f = FRPhoneNumberField() ->>> f.clean('01 55 44 58 64') -u'01 55 44 58 64' ->>> f.clean('0155445864') -u'01 55 44 58 64' ->>> f.clean('01 5544 5864') -u'01 55 44 58 64' ->>> f.clean('01 55.44.58.64') -u'01 55 44 58 64' ->>> f.clean('01.55.44.58.64') -u'01 55 44 58 64' ->>> f.clean('01,55,44,58,64') -Traceback (most recent call last): -... -ValidationError: [u'Phone numbers must be in 0X XX XX XX XX format.'] ->>> f.clean('555 015 544') -Traceback (most recent call last): -... -ValidationError: [u'Phone numbers must be in 0X XX XX XX XX format.'] ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] - ->>> f = FRPhoneNumberField(required=False) ->>> f.clean('01 55 44 58 64') -u'01 55 44 58 64' ->>> f.clean('0155445864') -u'01 55 44 58 64' ->>> f.clean('01 5544 5864') -u'01 55 44 58 64' ->>> f.clean('01 55.44.58.64') -u'01 55 44 58 64' ->>> f.clean('01.55.44.58.64') -u'01 55 44 58 64' ->>> f.clean('01,55,44,58,64') -Traceback (most recent call last): -... -ValidationError: [u'Phone numbers must be in 0X XX XX XX XX format.'] ->>> f.clean('555 015 544') -Traceback (most recent call last): -... -ValidationError: [u'Phone numbers must be in 0X XX XX XX XX format.'] ->>> f.clean(None) -u'' ->>> f.clean('') -u'' - -# FRDepartmentSelect ############################################################### - -FRDepartmentSelect is a Select widget that uses a list of french departments -including DOM TOM ->>> from django.contrib.localflavor.fr.forms import FRDepartmentSelect ->>> w = FRDepartmentSelect() ->>> print w.render('dep', 'Paris') -<select name="dep"> -<option value="01">01 - Ain</option> -<option value="02">02 - Aisne</option> -<option value="03">03 - Allier</option> -<option value="04">04 - Alpes-de-Haute-Provence</option> -<option value="05">05 - Hautes-Alpes</option> -<option value="06">06 - Alpes-Maritimes</option> -<option value="07">07 - Ardeche</option> -<option value="08">08 - Ardennes</option> -<option value="09">09 - Ariege</option> -<option value="10">10 - Aube</option> -<option value="11">11 - Aude</option> -<option value="12">12 - Aveyron</option> -<option value="13">13 - Bouches-du-Rhone</option> -<option value="14">14 - Calvados</option> -<option value="15">15 - Cantal</option> -<option value="16">16 - Charente</option> -<option value="17">17 - Charente-Maritime</option> -<option value="18">18 - Cher</option> -<option value="19">19 - Correze</option> -<option value="21">21 - Cote-d'Or</option> -<option value="22">22 - Cotes-d'Armor</option> -<option value="23">23 - Creuse</option> -<option value="24">24 - Dordogne</option> -<option value="25">25 - Doubs</option> -<option value="26">26 - Drome</option> -<option value="27">27 - Eure</option> -<option value="28">28 - Eure-et-Loire</option> -<option value="29">29 - Finistere</option> -<option value="2A">2A - Corse-du-Sud</option> -<option value="2B">2B - Haute-Corse</option> -<option value="30">30 - Gard</option> -<option value="31">31 - Haute-Garonne</option> -<option value="32">32 - Gers</option> -<option value="33">33 - Gironde</option> -<option value="34">34 - Herault</option> -<option value="35">35 - Ille-et-Vilaine</option> -<option value="36">36 - Indre</option> -<option value="37">37 - Indre-et-Loire</option> -<option value="38">38 - Isere</option> -<option value="39">39 - Jura</option> -<option value="40">40 - Landes</option> -<option value="41">41 - Loir-et-Cher</option> -<option value="42">42 - Loire</option> -<option value="43">43 - Haute-Loire</option> -<option value="44">44 - Loire-Atlantique</option> -<option value="45">45 - Loiret</option> -<option value="46">46 - Lot</option> -<option value="47">47 - Lot-et-Garonne</option> -<option value="48">48 - Lozere</option> -<option value="49">49 - Maine-et-Loire</option> -<option value="50">50 - Manche</option> -<option value="51">51 - Marne</option> -<option value="52">52 - Haute-Marne</option> -<option value="53">53 - Mayenne</option> -<option value="54">54 - Meurthe-et-Moselle</option> -<option value="55">55 - Meuse</option> -<option value="56">56 - Morbihan</option> -<option value="57">57 - Moselle</option> -<option value="58">58 - Nievre</option> -<option value="59">59 - Nord</option> -<option value="60">60 - Oise</option> -<option value="61">61 - Orne</option> -<option value="62">62 - Pas-de-Calais</option> -<option value="63">63 - Puy-de-Dome</option> -<option value="64">64 - Pyrenees-Atlantiques</option> -<option value="65">65 - Hautes-Pyrenees</option> -<option value="66">66 - Pyrenees-Orientales</option> -<option value="67">67 - Bas-Rhin</option> -<option value="68">68 - Haut-Rhin</option> -<option value="69">69 - Rhone</option> -<option value="70">70 - Haute-Saone</option> -<option value="71">71 - Saone-et-Loire</option> -<option value="72">72 - Sarthe</option> -<option value="73">73 - Savoie</option> -<option value="74">74 - Haute-Savoie</option> -<option value="75">75 - Paris</option> -<option value="76">76 - Seine-Maritime</option> -<option value="77">77 - Seine-et-Marne</option> -<option value="78">78 - Yvelines</option> -<option value="79">79 - Deux-Sevres</option> -<option value="80">80 - Somme</option> -<option value="81">81 - Tarn</option> -<option value="82">82 - Tarn-et-Garonne</option> -<option value="83">83 - Var</option> -<option value="84">84 - Vaucluse</option> -<option value="85">85 - Vendee</option> -<option value="86">86 - Vienne</option> -<option value="87">87 - Haute-Vienne</option> -<option value="88">88 - Vosges</option> -<option value="89">89 - Yonne</option> -<option value="90">90 - Territoire de Belfort</option> -<option value="91">91 - Essonne</option> -<option value="92">92 - Hauts-de-Seine</option> -<option value="93">93 - Seine-Saint-Denis</option> -<option value="94">94 - Val-de-Marne</option> -<option value="95">95 - Val-d'Oise</option> -<option value="2A">2A - Corse du sud</option> -<option value="2B">2B - Haute Corse</option> -<option value="971">971 - Guadeloupe</option> -<option value="972">972 - Martinique</option> -<option value="973">973 - Guyane</option> -<option value="974">974 - La Reunion</option> -<option value="975">975 - Saint-Pierre-et-Miquelon</option> -<option value="976">976 - Mayotte</option> -<option value="984">984 - Terres Australes et Antarctiques</option> -<option value="986">986 - Wallis et Futuna</option> -<option value="987">987 - Polynesie Francaise</option> -<option value="988">988 - Nouvelle-Caledonie</option> -</select> - -# JPPostalCodeField ############################################################### - -A form field that validates its input is a Japanese postcode. - -Accepts 7 digits(with/out hyphen). ->>> from django.contrib.localflavor.jp.forms import JPPostalCodeField ->>> f = JPPostalCodeField() ->>> f.clean('251-0032') -u'2510032' ->>> f.clean('2510032') -u'2510032' ->>> f.clean('2510-032') -Traceback (most recent call last): -... -ValidationError: [u'Enter a postal code in the format XXXXXXX or XXX-XXXX.'] ->>> f.clean('251a0032') -Traceback (most recent call last): -... -ValidationError: [u'Enter a postal code in the format XXXXXXX or XXX-XXXX.'] ->>> f.clean('a51-0032') -Traceback (most recent call last): -... -ValidationError: [u'Enter a postal code in the format XXXXXXX or XXX-XXXX.'] ->>> f.clean('25100321') -Traceback (most recent call last): -... -ValidationError: [u'Enter a postal code in the format XXXXXXX or XXX-XXXX.'] ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] - ->>> f = JPPostalCodeField(required=False) ->>> f.clean('251-0032') -u'2510032' ->>> f.clean('2510032') -u'2510032' ->>> f.clean('2510-032') -Traceback (most recent call last): -... -ValidationError: [u'Enter a postal code in the format XXXXXXX or XXX-XXXX.'] ->>> f.clean('') -u'' ->>> f.clean(None) -u'' - -# JPPrefectureSelect ############################################################### - -A Select widget that uses a list of Japanese prefectures as its choices. ->>> from django.contrib.localflavor.jp.forms import JPPrefectureSelect ->>> w = JPPrefectureSelect() ->>> print w.render('prefecture', 'kanagawa') -<select name="prefecture"> -<option value="hokkaido">Hokkaido</option> -<option value="aomori">Aomori</option> -<option value="iwate">Iwate</option> -<option value="miyagi">Miyagi</option> -<option value="akita">Akita</option> -<option value="yamagata">Yamagata</option> -<option value="fukushima">Fukushima</option> -<option value="ibaraki">Ibaraki</option> -<option value="tochigi">Tochigi</option> -<option value="gunma">Gunma</option> -<option value="saitama">Saitama</option> -<option value="chiba">Chiba</option> -<option value="tokyo">Tokyo</option> -<option value="kanagawa" selected="selected">Kanagawa</option> -<option value="yamanashi">Yamanashi</option> -<option value="nagano">Nagano</option> -<option value="niigata">Niigata</option> -<option value="toyama">Toyama</option> -<option value="ishikawa">Ishikawa</option> -<option value="fukui">Fukui</option> -<option value="gifu">Gifu</option> -<option value="shizuoka">Shizuoka</option> -<option value="aichi">Aichi</option> -<option value="mie">Mie</option> -<option value="shiga">Shiga</option> -<option value="kyoto">Kyoto</option> -<option value="osaka">Osaka</option> -<option value="hyogo">Hyogo</option> -<option value="nara">Nara</option> -<option value="wakayama">Wakayama</option> -<option value="tottori">Tottori</option> -<option value="shimane">Shimane</option> -<option value="okayama">Okayama</option> -<option value="hiroshima">Hiroshima</option> -<option value="yamaguchi">Yamaguchi</option> -<option value="tokushima">Tokushima</option> -<option value="kagawa">Kagawa</option> -<option value="ehime">Ehime</option> -<option value="kochi">Kochi</option> -<option value="fukuoka">Fukuoka</option> -<option value="saga">Saga</option> -<option value="nagasaki">Nagasaki</option> -<option value="kumamoto">Kumamoto</option> -<option value="oita">Oita</option> -<option value="miyazaki">Miyazaki</option> -<option value="kagoshima">Kagoshima</option> -<option value="okinawa">Okinawa</option> -</select> - -# ITZipCodeField ############################################################# - ->>> from django.contrib.localflavor.it.forms import ITZipCodeField ->>> f = ITZipCodeField() ->>> f.clean('00100') -u'00100' ->>> f.clean(' 00100') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid zip code.'] - -# ITRegionSelect ############################################################# - ->>> from django.contrib.localflavor.it.forms import ITRegionSelect ->>> w = ITRegionSelect() ->>> w.render('regions', 'PMN') -u'<select name="regions">\n<option value="ABR">Abruzzo</option>\n<option value="BAS">Basilicata</option>\n<option value="CAL">Calabria</option>\n<option value="CAM">Campania</option>\n<option value="EMR">Emilia-Romagna</option>\n<option value="FVG">Friuli-Venezia Giulia</option>\n<option value="LAZ">Lazio</option>\n<option value="LIG">Liguria</option>\n<option value="LOM">Lombardia</option>\n<option value="MAR">Marche</option>\n<option value="MOL">Molise</option>\n<option value="PMN" selected="selected">Piemonte</option>\n<option value="PUG">Puglia</option>\n<option value="SAR">Sardegna</option>\n<option value="SIC">Sicilia</option>\n<option value="TOS">Toscana</option>\n<option value="TAA">Trentino-Alto Adige</option>\n<option value="UMB">Umbria</option>\n<option value="VAO">Valle d\u2019Aosta</option>\n<option value="VEN">Veneto</option>\n</select>' - -# ITSocialSecurityNumberField ################################################# - ->>> from django.contrib.localflavor.it.forms import ITSocialSecurityNumberField ->>> f = ITSocialSecurityNumberField() ->>> f.clean('LVSGDU99T71H501L') -u'LVSGDU99T71H501L' ->>> f.clean('LBRRME11A01L736W') -u'LBRRME11A01L736W' ->>> f.clean('lbrrme11a01l736w') -u'LBRRME11A01L736W' ->>> f.clean('LBR RME 11A01 L736W') -u'LBRRME11A01L736W' ->>> f.clean('LBRRME11A01L736A') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid Social Security number.'] ->>> f.clean('%BRRME11A01L736W') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid Social Security number.'] - -# ITVatNumberField ########################################################### - ->>> from django.contrib.localflavor.it.forms import ITVatNumberField ->>> f = ITVatNumberField() ->>> f.clean('07973780013') -u'07973780013' ->>> f.clean('7973780013') -u'07973780013' ->>> f.clean(7973780013) -u'07973780013' ->>> f.clean('07973780014') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid VAT number.'] ->>> f.clean('A7973780013') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid VAT number.'] - -# FIZipCodeField ############################################################# - -FIZipCodeField validates that the data is a valid FI zipcode. ->>> from django.contrib.localflavor.fi.forms import FIZipCodeField ->>> f = FIZipCodeField() ->>> f.clean('20540') -u'20540' ->>> f.clean('20101') -u'20101' ->>> f.clean('20s40') -Traceback (most recent call last): -... -ValidationError: [u'Enter a zip code in the format XXXXX.'] ->>> f.clean('205401') -Traceback (most recent call last): -... -ValidationError: [u'Enter a zip code in the format XXXXX.'] ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] - ->>> f = FIZipCodeField(required=False) ->>> f.clean('20540') -u'20540' ->>> f.clean('20101') -u'20101' ->>> f.clean('20s40') -Traceback (most recent call last): -... -ValidationError: [u'Enter a zip code in the format XXXXX.'] ->>> f.clean('205401') -Traceback (most recent call last): -... -ValidationError: [u'Enter a zip code in the format XXXXX.'] ->>> f.clean(None) -u'' ->>> f.clean('') -u'' - -# FIMunicipalitySelect ############################################################### - -A Select widget that uses a list of Finnish municipalities as its choices. ->>> from django.contrib.localflavor.fi.forms import FIMunicipalitySelect ->>> w = FIMunicipalitySelect() ->>> unicode(w.render('municipalities', 'turku')) -u'<select name="municipalities">\n<option value="akaa">Akaa</option>\n<option value="alaharma">Alah\xe4rm\xe4</option>\n<option value="alajarvi">Alaj\xe4rvi</option>\n<option value="alastaro">Alastaro</option>\n<option value="alavieska">Alavieska</option>\n<option value="alavus">Alavus</option>\n<option value="anjalankoski">Anjalankoski</option>\n<option value="artjarvi">Artj\xe4rvi</option>\n<option value="asikkala">Asikkala</option>\n<option value="askainen">Askainen</option>\n<option value="askola">Askola</option>\n<option value="aura">Aura</option>\n<option value="brando">Br\xe4nd\xf6</option>\n<option value="dragsfjard">Dragsfj\xe4rd</option>\n<option value="eckero">Ecker\xf6</option>\n<option value="elimaki">Elim\xe4ki</option>\n<option value="eno">Eno</option>\n<option value="enonkoski">Enonkoski</option>\n<option value="enontekio">Enonteki\xf6</option>\n<option value="espoo">Espoo</option>\n<option value="eura">Eura</option>\n<option value="eurajoki">Eurajoki</option>\n<option value="evijarvi">Evij\xe4rvi</option>\n<option value="finstrom">Finstr\xf6m</option>\n<option value="forssa">Forssa</option>\n<option value="foglo">F\xf6gl\xf6</option>\n<option value="geta">Geta</option>\n<option value="haapajarvi">Haapaj\xe4rvi</option>\n<option value="haapavesi">Haapavesi</option>\n<option value="hailuoto">Hailuoto</option>\n<option value="halikko">Halikko</option>\n<option value="halsua">Halsua</option>\n<option value="hamina">Hamina</option>\n<option value="hammarland">Hammarland</option>\n<option value="hankasalmi">Hankasalmi</option>\n<option value="hanko">Hanko</option>\n<option value="harjavalta">Harjavalta</option>\n<option value="hartola">Hartola</option>\n<option value="hattula">Hattula</option>\n<option value="hauho">Hauho</option>\n<option value="haukipudas">Haukipudas</option>\n<option value="hausjarvi">Hausj\xe4rvi</option>\n<option value="heinola">Heinola</option>\n<option value="heinavesi">Hein\xe4vesi</option>\n<option value="helsinki">Helsinki</option>\n<option value="himanka">Himanka</option>\n<option value="hirvensalmi">Hirvensalmi</option>\n<option value="hollola">Hollola</option>\n<option value="honkajoki">Honkajoki</option>\n<option value="houtskari">Houtskari</option>\n<option value="huittinen">Huittinen</option>\n<option value="humppila">Humppila</option>\n<option value="hyrynsalmi">Hyrynsalmi</option>\n<option value="hyvinkaa">Hyvink\xe4\xe4</option>\n<option value="hameenkoski">H\xe4meenkoski</option>\n<option value="hameenkyro">H\xe4meenkyr\xf6</option>\n<option value="hameenlinna">H\xe4meenlinna</option>\n<option value="ii">Ii</option>\n<option value="iisalmi">Iisalmi</option>\n<option value="iitti">Iitti</option>\n<option value="ikaalinen">Ikaalinen</option>\n<option value="ilmajoki">Ilmajoki</option>\n<option value="ilomantsi">Ilomantsi</option>\n<option value="imatra">Imatra</option>\n<option value="inari">Inari</option>\n<option value="inio">Ini\xf6</option>\n<option value="inkoo">Inkoo</option>\n<option value="isojoki">Isojoki</option>\n<option value="isokyro">Isokyr\xf6</option>\n<option value="jaala">Jaala</option>\n<option value="jalasjarvi">Jalasj\xe4rvi</option>\n<option value="janakkala">Janakkala</option>\n<option value="joensuu">Joensuu</option>\n<option value="jokioinen">Jokioinen</option>\n<option value="jomala">Jomala</option>\n<option value="joroinen">Joroinen</option>\n<option value="joutsa">Joutsa</option>\n<option value="joutseno">Joutseno</option>\n<option value="juankoski">Juankoski</option>\n<option value="jurva">Jurva</option>\n<option value="juuka">Juuka</option>\n<option value="juupajoki">Juupajoki</option>\n<option value="juva">Juva</option>\n<option value="jyvaskyla">Jyv\xe4skyl\xe4</option>\n<option value="jyvaskylan_mlk">Jyv\xe4skyl\xe4n maalaiskunta</option>\n<option value="jamijarvi">J\xe4mij\xe4rvi</option>\n<option value="jamsa">J\xe4ms\xe4</option>\n<option value="jamsankoski">J\xe4ms\xe4nkoski</option>\n<option value="jarvenpaa">J\xe4rvenp\xe4\xe4</option>\n<option value="kaarina">Kaarina</option>\n<option value="kaavi">Kaavi</option>\n<option value="kajaani">Kajaani</option>\n<option value="kalajoki">Kalajoki</option>\n<option value="kalvola">Kalvola</option>\n<option value="kangasala">Kangasala</option>\n<option value="kangasniemi">Kangasniemi</option>\n<option value="kankaanpaa">Kankaanp\xe4\xe4</option>\n<option value="kannonkoski">Kannonkoski</option>\n<option value="kannus">Kannus</option>\n<option value="karijoki">Karijoki</option>\n<option value="karjaa">Karjaa</option>\n<option value="karjalohja">Karjalohja</option>\n<option value="karkkila">Karkkila</option>\n<option value="karstula">Karstula</option>\n<option value="karttula">Karttula</option>\n<option value="karvia">Karvia</option>\n<option value="kaskinen">Kaskinen</option>\n<option value="kauhajoki">Kauhajoki</option>\n<option value="kauhava">Kauhava</option>\n<option value="kauniainen">Kauniainen</option>\n<option value="kaustinen">Kaustinen</option>\n<option value="keitele">Keitele</option>\n<option value="kemi">Kemi</option>\n<option value="kemijarvi">Kemij\xe4rvi</option>\n<option value="keminmaa">Keminmaa</option>\n<option value="kemio">Kemi\xf6</option>\n<option value="kempele">Kempele</option>\n<option value="kerava">Kerava</option>\n<option value="kerimaki">Kerim\xe4ki</option>\n<option value="kestila">Kestil\xe4</option>\n<option value="kesalahti">Kes\xe4lahti</option>\n<option value="keuruu">Keuruu</option>\n<option value="kihnio">Kihni\xf6</option>\n<option value="kiikala">Kiikala</option>\n<option value="kiikoinen">Kiikoinen</option>\n<option value="kiiminki">Kiiminki</option>\n<option value="kinnula">Kinnula</option>\n<option value="kirkkonummi">Kirkkonummi</option>\n<option value="kisko">Kisko</option>\n<option value="kitee">Kitee</option>\n<option value="kittila">Kittil\xe4</option>\n<option value="kiukainen">Kiukainen</option>\n<option value="kiuruvesi">Kiuruvesi</option>\n<option value="kivijarvi">Kivij\xe4rvi</option>\n<option value="kokemaki">Kokem\xe4ki</option>\n<option value="kokkola">Kokkola</option>\n<option value="kolari">Kolari</option>\n<option value="konnevesi">Konnevesi</option>\n<option value="kontiolahti">Kontiolahti</option>\n<option value="korpilahti">Korpilahti</option>\n<option value="korppoo">Korppoo</option>\n<option value="korsnas">Korsn\xe4s</option>\n<option value="kortesjarvi">Kortesj\xe4rvi</option>\n<option value="koskitl">KoskiTl</option>\n<option value="kotka">Kotka</option>\n<option value="kouvola">Kouvola</option>\n<option value="kristiinankaupunki">Kristiinankaupunki</option>\n<option value="kruunupyy">Kruunupyy</option>\n<option value="kuhmalahti">Kuhmalahti</option>\n<option value="kuhmo">Kuhmo</option>\n<option value="kuhmoinen">Kuhmoinen</option>\n<option value="kumlinge">Kumlinge</option>\n<option value="kuopio">Kuopio</option>\n<option value="kuortane">Kuortane</option>\n<option value="kurikka">Kurikka</option>\n<option value="kuru">Kuru</option>\n<option value="kustavi">Kustavi</option>\n<option value="kuusamo">Kuusamo</option>\n<option value="kuusankoski">Kuusankoski</option>\n<option value="kuusjoki">Kuusjoki</option>\n<option value="kylmakoski">Kylm\xe4koski</option>\n<option value="kyyjarvi">Kyyj\xe4rvi</option>\n<option value="kalvia">K\xe4lvi\xe4</option>\n<option value="karkola">K\xe4rk\xf6l\xe4</option>\n<option value="karsamaki">K\xe4rs\xe4m\xe4ki</option>\n<option value="kokar">K\xf6kar</option>\n<option value="koylio">K\xf6yli\xf6</option>\n<option value="lahti">Lahti</option>\n<option value="laihia">Laihia</option>\n<option value="laitila">Laitila</option>\n<option value="lammi">Lammi</option>\n<option value="lapinjarvi">Lapinj\xe4rvi</option>\n<option value="lapinlahti">Lapinlahti</option>\n<option value="lappajarvi">Lappaj\xe4rvi</option>\n<option value="lappeenranta">Lappeenranta</option>\n<option value="lappi">Lappi</option>\n<option value="lapua">Lapua</option>\n<option value="laukaa">Laukaa</option>\n<option value="lavia">Lavia</option>\n<option value="lehtimaki">Lehtim\xe4ki</option>\n<option value="leivonmaki">Leivonm\xe4ki</option>\n<option value="lemi">Lemi</option>\n<option value="lemland">Lemland</option>\n<option value="lempaala">Lemp\xe4\xe4l\xe4</option>\n<option value="lemu">Lemu</option>\n<option value="leppavirta">Lepp\xe4virta</option>\n<option value="lestijarvi">Lestij\xe4rvi</option>\n<option value="lieksa">Lieksa</option>\n<option value="lieto">Lieto</option>\n<option value="liljendal">Liljendal</option>\n<option value="liminka">Liminka</option>\n<option value="liperi">Liperi</option>\n<option value="lohja">Lohja</option>\n<option value="lohtaja">Lohtaja</option>\n<option value="loimaa">Loimaa</option>\n<option value="loppi">Loppi</option>\n<option value="loviisa">Loviisa</option>\n<option value="luhanka">Luhanka</option>\n<option value="lumijoki">Lumijoki</option>\n<option value="lumparland">Lumparland</option>\n<option value="luoto">Luoto</option>\n<option value="luumaki">Luum\xe4ki</option>\n<option value="luvia">Luvia</option>\n<option value="maalahti">Maalahti</option>\n<option value="maaninka">Maaninka</option>\n<option value="maarianhamina">Maarianhamina</option>\n<option value="marttila">Marttila</option>\n<option value="masku">Masku</option>\n<option value="mellila">Mellil\xe4</option>\n<option value="merijarvi">Merij\xe4rvi</option>\n<option value="merikarvia">Merikarvia</option>\n<option value="merimasku">Merimasku</option>\n<option value="miehikkala">Miehikk\xe4l\xe4</option>\n<option value="mikkeli">Mikkeli</option>\n<option value="mouhijarvi">Mouhij\xe4rvi</option>\n<option value="muhos">Muhos</option>\n<option value="multia">Multia</option>\n<option value="muonio">Muonio</option>\n<option value="mustasaari">Mustasaari</option>\n<option value="muurame">Muurame</option>\n<option value="muurla">Muurla</option>\n<option value="mynamaki">Myn\xe4m\xe4ki</option>\n<option value="myrskyla">Myrskyl\xe4</option>\n<option value="mantsala">M\xe4nts\xe4l\xe4</option>\n<option value="mantta">M\xe4ntt\xe4</option>\n<option value="mantyharju">M\xe4ntyharju</option>\n<option value="naantali">Naantali</option>\n<option value="nakkila">Nakkila</option>\n<option value="nastola">Nastola</option>\n<option value="nauvo">Nauvo</option>\n<option value="nilsia">Nilsi\xe4</option>\n<option value="nivala">Nivala</option>\n<option value="nokia">Nokia</option>\n<option value="noormarkku">Noormarkku</option>\n<option value="nousiainen">Nousiainen</option>\n<option value="nummi-pusula">Nummi-Pusula</option>\n<option value="nurmes">Nurmes</option>\n<option value="nurmijarvi">Nurmij\xe4rvi</option>\n<option value="nurmo">Nurmo</option>\n<option value="narpio">N\xe4rpi\xf6</option>\n<option value="oravainen">Oravainen</option>\n<option value="orimattila">Orimattila</option>\n<option value="oripaa">Orip\xe4\xe4</option>\n<option value="orivesi">Orivesi</option>\n<option value="oulainen">Oulainen</option>\n<option value="oulu">Oulu</option>\n<option value="oulunsalo">Oulunsalo</option>\n<option value="outokumpu">Outokumpu</option>\n<option value="padasjoki">Padasjoki</option>\n<option value="paimio">Paimio</option>\n<option value="paltamo">Paltamo</option>\n<option value="parainen">Parainen</option>\n<option value="parikkala">Parikkala</option>\n<option value="parkano">Parkano</option>\n<option value="pedersore">Peders\xf6re</option>\n<option value="pelkosenniemi">Pelkosenniemi</option>\n<option value="pello">Pello</option>\n<option value="perho">Perho</option>\n<option value="pernaja">Pernaja</option>\n<option value="pernio">Perni\xf6</option>\n<option value="pertteli">Pertteli</option>\n<option value="pertunmaa">Pertunmaa</option>\n<option value="petajavesi">Pet\xe4j\xe4vesi</option>\n<option value="pieksamaki">Pieks\xe4m\xe4ki</option>\n<option value="pielavesi">Pielavesi</option>\n<option value="pietarsaari">Pietarsaari</option>\n<option value="pihtipudas">Pihtipudas</option>\n<option value="piikkio">Piikki\xf6</option>\n<option value="piippola">Piippola</option>\n<option value="pirkkala">Pirkkala</option>\n<option value="pohja">Pohja</option>\n<option value="polvijarvi">Polvij\xe4rvi</option>\n<option value="pomarkku">Pomarkku</option>\n<option value="pori">Pori</option>\n<option value="pornainen">Pornainen</option>\n<option value="porvoo">Porvoo</option>\n<option value="posio">Posio</option>\n<option value="pudasjarvi">Pudasj\xe4rvi</option>\n<option value="pukkila">Pukkila</option>\n<option value="pulkkila">Pulkkila</option>\n<option value="punkaharju">Punkaharju</option>\n<option value="punkalaidun">Punkalaidun</option>\n<option value="puolanka">Puolanka</option>\n<option value="puumala">Puumala</option>\n<option value="pyhtaa">Pyht\xe4\xe4</option>\n<option value="pyhajoki">Pyh\xe4joki</option>\n<option value="pyhajarvi">Pyh\xe4j\xe4rvi</option>\n<option value="pyhanta">Pyh\xe4nt\xe4</option>\n<option value="pyharanta">Pyh\xe4ranta</option>\n<option value="pyhaselka">Pyh\xe4selk\xe4</option>\n<option value="pylkonmaki">Pylk\xf6nm\xe4ki</option>\n<option value="palkane">P\xe4lk\xe4ne</option>\n<option value="poytya">P\xf6yty\xe4</option>\n<option value="raahe">Raahe</option>\n<option value="raisio">Raisio</option>\n<option value="rantasalmi">Rantasalmi</option>\n<option value="rantsila">Rantsila</option>\n<option value="ranua">Ranua</option>\n<option value="rauma">Rauma</option>\n<option value="rautalampi">Rautalampi</option>\n<option value="rautavaara">Rautavaara</option>\n<option value="rautjarvi">Rautj\xe4rvi</option>\n<option value="reisjarvi">Reisj\xe4rvi</option>\n<option value="renko">Renko</option>\n<option value="riihimaki">Riihim\xe4ki</option>\n<option value="ristiina">Ristiina</option>\n<option value="ristijarvi">Ristij\xe4rvi</option>\n<option value="rovaniemi">Rovaniemi</option>\n<option value="ruokolahti">Ruokolahti</option>\n<option value="ruotsinpyhtaa">Ruotsinpyht\xe4\xe4</option>\n<option value="ruovesi">Ruovesi</option>\n<option value="rusko">Rusko</option>\n<option value="rymattyla">Rym\xe4ttyl\xe4</option>\n<option value="raakkyla">R\xe4\xe4kkyl\xe4</option>\n<option value="saarijarvi">Saarij\xe4rvi</option>\n<option value="salla">Salla</option>\n<option value="salo">Salo</option>\n<option value="saltvik">Saltvik</option>\n<option value="sammatti">Sammatti</option>\n<option value="sauvo">Sauvo</option>\n<option value="savitaipale">Savitaipale</option>\n<option value="savonlinna">Savonlinna</option>\n<option value="savonranta">Savonranta</option>\n<option value="savukoski">Savukoski</option>\n<option value="seinajoki">Sein\xe4joki</option>\n<option value="sievi">Sievi</option>\n<option value="siikainen">Siikainen</option>\n<option value="siikajoki">Siikajoki</option>\n<option value="siilinjarvi">Siilinj\xe4rvi</option>\n<option value="simo">Simo</option>\n<option value="sipoo">Sipoo</option>\n<option value="siuntio">Siuntio</option>\n<option value="sodankyla">Sodankyl\xe4</option>\n<option value="soini">Soini</option>\n<option value="somero">Somero</option>\n<option value="sonkajarvi">Sonkaj\xe4rvi</option>\n<option value="sotkamo">Sotkamo</option>\n<option value="sottunga">Sottunga</option>\n<option value="sulkava">Sulkava</option>\n<option value="sund">Sund</option>\n<option value="suomenniemi">Suomenniemi</option>\n<option value="suomusjarvi">Suomusj\xe4rvi</option>\n<option value="suomussalmi">Suomussalmi</option>\n<option value="suonenjoki">Suonenjoki</option>\n<option value="sysma">Sysm\xe4</option>\n<option value="sakyla">S\xe4kyl\xe4</option>\n<option value="sarkisalo">S\xe4rkisalo</option>\n<option value="taipalsaari">Taipalsaari</option>\n<option value="taivalkoski">Taivalkoski</option>\n<option value="taivassalo">Taivassalo</option>\n<option value="tammela">Tammela</option>\n<option value="tammisaari">Tammisaari</option>\n<option value="tampere">Tampere</option>\n<option value="tarvasjoki">Tarvasjoki</option>\n<option value="tervo">Tervo</option>\n<option value="tervola">Tervola</option>\n<option value="teuva">Teuva</option>\n<option value="tohmajarvi">Tohmaj\xe4rvi</option>\n<option value="toholampi">Toholampi</option>\n<option value="toivakka">Toivakka</option>\n<option value="tornio">Tornio</option>\n<option value="turku" selected="selected">Turku</option>\n<option value="tuulos">Tuulos</option>\n<option value="tuusniemi">Tuusniemi</option>\n<option value="tuusula">Tuusula</option>\n<option value="tyrnava">Tyrn\xe4v\xe4</option>\n<option value="toysa">T\xf6ys\xe4</option>\n<option value="ullava">Ullava</option>\n<option value="ulvila">Ulvila</option>\n<option value="urjala">Urjala</option>\n<option value="utajarvi">Utaj\xe4rvi</option>\n<option value="utsjoki">Utsjoki</option>\n<option value="uurainen">Uurainen</option>\n<option value="uusikaarlepyy">Uusikaarlepyy</option>\n<option value="uusikaupunki">Uusikaupunki</option>\n<option value="vaala">Vaala</option>\n<option value="vaasa">Vaasa</option>\n<option value="vahto">Vahto</option>\n<option value="valkeakoski">Valkeakoski</option>\n<option value="valkeala">Valkeala</option>\n<option value="valtimo">Valtimo</option>\n<option value="vammala">Vammala</option>\n<option value="vampula">Vampula</option>\n<option value="vantaa">Vantaa</option>\n<option value="varkaus">Varkaus</option>\n<option value="varpaisjarvi">Varpaisj\xe4rvi</option>\n<option value="vehmaa">Vehmaa</option>\n<option value="velkua">Velkua</option>\n<option value="vesanto">Vesanto</option>\n<option value="vesilahti">Vesilahti</option>\n<option value="veteli">Veteli</option>\n<option value="vierema">Vierem\xe4</option>\n<option value="vihanti">Vihanti</option>\n<option value="vihti">Vihti</option>\n<option value="viitasaari">Viitasaari</option>\n<option value="vilppula">Vilppula</option>\n<option value="vimpeli">Vimpeli</option>\n<option value="virolahti">Virolahti</option>\n<option value="virrat">Virrat</option>\n<option value="vardo">V\xe5rd\xf6</option>\n<option value="vahakyro">V\xe4h\xe4kyr\xf6</option>\n<option value="vastanfjard">V\xe4stanfj\xe4rd</option>\n<option value="voyri-maksamaa">V\xf6yri-Maksamaa</option>\n<option value="yliharma">Ylih\xe4rm\xe4</option>\n<option value="yli-ii">Yli-Ii</option>\n<option value="ylikiiminki">Ylikiiminki</option>\n<option value="ylistaro">Ylistaro</option>\n<option value="ylitornio">Ylitornio</option>\n<option value="ylivieska">Ylivieska</option>\n<option value="ylamaa">Yl\xe4maa</option>\n<option value="ylane">Yl\xe4ne</option>\n<option value="ylojarvi">Yl\xf6j\xe4rvi</option>\n<option value="ypaja">Yp\xe4j\xe4</option>\n<option value="aetsa">\xc4ets\xe4</option>\n<option value="ahtari">\xc4ht\xe4ri</option>\n<option value="aanekoski">\xc4\xe4nekoski</option>\n</select>' - -# FISocialSecurityNumber -############################################################## - ->>> from django.contrib.localflavor.fi.forms import FISocialSecurityNumber ->>> f = FISocialSecurityNumber() ->>> f.clean('010101-0101') -u'010101-0101' ->>> f.clean('010101+0101') -u'010101+0101' ->>> f.clean('010101A0101') -u'010101A0101' ->>> f.clean('101010-0102') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid Finnish social security number.'] ->>> f.clean('10a010-0101') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid Finnish social security number.'] ->>> f.clean('101010-0\xe401') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid Finnish social security number.'] ->>> f.clean('101010b0101') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid Finnish social security number.'] ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] - ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f = FISocialSecurityNumber(required=False) ->>> f.clean('010101-0101') -u'010101-0101' ->>> f.clean(None) -u'' ->>> f.clean('') -u'' - -# BRZipCodeField ############################################################ ->>> from django.contrib.localflavor.br.forms import BRZipCodeField ->>> f = BRZipCodeField() ->>> f.clean('12345-123') -u'12345-123' ->>> f.clean('12345_123') -Traceback (most recent call last): -... -ValidationError: [u'Enter a zip code in the format XXXXX-XXX.'] ->>> f.clean('1234-123') -Traceback (most recent call last): -... -ValidationError: [u'Enter a zip code in the format XXXXX-XXX.'] ->>> f.clean('abcde-abc') -Traceback (most recent call last): -... -ValidationError: [u'Enter a zip code in the format XXXXX-XXX.'] ->>> f.clean('12345-') -Traceback (most recent call last): -... -ValidationError: [u'Enter a zip code in the format XXXXX-XXX.'] ->>> f.clean('-123') -Traceback (most recent call last): -... -ValidationError: [u'Enter a zip code in the format XXXXX-XXX.'] ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] - ->>> f = BRZipCodeField(required=False) ->>> f.clean(None) -u'' ->>> f.clean('') -u'' ->>> f.clean('-123') -Traceback (most recent call last): -... -ValidationError: [u'Enter a zip code in the format XXXXX-XXX.'] ->>> f.clean('12345-') -Traceback (most recent call last): -... -ValidationError: [u'Enter a zip code in the format XXXXX-XXX.'] ->>> f.clean('abcde-abc') -Traceback (most recent call last): -... -ValidationError: [u'Enter a zip code in the format XXXXX-XXX.'] ->>> f.clean('1234-123') -Traceback (most recent call last): -... -ValidationError: [u'Enter a zip code in the format XXXXX-XXX.'] ->>> f.clean('12345_123') -Traceback (most recent call last): -... -ValidationError: [u'Enter a zip code in the format XXXXX-XXX.'] ->>> f.clean('12345-123') -u'12345-123' - -# BRCNPJField ############################################################ - ->>> from django.contrib.localflavor.br.forms import BRCNPJField ->>> f = BRCNPJField(required=True) ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean('12-345-678/9012-10') -Traceback (most recent call last): -... -ValidationError: [u'Invalid CNPJ number.'] ->>> f.clean('12.345.678/9012-10') -Traceback (most recent call last): -... -ValidationError: [u'Invalid CNPJ number.'] ->>> f.clean('12345678/9012-10') -Traceback (most recent call last): -... -ValidationError: [u'Invalid CNPJ number.'] ->>> f.clean('64.132.916/0001-88') -'64.132.916/0001-88' ->>> f.clean('64-132-916/0001-88') -'64-132-916/0001-88' ->>> f.clean('64132916/0001-88') -'64132916/0001-88' ->>> f.clean('64.132.916/0001-XX') -Traceback (most recent call last): -... -ValidationError: [u'This field requires only numbers.'] ->>> f = BRCNPJField(required=False) ->>> f.clean('') -u'' - -# BRCPFField ################################################################# - ->>> from django.contrib.localflavor.br.forms import BRCPFField ->>> f = BRCPFField() ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean('489.294.654-54') -Traceback (most recent call last): -... -ValidationError: [u'Invalid CPF number.'] ->>> f.clean('295.669.575-98') -Traceback (most recent call last): -... -ValidationError: [u'Invalid CPF number.'] ->>> f.clean('539.315.127-22') -Traceback (most recent call last): -... -ValidationError: [u'Invalid CPF number.'] ->>> f.clean('663.256.017-26') -u'663.256.017-26' ->>> f.clean('66325601726') -u'66325601726' ->>> f.clean('375.788.573-20') -u'375.788.573-20' ->>> f.clean('84828509895') -u'84828509895' ->>> f.clean('375.788.573-XX') -Traceback (most recent call last): -... -ValidationError: [u'This field requires only numbers.'] ->>> f.clean('375.788.573-000') -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value has at most 14 characters (it has 15).'] ->>> f.clean('123.456.78') -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value has at least 11 characters (it has 10).'] ->>> f.clean('123456789555') -Traceback (most recent call last): -... -ValidationError: [u'This field requires at most 11 digits or 14 characters.'] ->>> f = BRCPFField(required=False) ->>> f.clean('') -u'' ->>> f.clean(None) -u'' - -# BRPhoneNumberField ######################################################### - ->>> from django.contrib.localflavor.br.forms import BRPhoneNumberField ->>> f = BRPhoneNumberField() ->>> f.clean('41-3562-3464') -u'41-3562-3464' ->>> f.clean('4135623464') -u'41-3562-3464' ->>> f.clean('41 3562-3464') -u'41-3562-3464' ->>> f.clean('41 3562 3464') -u'41-3562-3464' ->>> f.clean('(41) 3562 3464') -u'41-3562-3464' ->>> f.clean('41.3562.3464') -u'41-3562-3464' ->>> f.clean('41.3562-3464') -u'41-3562-3464' ->>> f.clean(' (41) 3562.3464') -u'41-3562-3464' ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] - ->>> f = BRPhoneNumberField(required=False) ->>> f.clean('') -u'' ->>> f.clean(None) -u'' ->>> f.clean(' (41) 3562.3464') -u'41-3562-3464' ->>> f.clean('41.3562-3464') -u'41-3562-3464' ->>> f.clean('(41) 3562 3464') -u'41-3562-3464' ->>> f.clean('4135623464') -u'41-3562-3464' ->>> f.clean('41 3562-3464') -u'41-3562-3464' - -# BRStateSelect ############################################################## - ->>> from django.contrib.localflavor.br.forms import BRStateSelect ->>> w = BRStateSelect() ->>> w.render('states', 'PR') -u'<select name="states">\n<option value="AC">Acre</option>\n<option value="AL">Alagoas</option>\n<option value="AP">Amap\xe1</option>\n<option value="AM">Amazonas</option>\n<option value="BA">Bahia</option>\n<option value="CE">Cear\xe1</option>\n<option value="DF">Distrito Federal</option>\n<option value="ES">Esp\xedrito Santo</option>\n<option value="GO">Goi\xe1s</option>\n<option value="MA">Maranh\xe3o</option>\n<option value="MT">Mato Grosso</option>\n<option value="MS">Mato Grosso do Sul</option>\n<option value="MG">Minas Gerais</option>\n<option value="PA">Par\xe1</option>\n<option value="PB">Para\xedba</option>\n<option value="PR" selected="selected">Paran\xe1</option>\n<option value="PE">Pernambuco</option>\n<option value="PI">Piau\xed</option>\n<option value="RJ">Rio de Janeiro</option>\n<option value="RN">Rio Grande do Norte</option>\n<option value="RS">Rio Grande do Sul</option>\n<option value="RO">Rond\xf4nia</option>\n<option value="RR">Roraima</option>\n<option value="SC">Santa Catarina</option>\n<option value="SP">S\xe3o Paulo</option>\n<option value="SE">Sergipe</option>\n<option value="TO">Tocantins</option>\n</select>' - -# DEZipCodeField ############################################################## - ->>> from django.contrib.localflavor.de.forms import DEZipCodeField ->>> f = DEZipCodeField() ->>> f.clean('99423') -u'99423' ->>> f.clean(' 99423') -Traceback (most recent call last): -... -ValidationError: [u'Enter a zip code in the format XXXXX.'] - -# DEStateSelect ############################################################# - ->>> from django.contrib.localflavor.de.forms import DEStateSelect ->>> w = DEStateSelect() ->>> w.render('states', 'TH') -u'<select name="states">\n<option value="BW">Baden-Wuerttemberg</option>\n<option value="BY">Bavaria</option>\n<option value="BE">Berlin</option>\n<option value="BB">Brandenburg</option>\n<option value="HB">Bremen</option>\n<option value="HH">Hamburg</option>\n<option value="HE">Hessen</option>\n<option value="MV">Mecklenburg-Western Pomerania</option>\n<option value="NI">Lower Saxony</option>\n<option value="NW">North Rhine-Westphalia</option>\n<option value="RP">Rhineland-Palatinate</option>\n<option value="SL">Saarland</option>\n<option value="SN">Saxony</option>\n<option value="ST">Saxony-Anhalt</option>\n<option value="SH">Schleswig-Holstein</option>\n<option value="TH" selected="selected">Thuringia</option>\n</select>' - -# DEIdentityCardNumberField ################################################# - ->>> from django.contrib.localflavor.de.forms import DEIdentityCardNumberField ->>> f = DEIdentityCardNumberField() ->>> f.clean('7549313035D-6004103-0903042-0') -u'7549313035D-6004103-0903042-0' ->>> f.clean('9786324830D 6104243 0910271 2') -u'9786324830D-6104243-0910271-2' ->>> f.clean('0434657485D-6407276-0508137-9') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid German identity card number in XXXXXXXXXXX-XXXXXXX-XXXXXXX-X format.'] - -# CHZipCodeField ############################################################ - ->>> from django.contrib.localflavor.ch.forms import CHZipCodeField ->>> f = CHZipCodeField() ->>> f.clean('800x') -Traceback (most recent call last): -... -ValidationError: [u'Enter a zip code in the format XXXX.'] ->>> f.clean('80 00') -Traceback (most recent call last): -... -ValidationError: [u'Enter a zip code in the format XXXX.'] ->>> f.clean('8000') -u'8000' - -# CHPhoneNumberField ######################################################## - ->>> from django.contrib.localflavor.ch.forms import CHPhoneNumberField ->>> f = CHPhoneNumberField() ->>> f.clean('01234567890') -Traceback (most recent call last): -... -ValidationError: [u'Phone numbers must be in 0XX XXX XX XX format.'] ->>> f.clean('1234567890') -Traceback (most recent call last): -... -ValidationError: [u'Phone numbers must be in 0XX XXX XX XX format.'] ->>> f.clean('0123456789') -u'012 345 67 89' - -# CHIdentityCardNumberField ################################################# - ->>> from django.contrib.localflavor.ch.forms import CHIdentityCardNumberField ->>> f = CHIdentityCardNumberField() ->>> f.clean('C1234567<0') -u'C1234567<0' ->>> f.clean('C1234567<1') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid Swiss identity or passport card number in X1234567<0 or 1234567890 format.'] ->>> f.clean('2123456700') -u'2123456700' ->>> f.clean('2123456701') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid Swiss identity or passport card number in X1234567<0 or 1234567890 format.'] - -# CHStateSelect ############################################################# - ->>> from django.contrib.localflavor.ch.forms import CHStateSelect ->>> w = CHStateSelect() ->>> w.render('state', 'AG') -u'<select name="state">\n<option value="AG" selected="selected">Aargau</option>\n<option value="AI">Appenzell Innerrhoden</option>\n<option value="AR">Appenzell Ausserrhoden</option>\n<option value="BS">Basel-Stadt</option>\n<option value="BL">Basel-Land</option>\n<option value="BE">Berne</option>\n<option value="FR">Fribourg</option>\n<option value="GE">Geneva</option>\n<option value="GL">Glarus</option>\n<option value="GR">Graubuenden</option>\n<option value="JU">Jura</option>\n<option value="LU">Lucerne</option>\n<option value="NE">Neuchatel</option>\n<option value="NW">Nidwalden</option>\n<option value="OW">Obwalden</option>\n<option value="SH">Schaffhausen</option>\n<option value="SZ">Schwyz</option>\n<option value="SO">Solothurn</option>\n<option value="SG">St. Gallen</option>\n<option value="TG">Thurgau</option>\n<option value="TI">Ticino</option>\n<option value="UR">Uri</option>\n<option value="VS">Valais</option>\n<option value="VD">Vaud</option>\n<option value="ZG">Zug</option>\n<option value="ZH">Zurich</option>\n</select>' - -## AUPostCodeField ########################################################## - -A field that accepts a four digit Australian post code. - ->>> from django.contrib.localflavor.au.forms import AUPostCodeField ->>> f = AUPostCodeField() ->>> f.clean('1234') -u'1234' ->>> f.clean('2000') -u'2000' ->>> f.clean('abcd') -Traceback (most recent call last): -... -ValidationError: [u'Enter a 4 digit post code.'] ->>> f.clean('20001') -Traceback (most recent call last): -... -ValidationError: [u'Enter a 4 digit post code.'] ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] - ->>> f = AUPostCodeField(required=False) ->>> f.clean('1234') -u'1234' ->>> f.clean('2000') -u'2000' ->>> f.clean('abcd') -Traceback (most recent call last): -... -ValidationError: [u'Enter a 4 digit post code.'] ->>> f.clean('20001') -Traceback (most recent call last): -... -ValidationError: [u'Enter a 4 digit post code.'] ->>> f.clean(None) -u'' ->>> f.clean('') -u'' - -## AUPhoneNumberField ######################################################## - -A field that accepts a 10 digit Australian phone number. -llows spaces and parentheses around area code. - ->>> from django.contrib.localflavor.au.forms import AUPhoneNumberField ->>> f = AUPhoneNumberField() ->>> f.clean('1234567890') -u'1234567890' ->>> f.clean('0213456789') -u'0213456789' ->>> f.clean('02 13 45 67 89') -u'0213456789' ->>> f.clean('(02) 1345 6789') -u'0213456789' ->>> f.clean('(02) 1345-6789') -u'0213456789' ->>> f.clean('(02)1345-6789') -u'0213456789' ->>> f.clean('0408 123 456') -u'0408123456' ->>> f.clean('123') -Traceback (most recent call last): -... -ValidationError: [u'Phone numbers must contain 10 digits.'] ->>> f.clean('1800DJANGO') -Traceback (most recent call last): -... -ValidationError: [u'Phone numbers must contain 10 digits.'] ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] - ->>> f = AUPhoneNumberField(required=False) ->>> f.clean('1234567890') -u'1234567890' ->>> f.clean('0213456789') -u'0213456789' ->>> f.clean('02 13 45 67 89') -u'0213456789' ->>> f.clean('(02) 1345 6789') -u'0213456789' ->>> f.clean('(02) 1345-6789') -u'0213456789' ->>> f.clean('(02)1345-6789') -u'0213456789' ->>> f.clean('0408 123 456') -u'0408123456' ->>> f.clean('123') -Traceback (most recent call last): -... -ValidationError: [u'Phone numbers must contain 10 digits.'] ->>> f.clean('1800DJANGO') -Traceback (most recent call last): -... -ValidationError: [u'Phone numbers must contain 10 digits.'] ->>> f.clean(None) -u'' ->>> f.clean('') -u'' - -## AUStateSelect ############################################################# - -AUStateSelect is a Select widget that uses a list of Australian -states/territories as its choices. - ->>> from django.contrib.localflavor.au.forms import AUStateSelect ->>> f = AUStateSelect() ->>> print f.render('state', 'NSW') -<select name="state"> -<option value="ACT">Australian Capital Territory</option> -<option value="NSW" selected="selected">New South Wales</option> -<option value="NT">Northern Territory</option> -<option value="QLD">Queensland</option> -<option value="SA">South Australia</option> -<option value="TAS">Tasmania</option> -<option value="VIC">Victoria</option> -<option value="WA">Western Australia</option> -</select> - -## ISIdNumberField ############################################################# - ->>> from django.contrib.localflavor.is_.forms import * ->>> f = ISIdNumberField() ->>> f.clean('2308803449') -u'230880-3449' ->>> f.clean('230880-3449') -u'230880-3449' ->>> f.clean('230880 3449') -u'230880-3449' ->>> f.clean('230880343') -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value has at least 10 characters (it has 9).'] ->>> f.clean('230880343234') -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value has at most 11 characters (it has 12).'] ->>> f.clean('abcdefghijk') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid Icelandic identification number. The format is XXXXXX-XXXX.'] ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean('2308803439') -Traceback (most recent call last): -... -ValidationError: [u'The Icelandic identification number is not valid.'] ->>> f.clean('2308803440') -u'230880-3440' ->>> f = ISIdNumberField(required=False) ->>> f.clean(None) -u'' ->>> f.clean('') -u'' - -## ISPhoneNumberField ############################################################# - ->>> from django.contrib.localflavor.is_.forms import * ->>> f = ISPhoneNumberField() ->>> f.clean('1234567') -u'1234567' ->>> f.clean('123 4567') -u'1234567' ->>> f.clean('123-4567') -u'1234567' ->>> f.clean('123-456') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid value.'] ->>> f.clean('123456') -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value has at least 7 characters (it has 6).'] ->>> f.clean('123456555') -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value has at most 8 characters (it has 9).'] ->>> f.clean('abcdefg') -Traceback (most recent call last): -ValidationError: [u'Enter a valid value.'] ->>> f.clean(' 1234567 ') -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value has at most 8 characters (it has 9).'] ->>> f.clean(' 12367 ') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid value.'] - ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f = ISPhoneNumberField(required=False) ->>> f.clean(None) -u'' ->>> f.clean('') -u'' - -## ISPostalCodeSelect ############################################################# - ->>> from django.contrib.localflavor.is_.forms import * ->>> f = ISPostalCodeSelect() - ->>> f.render('foo', 'bar') -u'<select name="foo">\n<option value="101">101 Reykjav\xedk</option>\n<option value="103">103 Reykjav\xedk</option>\n<option value="104">104 Reykjav\xedk</option>\n<option value="105">105 Reykjav\xedk</option>\n<option value="107">107 Reykjav\xedk</option>\n<option value="108">108 Reykjav\xedk</option>\n<option value="109">109 Reykjav\xedk</option>\n<option value="110">110 Reykjav\xedk</option>\n<option value="111">111 Reykjav\xedk</option>\n<option value="112">112 Reykjav\xedk</option>\n<option value="113">113 Reykjav\xedk</option>\n<option value="116">116 Kjalarnes</option>\n<option value="121">121 Reykjav\xedk</option>\n<option value="123">123 Reykjav\xedk</option>\n<option value="124">124 Reykjav\xedk</option>\n<option value="125">125 Reykjav\xedk</option>\n<option value="127">127 Reykjav\xedk</option>\n<option value="128">128 Reykjav\xedk</option>\n<option value="129">129 Reykjav\xedk</option>\n<option value="130">130 Reykjav\xedk</option>\n<option value="132">132 Reykjav\xedk</option>\n<option value="150">150 Reykjav\xedk</option>\n<option value="155">155 Reykjav\xedk</option>\n<option value="170">170 Seltjarnarnes</option>\n<option value="172">172 Seltjarnarnes</option>\n<option value="190">190 Vogar</option>\n<option value="200">200 K\xf3pavogur</option>\n<option value="201">201 K\xf3pavogur</option>\n<option value="202">202 K\xf3pavogur</option>\n<option value="203">203 K\xf3pavogur</option>\n<option value="210">210 Gar\xf0ab\xe6r</option>\n<option value="212">212 Gar\xf0ab\xe6r</option>\n<option value="220">220 Hafnarfj\xf6r\xf0ur</option>\n<option value="221">221 Hafnarfj\xf6r\xf0ur</option>\n<option value="222">222 Hafnarfj\xf6r\xf0ur</option>\n<option value="225">225 \xc1lftanes</option>\n<option value="230">230 Reykjanesb\xe6r</option>\n<option value="232">232 Reykjanesb\xe6r</option>\n<option value="233">233 Reykjanesb\xe6r</option>\n<option value="235">235 Keflav\xedkurflugv\xf6llur</option>\n<option value="240">240 Grindav\xedk</option>\n<option value="245">245 Sandger\xf0i</option>\n<option value="250">250 Gar\xf0ur</option>\n<option value="260">260 Reykjanesb\xe6r</option>\n<option value="270">270 Mosfellsb\xe6r</option>\n<option value="300">300 Akranes</option>\n<option value="301">301 Akranes</option>\n<option value="302">302 Akranes</option>\n<option value="310">310 Borgarnes</option>\n<option value="311">311 Borgarnes</option>\n<option value="320">320 Reykholt \xed Borgarfir\xf0i</option>\n<option value="340">340 Stykkish\xf3lmur</option>\n<option value="345">345 Flatey \xe1 Brei\xf0afir\xf0i</option>\n<option value="350">350 Grundarfj\xf6r\xf0ur</option>\n<option value="355">355 \xd3lafsv\xedk</option>\n<option value="356">356 Sn\xe6fellsb\xe6r</option>\n<option value="360">360 Hellissandur</option>\n<option value="370">370 B\xfa\xf0ardalur</option>\n<option value="371">371 B\xfa\xf0ardalur</option>\n<option value="380">380 Reykh\xf3lahreppur</option>\n<option value="400">400 \xcdsafj\xf6r\xf0ur</option>\n<option value="401">401 \xcdsafj\xf6r\xf0ur</option>\n<option value="410">410 Hn\xedfsdalur</option>\n<option value="415">415 Bolungarv\xedk</option>\n<option value="420">420 S\xfa\xf0av\xedk</option>\n<option value="425">425 Flateyri</option>\n<option value="430">430 Su\xf0ureyri</option>\n<option value="450">450 Patreksfj\xf6r\xf0ur</option>\n<option value="451">451 Patreksfj\xf6r\xf0ur</option>\n<option value="460">460 T\xe1lknafj\xf6r\xf0ur</option>\n<option value="465">465 B\xedldudalur</option>\n<option value="470">470 \xdeingeyri</option>\n<option value="471">471 \xdeingeyri</option>\n<option value="500">500 Sta\xf0ur</option>\n<option value="510">510 H\xf3lmav\xedk</option>\n<option value="512">512 H\xf3lmav\xedk</option>\n<option value="520">520 Drangsnes</option>\n<option value="522">522 Kj\xf6rvogur</option>\n<option value="523">523 B\xe6r</option>\n<option value="524">524 Nor\xf0urfj\xf6r\xf0ur</option>\n<option value="530">530 Hvammstangi</option>\n<option value="531">531 Hvammstangi</option>\n<option value="540">540 Bl\xf6ndu\xf3s</option>\n<option value="541">541 Bl\xf6ndu\xf3s</option>\n<option value="545">545 Skagastr\xf6nd</option>\n<option value="550">550 Sau\xf0\xe1rkr\xf3kur</option>\n<option value="551">551 Sau\xf0\xe1rkr\xf3kur</option>\n<option value="560">560 Varmahl\xed\xf0</option>\n<option value="565">565 Hofs\xf3s</option>\n<option value="566">566 Hofs\xf3s</option>\n<option value="570">570 Flj\xf3t</option>\n<option value="580">580 Siglufj\xf6r\xf0ur</option>\n<option value="600">600 Akureyri</option>\n<option value="601">601 Akureyri</option>\n<option value="602">602 Akureyri</option>\n<option value="603">603 Akureyri</option>\n<option value="610">610 Greniv\xedk</option>\n<option value="611">611 Gr\xedmsey</option>\n<option value="620">620 Dalv\xedk</option>\n<option value="621">621 Dalv\xedk</option>\n<option value="625">625 \xd3lafsfj\xf6r\xf0ur</option>\n<option value="630">630 Hr\xedsey</option>\n<option value="640">640 H\xfasav\xedk</option>\n<option value="641">641 H\xfasav\xedk</option>\n<option value="645">645 Fossh\xf3ll</option>\n<option value="650">650 Laugar</option>\n<option value="660">660 M\xfdvatn</option>\n<option value="670">670 K\xf3pasker</option>\n<option value="671">671 K\xf3pasker</option>\n<option value="675">675 Raufarh\xf6fn</option>\n<option value="680">680 \xde\xf3rsh\xf6fn</option>\n<option value="681">681 \xde\xf3rsh\xf6fn</option>\n<option value="685">685 Bakkafj\xf6r\xf0ur</option>\n<option value="690">690 Vopnafj\xf6r\xf0ur</option>\n<option value="700">700 Egilssta\xf0ir</option>\n<option value="701">701 Egilssta\xf0ir</option>\n<option value="710">710 Sey\xf0isfj\xf6r\xf0ur</option>\n<option value="715">715 Mj\xf3ifj\xf6r\xf0ur</option>\n<option value="720">720 Borgarfj\xf6r\xf0ur eystri</option>\n<option value="730">730 Rey\xf0arfj\xf6r\xf0ur</option>\n<option value="735">735 Eskifj\xf6r\xf0ur</option>\n<option value="740">740 Neskaupsta\xf0ur</option>\n<option value="750">750 F\xe1skr\xfa\xf0sfj\xf6r\xf0ur</option>\n<option value="755">755 St\xf6\xf0varfj\xf6r\xf0ur</option>\n<option value="760">760 Brei\xf0dalsv\xedk</option>\n<option value="765">765 Dj\xfapivogur</option>\n<option value="780">780 H\xf6fn \xed Hornafir\xf0i</option>\n<option value="781">781 H\xf6fn \xed Hornafir\xf0i</option>\n<option value="785">785 \xd6r\xe6fi</option>\n<option value="800">800 Selfoss</option>\n<option value="801">801 Selfoss</option>\n<option value="802">802 Selfoss</option>\n<option value="810">810 Hverager\xf0i</option>\n<option value="815">815 \xdeorl\xe1ksh\xf6fn</option>\n<option value="820">820 Eyrarbakki</option>\n<option value="825">825 Stokkseyri</option>\n<option value="840">840 Laugarvatn</option>\n<option value="845">845 Fl\xfa\xf0ir</option>\n<option value="850">850 Hella</option>\n<option value="851">851 Hella</option>\n<option value="860">860 Hvolsv\xf6llur</option>\n<option value="861">861 Hvolsv\xf6llur</option>\n<option value="870">870 V\xedk</option>\n<option value="871">871 V\xedk</option>\n<option value="880">880 Kirkjub\xe6jarklaustur</option>\n<option value="900">900 Vestmannaeyjar</option>\n<option value="902">902 Vestmannaeyjar</option>\n</select>' - -## CLRutField ############################################################# - -CLRutField is a Field that checks the validity of the Chilean -personal identification number (RUT). It has two modes relaxed (default) and -strict. - ->>> from django.contrib.localflavor.cl.forms import CLRutField ->>> rut = CLRutField() - ->>> rut.clean('11-6') -u'11-6' ->>> rut.clean('116') -u'11-6' - -# valid format, bad verifier. ->>> rut.clean('11.111.111-0') -Traceback (most recent call last): -... -ValidationError: [u'The Chilean RUT is not valid.'] ->>> rut.clean('111') -Traceback (most recent call last): -... -ValidationError: [u'The Chilean RUT is not valid.'] - ->>> rut.clean('767484100') -u'76.748.410-0' ->>> rut.clean('78.412.790-7') -u'78.412.790-7' ->>> rut.clean('8.334.6043') -u'8.334.604-3' ->>> rut.clean('76793310-K') -u'76.793.310-K' - -Strict RUT usage (does not allow imposible values) ->>> rut = CLRutField(strict=True) - ->>> rut.clean('11-6') -Traceback (most recent call last): -... -ValidationError: [u'Enter valid a Chilean RUT. The format is XX.XXX.XXX-X.'] - -# valid format, bad verifier. ->>> rut.clean('11.111.111-0') -Traceback (most recent call last): -... -ValidationError: [u'The Chilean RUT is not valid.'] - -# Correct input, invalid format. ->>> rut.clean('767484100') -Traceback (most recent call last): -... -ValidationError: [u'Enter valid a Chilean RUT. The format is XX.XXX.XXX-X.'] ->>> rut.clean('78.412.790-7') -u'78.412.790-7' ->>> rut.clean('8.334.6043') -Traceback (most recent call last): -... -ValidationError: [u'Enter valid a Chilean RUT. The format is XX.XXX.XXX-X.'] ->>> rut.clean('76793310-K') -Traceback (most recent call last): -... -ValidationError: [u'Enter valid a Chilean RUT. The format is XX.XXX.XXX-X.'] - -## CLRegionSelect ######################################################### ->>> from django.contrib.localflavor.cl.forms import CLRegionSelect ->>> f = CLRegionSelect() - ->>> f.render('foo', 'bar') -u'<select name="foo">\n<option value="RM">Regi\xf3n Metropolitana de Santiago</option>\n<option value="I">Regi\xf3n de Tarapac\xe1</option>\n<option value="II">Regi\xf3n de Antofagasta</option>\n<option value="III">Regi\xf3n de Atacama</option>\n<option value="IV">Regi\xf3n de Coquimbo</option>\n<option value="V">Regi\xf3n de Valpara\xedso</option>\n<option value="VI">Regi\xf3n del Libertador Bernardo O'Higgins</option>\n<option value="VII">Regi\xf3n del Maule</option>\n<option value="VIII">Regi\xf3n del B\xedo B\xedo</option>\n<option value="IX">Regi\xf3n de la Araucan\xeda</option>\n<option value="X">Regi\xf3n de los Lagos</option>\n<option value="XI">Regi\xf3n de Ays\xe9n del General Carlos Ib\xe1\xf1ez del Campo</option>\n<option value="XII">Regi\xf3n de Magallanes y la Ant\xe1rtica Chilena</option>\n<option value="XIV">Regi\xf3n de Los R\xedos</option>\n<option value="XV">Regi\xf3n de Arica-Parinacota</option>\n</select>' - -# SKPostalCodeField ######################################################### - ->>> from django.contrib.localflavor.sk.forms import SKPostalCodeField ->>> f = SKPostalCodeField() ->>> f.clean('84545x') -Traceback (most recent call last): -... -ValidationError: [u'Enter a postal code in the format XXXXX or XXX XX.'] ->>> f.clean('91909') -u'91909' ->>> f.clean('917 01') -u'91701' - -# SKRegionSelect ############################################################ - ->>> from django.contrib.localflavor.sk.forms import SKRegionSelect ->>> w = SKRegionSelect() ->>> w.render('regions', 'TT') -u'<select name="regions">\n<option value="BB">Banska Bystrica region</option>\n<option value="BA">Bratislava region</option>\n<option value="KE">Kosice region</option>\n<option value="NR">Nitra region</option>\n<option value="PO">Presov region</option>\n<option value="TN">Trencin region</option>\n<option value="TT" selected="selected">Trnava region</option>\n<option value="ZA">Zilina region</option>\n</select>' - -# SKDistrictSelect ########################################################## - ->>> from django.contrib.localflavor.sk.forms import SKDistrictSelect ->>> w = SKDistrictSelect() ->>> w.render('Districts', 'RK') -u'<select name="Districts">\n<option value="BB">Banska Bystrica</option>\n<option value="BS">Banska Stiavnica</option>\n<option value="BJ">Bardejov</option>\n<option value="BN">Banovce nad Bebravou</option>\n<option value="BR">Brezno</option>\n<option value="BA1">Bratislava I</option>\n<option value="BA2">Bratislava II</option>\n<option value="BA3">Bratislava III</option>\n<option value="BA4">Bratislava IV</option>\n<option value="BA5">Bratislava V</option>\n<option value="BY">Bytca</option>\n<option value="CA">Cadca</option>\n<option value="DT">Detva</option>\n<option value="DK">Dolny Kubin</option>\n<option value="DS">Dunajska Streda</option>\n<option value="GA">Galanta</option>\n<option value="GL">Gelnica</option>\n<option value="HC">Hlohovec</option>\n<option value="HE">Humenne</option>\n<option value="IL">Ilava</option>\n<option value="KK">Kezmarok</option>\n<option value="KN">Komarno</option>\n<option value="KE1">Kosice I</option>\n<option value="KE2">Kosice II</option>\n<option value="KE3">Kosice III</option>\n<option value="KE4">Kosice IV</option>\n<option value="KEO">Kosice - okolie</option>\n<option value="KA">Krupina</option>\n<option value="KM">Kysucke Nove Mesto</option>\n<option value="LV">Levice</option>\n<option value="LE">Levoca</option>\n<option value="LM">Liptovsky Mikulas</option>\n<option value="LC">Lucenec</option>\n<option value="MA">Malacky</option>\n<option value="MT">Martin</option>\n<option value="ML">Medzilaborce</option>\n<option value="MI">Michalovce</option>\n<option value="MY">Myjava</option>\n<option value="NO">Namestovo</option>\n<option value="NR">Nitra</option>\n<option value="NM">Nove Mesto nad Vahom</option>\n<option value="NZ">Nove Zamky</option>\n<option value="PE">Partizanske</option>\n<option value="PK">Pezinok</option>\n<option value="PN">Piestany</option>\n<option value="PT">Poltar</option>\n<option value="PP">Poprad</option>\n<option value="PB">Povazska Bystrica</option>\n<option value="PO">Presov</option>\n<option value="PD">Prievidza</option>\n<option value="PU">Puchov</option>\n<option value="RA">Revuca</option>\n<option value="RS">Rimavska Sobota</option>\n<option value="RV">Roznava</option>\n<option value="RK" selected="selected">Ruzomberok</option>\n<option value="SB">Sabinov</option>\n<option value="SC">Senec</option>\n<option value="SE">Senica</option>\n<option value="SI">Skalica</option>\n<option value="SV">Snina</option>\n<option value="SO">Sobrance</option>\n<option value="SN">Spisska Nova Ves</option>\n<option value="SL">Stara Lubovna</option>\n<option value="SP">Stropkov</option>\n<option value="SK">Svidnik</option>\n<option value="SA">Sala</option>\n<option value="TO">Topolcany</option>\n<option value="TV">Trebisov</option>\n<option value="TN">Trencin</option>\n<option value="TT">Trnava</option>\n<option value="TR">Turcianske Teplice</option>\n<option value="TS">Tvrdosin</option>\n<option value="VK">Velky Krtis</option>\n<option value="VT">Vranov nad Toplou</option>\n<option value="ZM">Zlate Moravce</option>\n<option value="ZV">Zvolen</option>\n<option value="ZC">Zarnovica</option>\n<option value="ZH">Ziar nad Hronom</option>\n<option value="ZA">Zilina</option>\n</select>' - -# PLVoivodeshipSelect ########################################################## - ->>> from django.contrib.localflavor.pl.forms import PLVoivodeshipSelect ->>> f = PLVoivodeshipSelect() ->>> f.render('voivodeships','pomerania') -u'<select name="voivodeships">\n<option value="lower_silesia">Lower Silesia</option>\n<option value="kuyavia-pomerania">Kuyavia-Pomerania</option>\n<option value="lublin">Lublin</option>\n<option value="lubusz">Lubusz</option>\n<option value="lodz">Lodz</option>\n<option value="lesser_poland">Lesser Poland</option>\n<option value="masovia">Masovia</option>\n<option value="opole">Opole</option>\n<option value="subcarpatia">Subcarpatia</option>\n<option value="podlasie">Podlasie</option>\n<option value="pomerania" selected="selected">Pomerania</option>\n<option value="silesia">Silesia</option>\n<option value="swietokrzyskie">Swietokrzyskie</option>\n<option value="warmia-masuria">Warmia-Masuria</option>\n<option value="greater_poland">Greater Poland</option>\n<option value="west_pomerania">West Pomerania</option>\n</select>' - -# PLAdministrativeUnitSelect ########################################################## - ->>> from django.contrib.localflavor.pl.forms import PLAdministrativeUnitSelect ->>> f = PLAdministrativeUnitSelect() ->>> f.render('administrativeunit','katowice') -u'<select name="administrativeunit">\n<option value="wroclaw">Wroc\u0142aw</option>\n<option value="jeleniagora">Jelenia G\xf3ra</option>\n<option value="legnica">Legnica</option>\n<option value="boleslawiecki">boles\u0142awiecki</option>\n<option value="dzierzoniowski">dzier\u017coniowski</option>\n<option value="glogowski">g\u0142ogowski</option>\n<option value="gorowski">g\xf3rowski</option>\n<option value="jaworski">jaworski</option>\n<option value="jeleniogorski">jeleniog\xf3rski</option>\n<option value="kamiennogorski">kamiennog\xf3rski</option>\n<option value="klodzki">k\u0142odzki</option>\n<option value="legnicki">legnicki</option>\n<option value="lubanski">luba\u0144ski</option>\n<option value="lubinski">lubi\u0144ski</option>\n<option value="lwowecki">lw\xf3wecki</option>\n<option value="milicki">milicki</option>\n<option value="olesnicki">ole\u015bnicki</option>\n<option value="olawski">o\u0142awski</option>\n<option value="polkowicki">polkowicki</option>\n<option value="strzelinski">strzeli\u0144ski</option>\n<option value="sredzki">\u015bredzki</option>\n<option value="swidnicki">\u015bwidnicki</option>\n<option value="trzebnicki">trzebnicki</option>\n<option value="walbrzyski">wa\u0142brzyski</option>\n<option value="wolowski">wo\u0142owski</option>\n<option value="wroclawski">wroc\u0142awski</option>\n<option value="zabkowicki">z\u0105bkowicki</option>\n<option value="zgorzelecki">zgorzelecki</option>\n<option value="zlotoryjski">z\u0142otoryjski</option>\n<option value="bydgoszcz">Bydgoszcz</option>\n<option value="torun">Toru\u0144</option>\n<option value="wloclawek">W\u0142oc\u0142awek</option>\n<option value="grudziadz">Grudzi\u0105dz</option>\n<option value="aleksandrowski">aleksandrowski</option>\n<option value="brodnicki">brodnicki</option>\n<option value="bydgoski">bydgoski</option>\n<option value="chelminski">che\u0142mi\u0144ski</option>\n<option value="golubsko-dobrzynski">golubsko-dobrzy\u0144ski</option>\n<option value="grudziadzki">grudzi\u0105dzki</option>\n<option value="inowroclawski">inowroc\u0142awski</option>\n<option value="lipnowski">lipnowski</option>\n<option value="mogilenski">mogile\u0144ski</option>\n<option value="nakielski">nakielski</option>\n<option value="radziejowski">radziejowski</option>\n<option value="rypinski">rypi\u0144ski</option>\n<option value="sepolenski">s\u0119pole\u0144ski</option>\n<option value="swiecki">\u015bwiecki</option>\n<option value="torunski">toru\u0144ski</option>\n<option value="tucholski">tucholski</option>\n<option value="wabrzeski">w\u0105brzeski</option>\n<option value="wloclawski">wroc\u0142awski</option>\n<option value="zninski">\u017ani\u0144ski</option>\n<option value="lublin">Lublin</option>\n<option value="biala-podlaska">Bia\u0142a Podlaska</option>\n<option value="chelm">Che\u0142m</option>\n<option value="zamosc">Zamo\u015b\u0107</option>\n<option value="bialski">bialski</option>\n<option value="bilgorajski">bi\u0142gorajski</option>\n<option value="chelmski">che\u0142mski</option>\n<option value="hrubieszowski">hrubieszowski</option>\n<option value="janowski">janowski</option>\n<option value="krasnostawski">krasnostawski</option>\n<option value="krasnicki">kra\u015bnicki</option>\n<option value="lubartowski">lubartowski</option>\n<option value="lubelski">lubelski</option>\n<option value="leczynski">\u0142\u0119czy\u0144ski</option>\n<option value="lukowski">\u0142ukowski</option>\n<option value="opolski">opolski</option>\n<option value="parczewski">parczewski</option>\n<option value="pulawski">pu\u0142awski</option>\n<option value="radzynski">radzy\u0144ski</option>\n<option value="rycki">rycki</option>\n<option value="swidnicki">\u015bwidnicki</option>\n<option value="tomaszowski">tomaszowski</option>\n<option value="wlodawski">w\u0142odawski</option>\n<option value="zamojski">zamojski</option>\n<option value="gorzow-wielkopolski">Gorz\xf3w Wielkopolski</option>\n<option value="zielona-gora">Zielona G\xf3ra</option>\n<option value="gorzowski">gorzowski</option>\n<option value="krosnienski">kro\u015bnie\u0144ski</option>\n<option value="miedzyrzecki">mi\u0119dzyrzecki</option>\n<option value="nowosolski">nowosolski</option>\n<option value="slubicki">s\u0142ubicki</option>\n<option value="strzelecko-drezdenecki">strzelecko-drezdenecki</option>\n<option value="sulecinski">sule\u0144ci\u0144ski</option>\n<option value="swiebodzinski">\u015bwiebodzi\u0144ski</option>\n<option value="wschowski">wschowski</option>\n<option value="zielonogorski">zielonog\xf3rski</option>\n<option value="zaganski">\u017caga\u0144ski</option>\n<option value="zarski">\u017carski</option>\n<option value="lodz">\u0141\xf3d\u017a</option>\n<option value="piotrkow-trybunalski">Piotrk\xf3w Trybunalski</option>\n<option value="skierniewice">Skierniewice</option>\n<option value="belchatowski">be\u0142chatowski</option>\n<option value="brzezinski">brzezi\u0144ski</option>\n<option value="kutnowski">kutnowski</option>\n<option value="laski">\u0142aski</option>\n<option value="leczycki">\u0142\u0119czycki</option>\n<option value="lowicki">\u0142owicki</option>\n<option value="lodzki wschodni">\u0142\xf3dzki wschodni</option>\n<option value="opoczynski">opoczy\u0144ski</option>\n<option value="pabianicki">pabianicki</option>\n<option value="pajeczanski">paj\u0119cza\u0144ski</option>\n<option value="piotrkowski">piotrkowski</option>\n<option value="poddebicki">podd\u0119bicki</option>\n<option value="radomszczanski">radomszcza\u0144ski</option>\n<option value="rawski">rawski</option>\n<option value="sieradzki">sieradzki</option>\n<option value="skierniewicki">skierniewicki</option>\n<option value="tomaszowski">tomaszowski</option>\n<option value="wielunski">wielu\u0144ski</option>\n<option value="wieruszowski">wieruszowski</option>\n<option value="zdunskowolski">zdu\u0144skowolski</option>\n<option value="zgierski">zgierski</option>\n<option value="krakow">Krak\xf3w</option>\n<option value="tarnow">Tarn\xf3w</option>\n<option value="nowy-sacz">Nowy S\u0105cz</option>\n<option value="bochenski">boche\u0144ski</option>\n<option value="brzeski">brzeski</option>\n<option value="chrzanowski">chrzanowski</option>\n<option value="dabrowski">d\u0105browski</option>\n<option value="gorlicki">gorlicki</option>\n<option value="krakowski">krakowski</option>\n<option value="limanowski">limanowski</option>\n<option value="miechowski">miechowski</option>\n<option value="myslenicki">my\u015blenicki</option>\n<option value="nowosadecki">nowos\u0105decki</option>\n<option value="nowotarski">nowotarski</option>\n<option value="olkuski">olkuski</option>\n<option value="oswiecimski">o\u015bwi\u0119cimski</option>\n<option value="proszowicki">proszowicki</option>\n<option value="suski">suski</option>\n<option value="tarnowski">tarnowski</option>\n<option value="tatrzanski">tatrza\u0144ski</option>\n<option value="wadowicki">wadowicki</option>\n<option value="wielicki">wielicki</option>\n<option value="warszawa">Warszawa</option>\n<option value="ostroleka">Ostro\u0142\u0119ka</option>\n<option value="plock">P\u0142ock</option>\n<option value="radom">Radom</option>\n<option value="siedlce">Siedlce</option>\n<option value="bialobrzeski">bia\u0142obrzeski</option>\n<option value="ciechanowski">ciechanowski</option>\n<option value="garwolinski">garwoli\u0144ski</option>\n<option value="gostyninski">gostyni\u0144ski</option>\n<option value="grodziski">grodziski</option>\n<option value="grojecki">gr\xf3jecki</option>\n<option value="kozienicki">kozenicki</option>\n<option value="legionowski">legionowski</option>\n<option value="lipski">lipski</option>\n<option value="losicki">\u0142osicki</option>\n<option value="makowski">makowski</option>\n<option value="minski">mi\u0144ski</option>\n<option value="mlawski">m\u0142awski</option>\n<option value="nowodworski">nowodworski</option>\n<option value="ostrolecki">ostro\u0142\u0119cki</option>\n<option value="ostrowski">ostrowski</option>\n<option value="otwocki">otwocki</option>\n<option value="piaseczynski">piaseczy\u0144ski</option>\n<option value="plocki">p\u0142ocki</option>\n<option value="plonski">p\u0142o\u0144ski</option>\n<option value="pruszkowski">pruszkowski</option>\n<option value="przasnyski">przasnyski</option>\n<option value="przysuski">przysuski</option>\n<option value="pultuski">pu\u0142tuski</option>\n<option value="radomski">radomski</option>\n<option value="siedlecki">siedlecki</option>\n<option value="sierpecki">sierpecki</option>\n<option value="sochaczewski">sochaczewski</option>\n<option value="sokolowski">soko\u0142owski</option>\n<option value="szydlowiecki">szyd\u0142owiecki</option>\n<option value="warszawski-zachodni">warszawski zachodni</option>\n<option value="wegrowski">w\u0119growski</option>\n<option value="wolominski">wo\u0142omi\u0144ski</option>\n<option value="wyszkowski">wyszkowski</option>\n<option value="zwolenski">zwole\u0144ski</option>\n<option value="zurominski">\u017curomi\u0144ski</option>\n<option value="zyrardowski">\u017cyrardowski</option>\n<option value="opole">Opole</option>\n<option value="brzeski">brzeski</option>\n<option value="glubczycki">g\u0142ubczyski</option>\n<option value="kedzierzynsko-kozielski">k\u0119dzierzy\u0144ski-kozielski</option>\n<option value="kluczborski">kluczborski</option>\n<option value="krapkowicki">krapkowicki</option>\n<option value="namyslowski">namys\u0142owski</option>\n<option value="nyski">nyski</option>\n<option value="oleski">oleski</option>\n<option value="opolski">opolski</option>\n<option value="prudnicki">prudnicki</option>\n<option value="strzelecki">strzelecki</option>\n<option value="rzeszow">Rzesz\xf3w</option>\n<option value="krosno">Krosno</option>\n<option value="przemysl">Przemy\u015bl</option>\n<option value="tarnobrzeg">Tarnobrzeg</option>\n<option value="bieszczadzki">bieszczadzki</option>\n<option value="brzozowski">brzozowski</option>\n<option value="debicki">d\u0119bicki</option>\n<option value="jaroslawski">jaros\u0142awski</option>\n<option value="jasielski">jasielski</option>\n<option value="kolbuszowski">kolbuszowski</option>\n<option value="krosnienski">kro\u015bnie\u0144ski</option>\n<option value="leski">leski</option>\n<option value="lezajski">le\u017cajski</option>\n<option value="lubaczowski">lubaczowski</option>\n<option value="lancucki">\u0142a\u0144cucki</option>\n<option value="mielecki">mielecki</option>\n<option value="nizanski">ni\u017ca\u0144ski</option>\n<option value="przemyski">przemyski</option>\n<option value="przeworski">przeworski</option>\n<option value="ropczycko-sedziszowski">ropczycko-s\u0119dziszowski</option>\n<option value="rzeszowski">rzeszowski</option>\n<option value="sanocki">sanocki</option>\n<option value="stalowowolski">stalowowolski</option>\n<option value="strzyzowski">strzy\u017cowski</option>\n<option value="tarnobrzeski">tarnobrzeski</option>\n<option value="bialystok">Bia\u0142ystok</option>\n<option value="lomza">\u0141om\u017ca</option>\n<option value="suwalki">Suwa\u0142ki</option>\n<option value="augustowski">augustowski</option>\n<option value="bialostocki">bia\u0142ostocki</option>\n<option value="bielski">bielski</option>\n<option value="grajewski">grajewski</option>\n<option value="hajnowski">hajnowski</option>\n<option value="kolnenski">kolne\u0144ski</option>\n<option value="\u0142omzynski">\u0142om\u017cy\u0144ski</option>\n<option value="moniecki">moniecki</option>\n<option value="sejnenski">sejne\u0144ski</option>\n<option value="siemiatycki">siematycki</option>\n<option value="sokolski">sok\xf3lski</option>\n<option value="suwalski">suwalski</option>\n<option value="wysokomazowiecki">wysokomazowiecki</option>\n<option value="zambrowski">zambrowski</option>\n<option value="gdansk">Gda\u0144sk</option>\n<option value="gdynia">Gdynia</option>\n<option value="slupsk">S\u0142upsk</option>\n<option value="sopot">Sopot</option>\n<option value="bytowski">bytowski</option>\n<option value="chojnicki">chojnicki</option>\n<option value="czluchowski">cz\u0142uchowski</option>\n<option value="kartuski">kartuski</option>\n<option value="koscierski">ko\u015bcierski</option>\n<option value="kwidzynski">kwidzy\u0144ski</option>\n<option value="leborski">l\u0119borski</option>\n<option value="malborski">malborski</option>\n<option value="nowodworski">nowodworski</option>\n<option value="gdanski">gda\u0144ski</option>\n<option value="pucki">pucki</option>\n<option value="slupski">s\u0142upski</option>\n<option value="starogardzki">starogardzki</option>\n<option value="sztumski">sztumski</option>\n<option value="tczewski">tczewski</option>\n<option value="wejherowski">wejcherowski</option>\n<option value="katowice" selected="selected">Katowice</option>\n<option value="bielsko-biala">Bielsko-Bia\u0142a</option>\n<option value="bytom">Bytom</option>\n<option value="chorzow">Chorz\xf3w</option>\n<option value="czestochowa">Cz\u0119stochowa</option>\n<option value="dabrowa-gornicza">D\u0105browa G\xf3rnicza</option>\n<option value="gliwice">Gliwice</option>\n<option value="jastrzebie-zdroj">Jastrz\u0119bie Zdr\xf3j</option>\n<option value="jaworzno">Jaworzno</option>\n<option value="myslowice">Mys\u0142owice</option>\n<option value="piekary-slaskie">Piekary \u015al\u0105skie</option>\n<option value="ruda-slaska">Ruda \u015al\u0105ska</option>\n<option value="rybnik">Rybnik</option>\n<option value="siemianowice-slaskie">Siemianowice \u015al\u0105skie</option>\n<option value="sosnowiec">Sosnowiec</option>\n<option value="swietochlowice">\u015awi\u0119toch\u0142owice</option>\n<option value="tychy">Tychy</option>\n<option value="zabrze">Zabrze</option>\n<option value="zory">\u017bory</option>\n<option value="bedzinski">b\u0119dzi\u0144ski</option>\n<option value="bielski">bielski</option>\n<option value="bierunsko-ledzinski">bieru\u0144sko-l\u0119dzi\u0144ski</option>\n<option value="cieszynski">cieszy\u0144ski</option>\n<option value="czestochowski">cz\u0119stochowski</option>\n<option value="gliwicki">gliwicki</option>\n<option value="klobucki">k\u0142obucki</option>\n<option value="lubliniecki">lubliniecki</option>\n<option value="mikolowski">miko\u0142owski</option>\n<option value="myszkowski">myszkowski</option>\n<option value="pszczynski">pszczy\u0144ski</option>\n<option value="raciborski">raciborski</option>\n<option value="rybnicki">rybnicki</option>\n<option value="tarnogorski">tarnog\xf3rski</option>\n<option value="wodzislawski">wodzis\u0142awski</option>\n<option value="zawiercianski">zawiercia\u0144ski</option>\n<option value="zywiecki">\u017cywiecki</option>\n<option value="kielce">Kielce</option>\n<option value="buski">buski</option>\n<option value="jedrzejowski">j\u0119drzejowski</option>\n<option value="kazimierski">kazimierski</option>\n<option value="kielecki">kielecki</option>\n<option value="konecki">konecki</option>\n<option value="opatowski">opatowski</option>\n<option value="ostrowiecki">ostrowiecki</option>\n<option value="pinczowski">pi\u0144czowski</option>\n<option value="sandomierski">sandomierski</option>\n<option value="skarzyski">skar\u017cyski</option>\n<option value="starachowicki">starachowicki</option>\n<option value="staszowski">staszowski</option>\n<option value="wloszczowski">w\u0142oszczowski</option>\n<option value="olsztyn">Olsztyn</option>\n<option value="elblag">Elbl\u0105g</option>\n<option value="bartoszycki">bartoszycki</option>\n<option value="braniewski">braniewski</option>\n<option value="dzialdowski">dzia\u0142dowski</option>\n<option value="elblaski">elbl\u0105ski</option>\n<option value="elcki">e\u0142cki</option>\n<option value="gizycki">gi\u017cycki</option>\n<option value="goldapski">go\u0142dapski</option>\n<option value="ilawski">i\u0142awski</option>\n<option value="ketrzynski">k\u0119trzy\u0144ski</option>\n<option value="lidzbarski">lidzbarski</option>\n<option value="mragowski">mr\u0105gowski</option>\n<option value="nidzicki">nidzicki</option>\n<option value="nowomiejski">nowomiejski</option>\n<option value="olecki">olecki</option>\n<option value="olsztynski">olszty\u0144ski</option>\n<option value="ostrodzki">ostr\xf3dzki</option>\n<option value="piski">piski</option>\n<option value="szczycienski">szczycie\u0144ski</option>\n<option value="wegorzewski">w\u0119gorzewski</option>\n<option value="poznan">Pozna\u0144</option>\n<option value="kalisz">Kalisz</option>\n<option value="konin">Konin</option>\n<option value="leszno">Leszno</option>\n<option value="chodzieski">chodziejski</option>\n<option value="czarnkowsko-trzcianecki">czarnkowsko-trzcianecki</option>\n<option value="gnieznienski">gnie\u017anie\u0144ski</option>\n<option value="gostynski">gosty\u0144ski</option>\n<option value="grodziski">grodziski</option>\n<option value="jarocinski">jaroci\u0144ski</option>\n<option value="kaliski">kaliski</option>\n<option value="kepinski">k\u0119pi\u0144ski</option>\n<option value="kolski">kolski</option>\n<option value="koninski">koni\u0144ski</option>\n<option value="koscianski">ko\u015bcia\u0144ski</option>\n<option value="krotoszynski">krotoszy\u0144ski</option>\n<option value="leszczynski">leszczy\u0144ski</option>\n<option value="miedzychodzki">mi\u0119dzychodzki</option>\n<option value="nowotomyski">nowotomyski</option>\n<option value="obornicki">obornicki</option>\n<option value="ostrowski">ostrowski</option>\n<option value="ostrzeszowski">ostrzeszowski</option>\n<option value="pilski">pilski</option>\n<option value="pleszewski">pleszewski</option>\n<option value="poznanski">pozna\u0144ski</option>\n<option value="rawicki">rawicki</option>\n<option value="slupecki">s\u0142upecki</option>\n<option value="szamotulski">szamotulski</option>\n<option value="sredzki">\u015bredzki</option>\n<option value="sremski">\u015bremski</option>\n<option value="turecki">turecki</option>\n<option value="wagrowiecki">w\u0105growiecki</option>\n<option value="wolsztynski">wolszty\u0144ski</option>\n<option value="wrzesinski">wrzesi\u0144ski</option>\n<option value="zlotowski">z\u0142otowski</option>\n<option value="bialogardzki">bia\u0142ogardzki</option>\n<option value="choszczenski">choszcze\u0144ski</option>\n<option value="drawski">drawski</option>\n<option value="goleniowski">goleniowski</option>\n<option value="gryficki">gryficki</option>\n<option value="gryfinski">gryfi\u0144ski</option>\n<option value="kamienski">kamie\u0144ski</option>\n<option value="kolobrzeski">ko\u0142obrzeski</option>\n<option value="koszalinski">koszali\u0144ski</option>\n<option value="lobeski">\u0142obeski</option>\n<option value="mysliborski">my\u015bliborski</option>\n<option value="policki">policki</option>\n<option value="pyrzycki">pyrzycki</option>\n<option value="slawienski">s\u0142awie\u0144ski</option>\n<option value="stargardzki">stargardzki</option>\n<option value="szczecinecki">szczecinecki</option>\n<option value="swidwinski">\u015bwidwi\u0144ski</option>\n<option value="walecki">wa\u0142ecki</option>\n</select>' - -# PLPostalCodeField ############################################################## - ->>> from django.contrib.localflavor.pl.forms import PLPostalCodeField ->>> f = PLPostalCodeField() ->>> f.clean('43--434') -Traceback (most recent call last): -... -ValidationError: [u'Enter a postal code in the format XX-XXX.'] ->>> f.clean('41-403') -u'41-403' - -# PLTaxNumberField ############################################################### - ->>> from django.contrib.localflavor.pl.forms import PLTaxNumberField ->>> f = PLTaxNumberField() ->>> f.clean('43-343-234-323') -Traceback (most recent call last): -... -ValidationError: [u'Enter a tax number field (NIP) in the format XXX-XXX-XX-XX or XX-XX-XXX-XXX.'] ->>> f.clean('43-34-234-323') -u'43-34-234-323' ->>> f.clean('433-344-24-23') -u'433-344-24-23' - -# PLNationalIdentificationNumberField ############################################ - ->>> from django.contrib.localflavor.pl.forms import PLNationalIdentificationNumberField ->>> f = PLNationalIdentificationNumberField() ->>> f.clean('80071610614') -u'80071610614' ->>> f.clean('80071610610') -Traceback (most recent call last): -... -ValidationError: [u'Wrong checksum for the National Identification Number.'] ->>> f.clean('80') -Traceback (most recent call last): -... -ValidationError: [u'National Identification Number consists of 11 digits.'] ->>> f.clean('800716106AA') -Traceback (most recent call last): -... -ValidationError: [u'National Identification Number consists of 11 digits.'] -""" diff --git a/tests/regressiontests/forms/localflavor/__init__.py b/tests/regressiontests/forms/localflavor/__init__.py new file mode 100644 index 0000000000..40a96afc6f --- /dev/null +++ b/tests/regressiontests/forms/localflavor/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/tests/regressiontests/forms/localflavor/ar.py b/tests/regressiontests/forms/localflavor/ar.py new file mode 100644 index 0000000000..e1c827c4a0 --- /dev/null +++ b/tests/regressiontests/forms/localflavor/ar.py @@ -0,0 +1,294 @@ +# -*- coding: utf-8 -*- +# Tests for the contrib/localflavor/ AR form fields. + +tests = r""" +# ARProvinceField ############################################################# + +>>> from django.contrib.localflavor.ar.forms import ARProvinceSelect +>>> f = ARProvinceSelect() +>>> f.render('provincias', 'A') +u'<select name="provincias">\n<option value="B">Buenos Aires</option>\n<option value="K">Catamarca</option>\n<option value="H">Chaco</option>\n<option value="U">Chubut</option>\n<option value="C">Ciudad Aut\xf3noma de Buenos Aires</option>\n<option value="X">C\xf3rdoba</option>\n<option value="W">Corrientes</option>\n<option value="E">Entre R\xedos</option>\n<option value="P">Formosa</option>\n<option value="Y">Jujuy</option>\n<option value="L">La Pampa</option>\n<option value="F">La Rioja</option>\n<option value="M">Mendoza</option>\n<option value="N">Misiones</option>\n<option value="Q">Neuqu\xe9n</option>\n<option value="R">R\xedo Negro</option>\n<option value="A" selected="selected">Salta</option>\n<option value="J">San Juan</option>\n<option value="D">San Luis</option>\n<option value="Z">Santa Cruz</option>\n<option value="S">Santa Fe</option>\n<option value="G">Santiago del Estero</option>\n<option value="V">Tierra del Fuego, Ant\xe1rtida e Islas del Atl\xe1ntico Sur</option>\n<option value="T">Tucum\xe1n</option>\n</select>' + +# ARPostalCodeField ########################################################### + +>>> from django.contrib.localflavor.ar.forms import ARPostalCodeField +>>> f = ARPostalCodeField() +>>> f.clean('5000') +u'5000' +>>> f.clean('C1064AAB') +u'C1064AAB' +>>> f.clean('c1064AAB') +u'C1064AAB' +>>> f.clean('C1064aab') +u'C1064AAB' +>>> f.clean(u'4400') +u'4400' +>>> f.clean(u'C1064AAB') +u'C1064AAB' +>>> f.clean('C1064AABB') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value has at most 8 characters (it has 9).'] +>>> f.clean('C1064AA') +Traceback (most recent call last): +... +ValidationError: [u'Enter a postal code in the format NNNN or ANNNNAAA.'] +>>> f.clean('C106AAB') +Traceback (most recent call last): +... +ValidationError: [u'Enter a postal code in the format NNNN or ANNNNAAA.'] +>>> f.clean('106AAB') +Traceback (most recent call last): +... +ValidationError: [u'Enter a postal code in the format NNNN or ANNNNAAA.'] +>>> f.clean('500') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value has at least 4 characters (it has 3).'] +>>> f.clean('5PPP') +Traceback (most recent call last): +... +ValidationError: [u'Enter a postal code in the format NNNN or ANNNNAAA.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean(u'') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] + +>>> f = ARPostalCodeField(required=False) +>>> f.clean('5000') +u'5000' +>>> f.clean('C1064AAB') +u'C1064AAB' +>>> f.clean('c1064AAB') +u'C1064AAB' +>>> f.clean('C1064aab') +u'C1064AAB' +>>> f.clean(u'4400') +u'4400' +>>> f.clean(u'C1064AAB') +u'C1064AAB' +>>> f.clean('C1064AABB') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value has at most 8 characters (it has 9).'] +>>> f.clean('C1064AA') +Traceback (most recent call last): +... +ValidationError: [u'Enter a postal code in the format NNNN or ANNNNAAA.'] +>>> f.clean('C106AAB') +Traceback (most recent call last): +... +ValidationError: [u'Enter a postal code in the format NNNN or ANNNNAAA.'] +>>> f.clean('106AAB') +Traceback (most recent call last): +... +ValidationError: [u'Enter a postal code in the format NNNN or ANNNNAAA.'] +>>> f.clean('500') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value has at least 4 characters (it has 3).'] +>>> f.clean('5PPP') +Traceback (most recent call last): +... +ValidationError: [u'Enter a postal code in the format NNNN or ANNNNAAA.'] +>>> f.clean(None) +u'' +>>> f.clean('') +u'' +>>> f.clean(u'') +u'' + +# ARDNIField ################################################################## + +>>> from django.contrib.localflavor.ar.forms import ARDNIField +>>> f = ARDNIField() +>>> f.clean('20123456') +u'20123456' +>>> f.clean('20.123.456') +u'20123456' +>>> f.clean('9123456') +u'9123456' +>>> f.clean('9.123.456') +u'9123456' +>>> f.clean(u'20123456') +u'20123456' +>>> f.clean(u'20.123.456') +u'20123456' +>>> f.clean('20.123456') +u'20123456' +>>> f.clean('101234566') +Traceback (most recent call last): +... +ValidationError: [u'This field requires 7 or 8 digits.'] +>>> f.clean('W0123456') +Traceback (most recent call last): +... +ValidationError: [u'This field requires only numbers.'] +>>> f.clean('10,123,456') +Traceback (most recent call last): +... +ValidationError: [u'This field requires only numbers.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean(u'') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] + +>>> f = ARDNIField(required=False) +>>> f.clean('20123456') +u'20123456' +>>> f.clean('20.123.456') +u'20123456' +>>> f.clean('9123456') +u'9123456' +>>> f.clean('9.123.456') +u'9123456' +>>> f.clean(u'20123456') +u'20123456' +>>> f.clean(u'20.123.456') +u'20123456' +>>> f.clean('20.123456') +u'20123456' +>>> f.clean('101234566') +Traceback (most recent call last): +... +ValidationError: [u'This field requires 7 or 8 digits.'] +>>> f.clean('W0123456') +Traceback (most recent call last): +... +ValidationError: [u'This field requires only numbers.'] +>>> f.clean('10,123,456') +Traceback (most recent call last): +... +ValidationError: [u'This field requires only numbers.'] +>>> f.clean(None) +u'' +>>> f.clean('') +u'' +>>> f.clean(u'') +u'' + +# ARCUITField ################################################################# + +>>> from django.contrib.localflavor.ar.forms import ARCUITField +>>> f = ARCUITField() +>>> f.clean('20-10123456-9') +u'20-10123456-9' +>>> f.clean(u'20-10123456-9') +u'20-10123456-9' +>>> f.clean('27-10345678-4') +u'27-10345678-4' +>>> f.clean('20101234569') +u'20-10123456-9' +>>> f.clean('27103456784') +u'27-10345678-4' +>>> f.clean('2-10123456-9') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.'] +>>> f.clean('210123456-9') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.'] +>>> f.clean('20-10123456') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.'] +>>> f.clean('20-10123456-') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.'] +>>> f.clean('20-10123456-5') +Traceback (most recent call last): +... +ValidationError: [u'Invalid CUIT.'] +>>> f.clean(u'2-10123456-9') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.'] +>>> f.clean('27-10345678-1') +Traceback (most recent call last): +... +ValidationError: [u'Invalid CUIT.'] +>>> f.clean(u'27-10345678-1') +Traceback (most recent call last): +... +ValidationError: [u'Invalid CUIT.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean(u'') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] + +>>> f = ARCUITField(required=False) +>>> f.clean('20-10123456-9') +u'20-10123456-9' +>>> f.clean(u'20-10123456-9') +u'20-10123456-9' +>>> f.clean('27-10345678-4') +u'27-10345678-4' +>>> f.clean('20101234569') +u'20-10123456-9' +>>> f.clean('27103456784') +u'27-10345678-4' +>>> f.clean('2-10123456-9') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.'] +>>> f.clean('210123456-9') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.'] +>>> f.clean('20-10123456') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.'] +>>> f.clean('20-10123456-') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.'] +>>> f.clean('20-10123456-5') +Traceback (most recent call last): +... +ValidationError: [u'Invalid CUIT.'] +>>> f.clean(u'2-10123456-9') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.'] +>>> f.clean('27-10345678-1') +Traceback (most recent call last): +... +ValidationError: [u'Invalid CUIT.'] +>>> f.clean(u'27-10345678-1') +Traceback (most recent call last): +... +ValidationError: [u'Invalid CUIT.'] +>>> f.clean(None) +u'' +>>> f.clean('') +u'' +>>> f.clean(u'') +u'' +""" diff --git a/tests/regressiontests/forms/localflavor/au.py b/tests/regressiontests/forms/localflavor/au.py new file mode 100644 index 0000000000..fd4c0d6980 --- /dev/null +++ b/tests/regressiontests/forms/localflavor/au.py @@ -0,0 +1,134 @@ +# -*- coding: utf-8 -*- +# Tests for the contrib/localflavor/ AU form fields. + +tests = r""" +## AUPostCodeField ########################################################## + +A field that accepts a four digit Australian post code. + +>>> from django.contrib.localflavor.au.forms import AUPostCodeField +>>> f = AUPostCodeField() +>>> f.clean('1234') +u'1234' +>>> f.clean('2000') +u'2000' +>>> f.clean('abcd') +Traceback (most recent call last): +... +ValidationError: [u'Enter a 4 digit post code.'] +>>> f.clean('20001') +Traceback (most recent call last): +... +ValidationError: [u'Enter a 4 digit post code.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] + +>>> f = AUPostCodeField(required=False) +>>> f.clean('1234') +u'1234' +>>> f.clean('2000') +u'2000' +>>> f.clean('abcd') +Traceback (most recent call last): +... +ValidationError: [u'Enter a 4 digit post code.'] +>>> f.clean('20001') +Traceback (most recent call last): +... +ValidationError: [u'Enter a 4 digit post code.'] +>>> f.clean(None) +u'' +>>> f.clean('') +u'' + +## AUPhoneNumberField ######################################################## + +A field that accepts a 10 digit Australian phone number. +llows spaces and parentheses around area code. + +>>> from django.contrib.localflavor.au.forms import AUPhoneNumberField +>>> f = AUPhoneNumberField() +>>> f.clean('1234567890') +u'1234567890' +>>> f.clean('0213456789') +u'0213456789' +>>> f.clean('02 13 45 67 89') +u'0213456789' +>>> f.clean('(02) 1345 6789') +u'0213456789' +>>> f.clean('(02) 1345-6789') +u'0213456789' +>>> f.clean('(02)1345-6789') +u'0213456789' +>>> f.clean('0408 123 456') +u'0408123456' +>>> f.clean('123') +Traceback (most recent call last): +... +ValidationError: [u'Phone numbers must contain 10 digits.'] +>>> f.clean('1800DJANGO') +Traceback (most recent call last): +... +ValidationError: [u'Phone numbers must contain 10 digits.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] + +>>> f = AUPhoneNumberField(required=False) +>>> f.clean('1234567890') +u'1234567890' +>>> f.clean('0213456789') +u'0213456789' +>>> f.clean('02 13 45 67 89') +u'0213456789' +>>> f.clean('(02) 1345 6789') +u'0213456789' +>>> f.clean('(02) 1345-6789') +u'0213456789' +>>> f.clean('(02)1345-6789') +u'0213456789' +>>> f.clean('0408 123 456') +u'0408123456' +>>> f.clean('123') +Traceback (most recent call last): +... +ValidationError: [u'Phone numbers must contain 10 digits.'] +>>> f.clean('1800DJANGO') +Traceback (most recent call last): +... +ValidationError: [u'Phone numbers must contain 10 digits.'] +>>> f.clean(None) +u'' +>>> f.clean('') +u'' + +## AUStateSelect ############################################################# + +AUStateSelect is a Select widget that uses a list of Australian +states/territories as its choices. + +>>> from django.contrib.localflavor.au.forms import AUStateSelect +>>> f = AUStateSelect() +>>> print f.render('state', 'NSW') +<select name="state"> +<option value="ACT">Australian Capital Territory</option> +<option value="NSW" selected="selected">New South Wales</option> +<option value="NT">Northern Territory</option> +<option value="QLD">Queensland</option> +<option value="SA">South Australia</option> +<option value="TAS">Tasmania</option> +<option value="VIC">Victoria</option> +<option value="WA">Western Australia</option> +</select> +""" diff --git a/tests/regressiontests/forms/localflavor/br.py b/tests/regressiontests/forms/localflavor/br.py new file mode 100644 index 0000000000..757f382d64 --- /dev/null +++ b/tests/regressiontests/forms/localflavor/br.py @@ -0,0 +1,220 @@ +# -*- coding: utf-8 -*- +# Tests for the contrib/localflavor/ BR form fields. + +tests = r""" +# BRZipCodeField ############################################################ +>>> from django.contrib.localflavor.br.forms import BRZipCodeField +>>> f = BRZipCodeField() +>>> f.clean('12345-123') +u'12345-123' +>>> f.clean('12345_123') +Traceback (most recent call last): +... +ValidationError: [u'Enter a zip code in the format XXXXX-XXX.'] +>>> f.clean('1234-123') +Traceback (most recent call last): +... +ValidationError: [u'Enter a zip code in the format XXXXX-XXX.'] +>>> f.clean('abcde-abc') +Traceback (most recent call last): +... +ValidationError: [u'Enter a zip code in the format XXXXX-XXX.'] +>>> f.clean('12345-') +Traceback (most recent call last): +... +ValidationError: [u'Enter a zip code in the format XXXXX-XXX.'] +>>> f.clean('-123') +Traceback (most recent call last): +... +ValidationError: [u'Enter a zip code in the format XXXXX-XXX.'] +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] + +>>> f = BRZipCodeField(required=False) +>>> f.clean(None) +u'' +>>> f.clean('') +u'' +>>> f.clean('-123') +Traceback (most recent call last): +... +ValidationError: [u'Enter a zip code in the format XXXXX-XXX.'] +>>> f.clean('12345-') +Traceback (most recent call last): +... +ValidationError: [u'Enter a zip code in the format XXXXX-XXX.'] +>>> f.clean('abcde-abc') +Traceback (most recent call last): +... +ValidationError: [u'Enter a zip code in the format XXXXX-XXX.'] +>>> f.clean('1234-123') +Traceback (most recent call last): +... +ValidationError: [u'Enter a zip code in the format XXXXX-XXX.'] +>>> f.clean('12345_123') +Traceback (most recent call last): +... +ValidationError: [u'Enter a zip code in the format XXXXX-XXX.'] +>>> f.clean('12345-123') +u'12345-123' + +# BRCNPJField ############################################################ + +>>> from django.contrib.localflavor.br.forms import BRCNPJField +>>> f = BRCNPJField(required=True) +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('12-345-678/9012-10') +Traceback (most recent call last): +... +ValidationError: [u'Invalid CNPJ number.'] +>>> f.clean('12.345.678/9012-10') +Traceback (most recent call last): +... +ValidationError: [u'Invalid CNPJ number.'] +>>> f.clean('12345678/9012-10') +Traceback (most recent call last): +... +ValidationError: [u'Invalid CNPJ number.'] +>>> f.clean('64.132.916/0001-88') +'64.132.916/0001-88' +>>> f.clean('64-132-916/0001-88') +'64-132-916/0001-88' +>>> f.clean('64132916/0001-88') +'64132916/0001-88' +>>> f.clean('64.132.916/0001-XX') +Traceback (most recent call last): +... +ValidationError: [u'This field requires only numbers.'] +>>> f = BRCNPJField(required=False) +>>> f.clean('') +u'' + +# BRCPFField ################################################################# + +>>> from django.contrib.localflavor.br.forms import BRCPFField +>>> f = BRCPFField() +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('489.294.654-54') +Traceback (most recent call last): +... +ValidationError: [u'Invalid CPF number.'] +>>> f.clean('295.669.575-98') +Traceback (most recent call last): +... +ValidationError: [u'Invalid CPF number.'] +>>> f.clean('539.315.127-22') +Traceback (most recent call last): +... +ValidationError: [u'Invalid CPF number.'] +>>> f.clean('663.256.017-26') +u'663.256.017-26' +>>> f.clean('66325601726') +u'66325601726' +>>> f.clean('375.788.573-20') +u'375.788.573-20' +>>> f.clean('84828509895') +u'84828509895' +>>> f.clean('375.788.573-XX') +Traceback (most recent call last): +... +ValidationError: [u'This field requires only numbers.'] +>>> f.clean('375.788.573-000') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value has at most 14 characters (it has 15).'] +>>> f.clean('123.456.78') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value has at least 11 characters (it has 10).'] +>>> f.clean('123456789555') +Traceback (most recent call last): +... +ValidationError: [u'This field requires at most 11 digits or 14 characters.'] +>>> f = BRCPFField(required=False) +>>> f.clean('') +u'' +>>> f.clean(None) +u'' + +# BRPhoneNumberField ######################################################### + +>>> from django.contrib.localflavor.br.forms import BRPhoneNumberField +>>> f = BRPhoneNumberField() +>>> f.clean('41-3562-3464') +u'41-3562-3464' +>>> f.clean('4135623464') +u'41-3562-3464' +>>> f.clean('41 3562-3464') +u'41-3562-3464' +>>> f.clean('41 3562 3464') +u'41-3562-3464' +>>> f.clean('(41) 3562 3464') +u'41-3562-3464' +>>> f.clean('41.3562.3464') +u'41-3562-3464' +>>> f.clean('41.3562-3464') +u'41-3562-3464' +>>> f.clean(' (41) 3562.3464') +u'41-3562-3464' +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] + +>>> f = BRPhoneNumberField(required=False) +>>> f.clean('') +u'' +>>> f.clean(None) +u'' +>>> f.clean(' (41) 3562.3464') +u'41-3562-3464' +>>> f.clean('41.3562-3464') +u'41-3562-3464' +>>> f.clean('(41) 3562 3464') +u'41-3562-3464' +>>> f.clean('4135623464') +u'41-3562-3464' +>>> f.clean('41 3562-3464') +u'41-3562-3464' + +# BRStateSelect ############################################################## + +>>> from django.contrib.localflavor.br.forms import BRStateSelect +>>> w = BRStateSelect() +>>> w.render('states', 'PR') +u'<select name="states">\n<option value="AC">Acre</option>\n<option value="AL">Alagoas</option>\n<option value="AP">Amap\xe1</option>\n<option value="AM">Amazonas</option>\n<option value="BA">Bahia</option>\n<option value="CE">Cear\xe1</option>\n<option value="DF">Distrito Federal</option>\n<option value="ES">Esp\xedrito Santo</option>\n<option value="GO">Goi\xe1s</option>\n<option value="MA">Maranh\xe3o</option>\n<option value="MT">Mato Grosso</option>\n<option value="MS">Mato Grosso do Sul</option>\n<option value="MG">Minas Gerais</option>\n<option value="PA">Par\xe1</option>\n<option value="PB">Para\xedba</option>\n<option value="PR" selected="selected">Paran\xe1</option>\n<option value="PE">Pernambuco</option>\n<option value="PI">Piau\xed</option>\n<option value="RJ">Rio de Janeiro</option>\n<option value="RN">Rio Grande do Norte</option>\n<option value="RS">Rio Grande do Sul</option>\n<option value="RO">Rond\xf4nia</option>\n<option value="RR">Roraima</option>\n<option value="SC">Santa Catarina</option>\n<option value="SP">S\xe3o Paulo</option>\n<option value="SE">Sergipe</option>\n<option value="TO">Tocantins</option>\n</select>' + +# BRStateChoiceField ######################################################### +>>> from django.contrib.localflavor.br.forms import BRStateChoiceField +>>> f = BRStateChoiceField() +>>> ', '.join([f.clean(s) for s, _ in f.widget.choices]) +u'AC, AL, AP, AM, BA, CE, DF, ES, GO, MA, MT, MS, MG, PA, PB, PR, PE, PI, RJ, RN, RS, RO, RR, SC, SP, SE, TO' +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('pr') +Traceback (most recent call last): +... +ValidationError: [u'Select a valid brazilian state. That state is not one of the available states.'] +""" diff --git a/tests/regressiontests/forms/localflavor/ca.py b/tests/regressiontests/forms/localflavor/ca.py new file mode 100644 index 0000000000..baeb2ad9a8 --- /dev/null +++ b/tests/regressiontests/forms/localflavor/ca.py @@ -0,0 +1,221 @@ +# -*- coding: utf-8 -*- +# Tests for the contrib/localflavor/ CA form fields. + +tests = r""" +# CAPostalCodeField ############################################################## + +CAPostalCodeField validates that the data is a six-character Canadian postal code. +>>> from django.contrib.localflavor.ca.forms import CAPostalCodeField +>>> f = CAPostalCodeField() +>>> f.clean('T2S 2H7') +u'T2S 2H7' +>>> f.clean('T2S 2H') +Traceback (most recent call last): +... +ValidationError: [u'Enter a postal code in the format XXX XXX.'] +>>> f.clean('2T6 H8I') +Traceback (most recent call last): +... +ValidationError: [u'Enter a postal code in the format XXX XXX.'] +>>> f.clean('T2S2H') +Traceback (most recent call last): +... +ValidationError: [u'Enter a postal code in the format XXX XXX.'] +>>> f.clean(90210) +Traceback (most recent call last): +... +ValidationError: [u'Enter a postal code in the format XXX XXX.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f = CAPostalCodeField(required=False) +>>> f.clean('T2S 2H7') +u'T2S 2H7' +>>> f.clean('T2S2H7') +Traceback (most recent call last): +... +ValidationError: [u'Enter a postal code in the format XXX XXX.'] +>>> f.clean('T2S 2H') +Traceback (most recent call last): +... +ValidationError: [u'Enter a postal code in the format XXX XXX.'] +>>> f.clean('2T6 H8I') +Traceback (most recent call last): +... +ValidationError: [u'Enter a postal code in the format XXX XXX.'] +>>> f.clean('T2S2H') +Traceback (most recent call last): +... +ValidationError: [u'Enter a postal code in the format XXX XXX.'] +>>> f.clean(90210) +Traceback (most recent call last): +... +ValidationError: [u'Enter a postal code in the format XXX XXX.'] +>>> f.clean(None) +u'' +>>> f.clean('') +u'' + +# CAPhoneNumberField ########################################################## + +CAPhoneNumberField validates that the data is a valid Canadian phone number, +including the area code. It's normalized to XXX-XXX-XXXX format. +Note: This test is exactly the same as the USPhoneNumberField except using a real +Candian area code + +>>> from django.contrib.localflavor.ca.forms import CAPhoneNumberField +>>> f = CAPhoneNumberField() +>>> f.clean('403-555-1212') +u'403-555-1212' +>>> f.clean('4035551212') +u'403-555-1212' +>>> f.clean('403 555-1212') +u'403-555-1212' +>>> f.clean('(403) 555-1212') +u'403-555-1212' +>>> f.clean('403 555 1212') +u'403-555-1212' +>>> f.clean('403.555.1212') +u'403-555-1212' +>>> f.clean('403.555-1212') +u'403-555-1212' +>>> f.clean(' (403) 555.1212 ') +u'403-555-1212' +>>> f.clean('555-1212') +Traceback (most recent call last): +... +ValidationError: [u'Phone numbers must be in XXX-XXX-XXXX format.'] +>>> f.clean('403-55-1212') +Traceback (most recent call last): +... +ValidationError: [u'Phone numbers must be in XXX-XXX-XXXX format.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] + +>>> f = CAPhoneNumberField(required=False) +>>> f.clean('403-555-1212') +u'403-555-1212' +>>> f.clean('4035551212') +u'403-555-1212' +>>> f.clean('403 555-1212') +u'403-555-1212' +>>> f.clean('(403) 555-1212') +u'403-555-1212' +>>> f.clean('403 555 1212') +u'403-555-1212' +>>> f.clean('403.555.1212') +u'403-555-1212' +>>> f.clean('403.555-1212') +u'403-555-1212' +>>> f.clean(' (403) 555.1212 ') +u'403-555-1212' +>>> f.clean('555-1212') +Traceback (most recent call last): +... +ValidationError: [u'Phone numbers must be in XXX-XXX-XXXX format.'] +>>> f.clean('403-55-1212') +Traceback (most recent call last): +... +ValidationError: [u'Phone numbers must be in XXX-XXX-XXXX format.'] +>>> f.clean(None) +u'' +>>> f.clean('') +u'' + +# CAProvinceField ################################################################ + +CAProvinceField validates that the data is either an abbreviation or name of a +Canadian province. +>>> from django.contrib.localflavor.ca.forms import CAProvinceField +>>> f = CAProvinceField() +>>> f.clean('ab') +u'AB' +>>> f.clean('BC') +u'BC' +>>> f.clean('nova scotia') +u'NS' +>>> f.clean(' manitoba ') +u'MB' +>>> f.clean('T2S 2H7') +Traceback (most recent call last): +... +ValidationError: [u'Enter a Canadian province or territory.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] + +>>> f = CAProvinceField(required=False) +>>> f.clean('ab') +u'AB' +>>> f.clean('BC') +u'BC' +>>> f.clean('nova scotia') +u'NS' +>>> f.clean(' manitoba ') +u'MB' +>>> f.clean('T2S 2H7') +Traceback (most recent call last): +... +ValidationError: [u'Enter a Canadian province or territory.'] +>>> f.clean(None) +u'' +>>> f.clean('') +u'' + +# CAProvinceSelect ############################################################### + +CAProvinceSelect is a Select widget that uses a list of Canadian provinces/territories +as its choices. +>>> from django.contrib.localflavor.ca.forms import CAProvinceSelect +>>> w = CAProvinceSelect() +>>> print w.render('province', 'AB') +<select name="province"> +<option value="AB" selected="selected">Alberta</option> +<option value="BC">British Columbia</option> +<option value="MB">Manitoba</option> +<option value="NB">New Brunswick</option> +<option value="NF">Newfoundland and Labrador</option> +<option value="NT">Northwest Territories</option> +<option value="NS">Nova Scotia</option> +<option value="NU">Nunavut</option> +<option value="ON">Ontario</option> +<option value="PE">Prince Edward Island</option> +<option value="QC">Quebec</option> +<option value="SK">Saskatchewan</option> +<option value="YK">Yukon</option> +</select> + +# CASocialInsuranceNumberField ################################################# +>>> from django.contrib.localflavor.ca.forms import CASocialInsuranceNumberField +>>> f = CASocialInsuranceNumberField() +>>> f.clean('046-454-286') +u'046-454-286' +>>> f.clean('046-454-287') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid Canadian Social Insurance number in XXX-XXX-XXXX format.'] +>>> f.clean('046 454 286') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid Canadian Social Insurance number in XXX-XXX-XXXX format.'] +>>> f.clean('046-44-286') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid Canadian Social Insurance number in XXX-XXX-XXXX format.'] +""" diff --git a/tests/regressiontests/forms/localflavor/ch.py b/tests/regressiontests/forms/localflavor/ch.py new file mode 100644 index 0000000000..b4f8e7d667 --- /dev/null +++ b/tests/regressiontests/forms/localflavor/ch.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Tests for the contrib/localflavor/ CH form fields. + +tests = r""" +# CHZipCodeField ############################################################ + +>>> from django.contrib.localflavor.ch.forms import CHZipCodeField +>>> f = CHZipCodeField() +>>> f.clean('800x') +Traceback (most recent call last): +... +ValidationError: [u'Enter a zip code in the format XXXX.'] +>>> f.clean('80 00') +Traceback (most recent call last): +... +ValidationError: [u'Enter a zip code in the format XXXX.'] +>>> f.clean('8000') +u'8000' + +# CHPhoneNumberField ######################################################## + +>>> from django.contrib.localflavor.ch.forms import CHPhoneNumberField +>>> f = CHPhoneNumberField() +>>> f.clean('01234567890') +Traceback (most recent call last): +... +ValidationError: [u'Phone numbers must be in 0XX XXX XX XX format.'] +>>> f.clean('1234567890') +Traceback (most recent call last): +... +ValidationError: [u'Phone numbers must be in 0XX XXX XX XX format.'] +>>> f.clean('0123456789') +u'012 345 67 89' + +# CHIdentityCardNumberField ################################################# + +>>> from django.contrib.localflavor.ch.forms import CHIdentityCardNumberField +>>> f = CHIdentityCardNumberField() +>>> f.clean('C1234567<0') +u'C1234567<0' +>>> f.clean('C1234567<1') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid Swiss identity or passport card number in X1234567<0 or 1234567890 format.'] +>>> f.clean('2123456700') +u'2123456700' +>>> f.clean('2123456701') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid Swiss identity or passport card number in X1234567<0 or 1234567890 format.'] + +# CHStateSelect ############################################################# + +>>> from django.contrib.localflavor.ch.forms import CHStateSelect +>>> w = CHStateSelect() +>>> w.render('state', 'AG') +u'<select name="state">\n<option value="AG" selected="selected">Aargau</option>\n<option value="AI">Appenzell Innerrhoden</option>\n<option value="AR">Appenzell Ausserrhoden</option>\n<option value="BS">Basel-Stadt</option>\n<option value="BL">Basel-Land</option>\n<option value="BE">Berne</option>\n<option value="FR">Fribourg</option>\n<option value="GE">Geneva</option>\n<option value="GL">Glarus</option>\n<option value="GR">Graubuenden</option>\n<option value="JU">Jura</option>\n<option value="LU">Lucerne</option>\n<option value="NE">Neuchatel</option>\n<option value="NW">Nidwalden</option>\n<option value="OW">Obwalden</option>\n<option value="SH">Schaffhausen</option>\n<option value="SZ">Schwyz</option>\n<option value="SO">Solothurn</option>\n<option value="SG">St. Gallen</option>\n<option value="TG">Thurgau</option>\n<option value="TI">Ticino</option>\n<option value="UR">Uri</option>\n<option value="VS">Valais</option>\n<option value="VD">Vaud</option>\n<option value="ZG">Zug</option>\n<option value="ZH">Zurich</option>\n</select>' +""" diff --git a/tests/regressiontests/forms/localflavor/cl.py b/tests/regressiontests/forms/localflavor/cl.py new file mode 100644 index 0000000000..407f6610e4 --- /dev/null +++ b/tests/regressiontests/forms/localflavor/cl.py @@ -0,0 +1,74 @@ + +# Tests for the contrib/localflavor/ CL form fields. + +tests = r""" +## CLRutField ############################################################# + +CLRutField is a Field that checks the validity of the Chilean +personal identification number (RUT). It has two modes relaxed (default) and +strict. + +>>> from django.contrib.localflavor.cl.forms import CLRutField +>>> rut = CLRutField() + +>>> rut.clean('11-6') +u'11-6' +>>> rut.clean('116') +u'11-6' + +# valid format, bad verifier. +>>> rut.clean('11.111.111-0') +Traceback (most recent call last): +... +ValidationError: [u'The Chilean RUT is not valid.'] +>>> rut.clean('111') +Traceback (most recent call last): +... +ValidationError: [u'The Chilean RUT is not valid.'] + +>>> rut.clean('767484100') +u'76.748.410-0' +>>> rut.clean('78.412.790-7') +u'78.412.790-7' +>>> rut.clean('8.334.6043') +u'8.334.604-3' +>>> rut.clean('76793310-K') +u'76.793.310-K' + +Strict RUT usage (does not allow imposible values) +>>> rut = CLRutField(strict=True) + +>>> rut.clean('11-6') +Traceback (most recent call last): +... +ValidationError: [u'Enter valid a Chilean RUT. The format is XX.XXX.XXX-X.'] + +# valid format, bad verifier. +>>> rut.clean('11.111.111-0') +Traceback (most recent call last): +... +ValidationError: [u'The Chilean RUT is not valid.'] + +# Correct input, invalid format. +>>> rut.clean('767484100') +Traceback (most recent call last): +... +ValidationError: [u'Enter valid a Chilean RUT. The format is XX.XXX.XXX-X.'] +>>> rut.clean('78.412.790-7') +u'78.412.790-7' +>>> rut.clean('8.334.6043') +Traceback (most recent call last): +... +ValidationError: [u'Enter valid a Chilean RUT. The format is XX.XXX.XXX-X.'] +>>> rut.clean('76793310-K') +Traceback (most recent call last): +... +ValidationError: [u'Enter valid a Chilean RUT. The format is XX.XXX.XXX-X.'] + +## CLRegionSelect ######################################################### +>>> from django.contrib.localflavor.cl.forms import CLRegionSelect +>>> f = CLRegionSelect() + +>>> f.render('foo', 'bar') +u'<select name="foo">\n<option value="RM">Regi\xf3n Metropolitana de Santiago</option>\n<option value="I">Regi\xf3n de Tarapac\xe1</option>\n<option value="II">Regi\xf3n de Antofagasta</option>\n<option value="III">Regi\xf3n de Atacama</option>\n<option value="IV">Regi\xf3n de Coquimbo</option>\n<option value="V">Regi\xf3n de Valpara\xedso</option>\n<option value="VI">Regi\xf3n del Libertador Bernardo O'Higgins</option>\n<option value="VII">Regi\xf3n del Maule</option>\n<option value="VIII">Regi\xf3n del B\xedo B\xedo</option>\n<option value="IX">Regi\xf3n de la Araucan\xeda</option>\n<option value="X">Regi\xf3n de los Lagos</option>\n<option value="XI">Regi\xf3n de Ays\xe9n del General Carlos Ib\xe1\xf1ez del Campo</option>\n<option value="XII">Regi\xf3n de Magallanes y la Ant\xe1rtica Chilena</option>\n<option value="XIV">Regi\xf3n de Los R\xedos</option>\n<option value="XV">Regi\xf3n de Arica-Parinacota</option>\n</select>' +""" diff --git a/tests/regressiontests/forms/localflavor/de.py b/tests/regressiontests/forms/localflavor/de.py new file mode 100644 index 0000000000..e02323fc62 --- /dev/null +++ b/tests/regressiontests/forms/localflavor/de.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# Tests for the contrib/localflavor/ DE form fields. + +tests = r""" +# DEZipCodeField ############################################################## + +>>> from django.contrib.localflavor.de.forms import DEZipCodeField +>>> f = DEZipCodeField() +>>> f.clean('99423') +u'99423' +>>> f.clean(' 99423') +Traceback (most recent call last): +... +ValidationError: [u'Enter a zip code in the format XXXXX.'] + +# DEStateSelect ############################################################# + +>>> from django.contrib.localflavor.de.forms import DEStateSelect +>>> w = DEStateSelect() +>>> w.render('states', 'TH') +u'<select name="states">\n<option value="BW">Baden-Wuerttemberg</option>\n<option value="BY">Bavaria</option>\n<option value="BE">Berlin</option>\n<option value="BB">Brandenburg</option>\n<option value="HB">Bremen</option>\n<option value="HH">Hamburg</option>\n<option value="HE">Hessen</option>\n<option value="MV">Mecklenburg-Western Pomerania</option>\n<option value="NI">Lower Saxony</option>\n<option value="NW">North Rhine-Westphalia</option>\n<option value="RP">Rhineland-Palatinate</option>\n<option value="SL">Saarland</option>\n<option value="SN">Saxony</option>\n<option value="ST">Saxony-Anhalt</option>\n<option value="SH">Schleswig-Holstein</option>\n<option value="TH" selected="selected">Thuringia</option>\n</select>' + +# DEIdentityCardNumberField ################################################# + +>>> from django.contrib.localflavor.de.forms import DEIdentityCardNumberField +>>> f = DEIdentityCardNumberField() +>>> f.clean('7549313035D-6004103-0903042-0') +u'7549313035D-6004103-0903042-0' +>>> f.clean('9786324830D 6104243 0910271 2') +u'9786324830D-6104243-0910271-2' +>>> f.clean('0434657485D-6407276-0508137-9') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid German identity card number in XXXXXXXXXXX-XXXXXXX-XXXXXXX-X format.'] +""" diff --git a/tests/regressiontests/forms/localflavor/fi.py b/tests/regressiontests/forms/localflavor/fi.py new file mode 100644 index 0000000000..f29fcc3c69 --- /dev/null +++ b/tests/regressiontests/forms/localflavor/fi.py @@ -0,0 +1,99 @@ +# -*- coding: utf-8 -*- +# Tests for the contrib/localflavor/ FI form fields. + +tests = r""" +# FIZipCodeField ############################################################# + +FIZipCodeField validates that the data is a valid FI zipcode. +>>> from django.contrib.localflavor.fi.forms import FIZipCodeField +>>> f = FIZipCodeField() +>>> f.clean('20540') +u'20540' +>>> f.clean('20101') +u'20101' +>>> f.clean('20s40') +Traceback (most recent call last): +... +ValidationError: [u'Enter a zip code in the format XXXXX.'] +>>> f.clean('205401') +Traceback (most recent call last): +... +ValidationError: [u'Enter a zip code in the format XXXXX.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] + +>>> f = FIZipCodeField(required=False) +>>> f.clean('20540') +u'20540' +>>> f.clean('20101') +u'20101' +>>> f.clean('20s40') +Traceback (most recent call last): +... +ValidationError: [u'Enter a zip code in the format XXXXX.'] +>>> f.clean('205401') +Traceback (most recent call last): +... +ValidationError: [u'Enter a zip code in the format XXXXX.'] +>>> f.clean(None) +u'' +>>> f.clean('') +u'' + +# FIMunicipalitySelect ############################################################### + +A Select widget that uses a list of Finnish municipalities as its choices. +>>> from django.contrib.localflavor.fi.forms import FIMunicipalitySelect +>>> w = FIMunicipalitySelect() +>>> unicode(w.render('municipalities', 'turku')) +u'<select name="municipalities">\n<option value="akaa">Akaa</option>\n<option value="alaharma">Alah\xe4rm\xe4</option>\n<option value="alajarvi">Alaj\xe4rvi</option>\n<option value="alastaro">Alastaro</option>\n<option value="alavieska">Alavieska</option>\n<option value="alavus">Alavus</option>\n<option value="anjalankoski">Anjalankoski</option>\n<option value="artjarvi">Artj\xe4rvi</option>\n<option value="asikkala">Asikkala</option>\n<option value="askainen">Askainen</option>\n<option value="askola">Askola</option>\n<option value="aura">Aura</option>\n<option value="brando">Br\xe4nd\xf6</option>\n<option value="dragsfjard">Dragsfj\xe4rd</option>\n<option value="eckero">Ecker\xf6</option>\n<option value="elimaki">Elim\xe4ki</option>\n<option value="eno">Eno</option>\n<option value="enonkoski">Enonkoski</option>\n<option value="enontekio">Enonteki\xf6</option>\n<option value="espoo">Espoo</option>\n<option value="eura">Eura</option>\n<option value="eurajoki">Eurajoki</option>\n<option value="evijarvi">Evij\xe4rvi</option>\n<option value="finstrom">Finstr\xf6m</option>\n<option value="forssa">Forssa</option>\n<option value="foglo">F\xf6gl\xf6</option>\n<option value="geta">Geta</option>\n<option value="haapajarvi">Haapaj\xe4rvi</option>\n<option value="haapavesi">Haapavesi</option>\n<option value="hailuoto">Hailuoto</option>\n<option value="halikko">Halikko</option>\n<option value="halsua">Halsua</option>\n<option value="hamina">Hamina</option>\n<option value="hammarland">Hammarland</option>\n<option value="hankasalmi">Hankasalmi</option>\n<option value="hanko">Hanko</option>\n<option value="harjavalta">Harjavalta</option>\n<option value="hartola">Hartola</option>\n<option value="hattula">Hattula</option>\n<option value="hauho">Hauho</option>\n<option value="haukipudas">Haukipudas</option>\n<option value="hausjarvi">Hausj\xe4rvi</option>\n<option value="heinola">Heinola</option>\n<option value="heinavesi">Hein\xe4vesi</option>\n<option value="helsinki">Helsinki</option>\n<option value="himanka">Himanka</option>\n<option value="hirvensalmi">Hirvensalmi</option>\n<option value="hollola">Hollola</option>\n<option value="honkajoki">Honkajoki</option>\n<option value="houtskari">Houtskari</option>\n<option value="huittinen">Huittinen</option>\n<option value="humppila">Humppila</option>\n<option value="hyrynsalmi">Hyrynsalmi</option>\n<option value="hyvinkaa">Hyvink\xe4\xe4</option>\n<option value="hameenkoski">H\xe4meenkoski</option>\n<option value="hameenkyro">H\xe4meenkyr\xf6</option>\n<option value="hameenlinna">H\xe4meenlinna</option>\n<option value="ii">Ii</option>\n<option value="iisalmi">Iisalmi</option>\n<option value="iitti">Iitti</option>\n<option value="ikaalinen">Ikaalinen</option>\n<option value="ilmajoki">Ilmajoki</option>\n<option value="ilomantsi">Ilomantsi</option>\n<option value="imatra">Imatra</option>\n<option value="inari">Inari</option>\n<option value="inio">Ini\xf6</option>\n<option value="inkoo">Inkoo</option>\n<option value="isojoki">Isojoki</option>\n<option value="isokyro">Isokyr\xf6</option>\n<option value="jaala">Jaala</option>\n<option value="jalasjarvi">Jalasj\xe4rvi</option>\n<option value="janakkala">Janakkala</option>\n<option value="joensuu">Joensuu</option>\n<option value="jokioinen">Jokioinen</option>\n<option value="jomala">Jomala</option>\n<option value="joroinen">Joroinen</option>\n<option value="joutsa">Joutsa</option>\n<option value="joutseno">Joutseno</option>\n<option value="juankoski">Juankoski</option>\n<option value="jurva">Jurva</option>\n<option value="juuka">Juuka</option>\n<option value="juupajoki">Juupajoki</option>\n<option value="juva">Juva</option>\n<option value="jyvaskyla">Jyv\xe4skyl\xe4</option>\n<option value="jyvaskylan_mlk">Jyv\xe4skyl\xe4n maalaiskunta</option>\n<option value="jamijarvi">J\xe4mij\xe4rvi</option>\n<option value="jamsa">J\xe4ms\xe4</option>\n<option value="jamsankoski">J\xe4ms\xe4nkoski</option>\n<option value="jarvenpaa">J\xe4rvenp\xe4\xe4</option>\n<option value="kaarina">Kaarina</option>\n<option value="kaavi">Kaavi</option>\n<option value="kajaani">Kajaani</option>\n<option value="kalajoki">Kalajoki</option>\n<option value="kalvola">Kalvola</option>\n<option value="kangasala">Kangasala</option>\n<option value="kangasniemi">Kangasniemi</option>\n<option value="kankaanpaa">Kankaanp\xe4\xe4</option>\n<option value="kannonkoski">Kannonkoski</option>\n<option value="kannus">Kannus</option>\n<option value="karijoki">Karijoki</option>\n<option value="karjaa">Karjaa</option>\n<option value="karjalohja">Karjalohja</option>\n<option value="karkkila">Karkkila</option>\n<option value="karstula">Karstula</option>\n<option value="karttula">Karttula</option>\n<option value="karvia">Karvia</option>\n<option value="kaskinen">Kaskinen</option>\n<option value="kauhajoki">Kauhajoki</option>\n<option value="kauhava">Kauhava</option>\n<option value="kauniainen">Kauniainen</option>\n<option value="kaustinen">Kaustinen</option>\n<option value="keitele">Keitele</option>\n<option value="kemi">Kemi</option>\n<option value="kemijarvi">Kemij\xe4rvi</option>\n<option value="keminmaa">Keminmaa</option>\n<option value="kemio">Kemi\xf6</option>\n<option value="kempele">Kempele</option>\n<option value="kerava">Kerava</option>\n<option value="kerimaki">Kerim\xe4ki</option>\n<option value="kestila">Kestil\xe4</option>\n<option value="kesalahti">Kes\xe4lahti</option>\n<option value="keuruu">Keuruu</option>\n<option value="kihnio">Kihni\xf6</option>\n<option value="kiikala">Kiikala</option>\n<option value="kiikoinen">Kiikoinen</option>\n<option value="kiiminki">Kiiminki</option>\n<option value="kinnula">Kinnula</option>\n<option value="kirkkonummi">Kirkkonummi</option>\n<option value="kisko">Kisko</option>\n<option value="kitee">Kitee</option>\n<option value="kittila">Kittil\xe4</option>\n<option value="kiukainen">Kiukainen</option>\n<option value="kiuruvesi">Kiuruvesi</option>\n<option value="kivijarvi">Kivij\xe4rvi</option>\n<option value="kokemaki">Kokem\xe4ki</option>\n<option value="kokkola">Kokkola</option>\n<option value="kolari">Kolari</option>\n<option value="konnevesi">Konnevesi</option>\n<option value="kontiolahti">Kontiolahti</option>\n<option value="korpilahti">Korpilahti</option>\n<option value="korppoo">Korppoo</option>\n<option value="korsnas">Korsn\xe4s</option>\n<option value="kortesjarvi">Kortesj\xe4rvi</option>\n<option value="koskitl">KoskiTl</option>\n<option value="kotka">Kotka</option>\n<option value="kouvola">Kouvola</option>\n<option value="kristiinankaupunki">Kristiinankaupunki</option>\n<option value="kruunupyy">Kruunupyy</option>\n<option value="kuhmalahti">Kuhmalahti</option>\n<option value="kuhmo">Kuhmo</option>\n<option value="kuhmoinen">Kuhmoinen</option>\n<option value="kumlinge">Kumlinge</option>\n<option value="kuopio">Kuopio</option>\n<option value="kuortane">Kuortane</option>\n<option value="kurikka">Kurikka</option>\n<option value="kuru">Kuru</option>\n<option value="kustavi">Kustavi</option>\n<option value="kuusamo">Kuusamo</option>\n<option value="kuusankoski">Kuusankoski</option>\n<option value="kuusjoki">Kuusjoki</option>\n<option value="kylmakoski">Kylm\xe4koski</option>\n<option value="kyyjarvi">Kyyj\xe4rvi</option>\n<option value="kalvia">K\xe4lvi\xe4</option>\n<option value="karkola">K\xe4rk\xf6l\xe4</option>\n<option value="karsamaki">K\xe4rs\xe4m\xe4ki</option>\n<option value="kokar">K\xf6kar</option>\n<option value="koylio">K\xf6yli\xf6</option>\n<option value="lahti">Lahti</option>\n<option value="laihia">Laihia</option>\n<option value="laitila">Laitila</option>\n<option value="lammi">Lammi</option>\n<option value="lapinjarvi">Lapinj\xe4rvi</option>\n<option value="lapinlahti">Lapinlahti</option>\n<option value="lappajarvi">Lappaj\xe4rvi</option>\n<option value="lappeenranta">Lappeenranta</option>\n<option value="lappi">Lappi</option>\n<option value="lapua">Lapua</option>\n<option value="laukaa">Laukaa</option>\n<option value="lavia">Lavia</option>\n<option value="lehtimaki">Lehtim\xe4ki</option>\n<option value="leivonmaki">Leivonm\xe4ki</option>\n<option value="lemi">Lemi</option>\n<option value="lemland">Lemland</option>\n<option value="lempaala">Lemp\xe4\xe4l\xe4</option>\n<option value="lemu">Lemu</option>\n<option value="leppavirta">Lepp\xe4virta</option>\n<option value="lestijarvi">Lestij\xe4rvi</option>\n<option value="lieksa">Lieksa</option>\n<option value="lieto">Lieto</option>\n<option value="liljendal">Liljendal</option>\n<option value="liminka">Liminka</option>\n<option value="liperi">Liperi</option>\n<option value="lohja">Lohja</option>\n<option value="lohtaja">Lohtaja</option>\n<option value="loimaa">Loimaa</option>\n<option value="loppi">Loppi</option>\n<option value="loviisa">Loviisa</option>\n<option value="luhanka">Luhanka</option>\n<option value="lumijoki">Lumijoki</option>\n<option value="lumparland">Lumparland</option>\n<option value="luoto">Luoto</option>\n<option value="luumaki">Luum\xe4ki</option>\n<option value="luvia">Luvia</option>\n<option value="maalahti">Maalahti</option>\n<option value="maaninka">Maaninka</option>\n<option value="maarianhamina">Maarianhamina</option>\n<option value="marttila">Marttila</option>\n<option value="masku">Masku</option>\n<option value="mellila">Mellil\xe4</option>\n<option value="merijarvi">Merij\xe4rvi</option>\n<option value="merikarvia">Merikarvia</option>\n<option value="merimasku">Merimasku</option>\n<option value="miehikkala">Miehikk\xe4l\xe4</option>\n<option value="mikkeli">Mikkeli</option>\n<option value="mouhijarvi">Mouhij\xe4rvi</option>\n<option value="muhos">Muhos</option>\n<option value="multia">Multia</option>\n<option value="muonio">Muonio</option>\n<option value="mustasaari">Mustasaari</option>\n<option value="muurame">Muurame</option>\n<option value="muurla">Muurla</option>\n<option value="mynamaki">Myn\xe4m\xe4ki</option>\n<option value="myrskyla">Myrskyl\xe4</option>\n<option value="mantsala">M\xe4nts\xe4l\xe4</option>\n<option value="mantta">M\xe4ntt\xe4</option>\n<option value="mantyharju">M\xe4ntyharju</option>\n<option value="naantali">Naantali</option>\n<option value="nakkila">Nakkila</option>\n<option value="nastola">Nastola</option>\n<option value="nauvo">Nauvo</option>\n<option value="nilsia">Nilsi\xe4</option>\n<option value="nivala">Nivala</option>\n<option value="nokia">Nokia</option>\n<option value="noormarkku">Noormarkku</option>\n<option value="nousiainen">Nousiainen</option>\n<option value="nummi-pusula">Nummi-Pusula</option>\n<option value="nurmes">Nurmes</option>\n<option value="nurmijarvi">Nurmij\xe4rvi</option>\n<option value="nurmo">Nurmo</option>\n<option value="narpio">N\xe4rpi\xf6</option>\n<option value="oravainen">Oravainen</option>\n<option value="orimattila">Orimattila</option>\n<option value="oripaa">Orip\xe4\xe4</option>\n<option value="orivesi">Orivesi</option>\n<option value="oulainen">Oulainen</option>\n<option value="oulu">Oulu</option>\n<option value="oulunsalo">Oulunsalo</option>\n<option value="outokumpu">Outokumpu</option>\n<option value="padasjoki">Padasjoki</option>\n<option value="paimio">Paimio</option>\n<option value="paltamo">Paltamo</option>\n<option value="parainen">Parainen</option>\n<option value="parikkala">Parikkala</option>\n<option value="parkano">Parkano</option>\n<option value="pedersore">Peders\xf6re</option>\n<option value="pelkosenniemi">Pelkosenniemi</option>\n<option value="pello">Pello</option>\n<option value="perho">Perho</option>\n<option value="pernaja">Pernaja</option>\n<option value="pernio">Perni\xf6</option>\n<option value="pertteli">Pertteli</option>\n<option value="pertunmaa">Pertunmaa</option>\n<option value="petajavesi">Pet\xe4j\xe4vesi</option>\n<option value="pieksamaki">Pieks\xe4m\xe4ki</option>\n<option value="pielavesi">Pielavesi</option>\n<option value="pietarsaari">Pietarsaari</option>\n<option value="pihtipudas">Pihtipudas</option>\n<option value="piikkio">Piikki\xf6</option>\n<option value="piippola">Piippola</option>\n<option value="pirkkala">Pirkkala</option>\n<option value="pohja">Pohja</option>\n<option value="polvijarvi">Polvij\xe4rvi</option>\n<option value="pomarkku">Pomarkku</option>\n<option value="pori">Pori</option>\n<option value="pornainen">Pornainen</option>\n<option value="porvoo">Porvoo</option>\n<option value="posio">Posio</option>\n<option value="pudasjarvi">Pudasj\xe4rvi</option>\n<option value="pukkila">Pukkila</option>\n<option value="pulkkila">Pulkkila</option>\n<option value="punkaharju">Punkaharju</option>\n<option value="punkalaidun">Punkalaidun</option>\n<option value="puolanka">Puolanka</option>\n<option value="puumala">Puumala</option>\n<option value="pyhtaa">Pyht\xe4\xe4</option>\n<option value="pyhajoki">Pyh\xe4joki</option>\n<option value="pyhajarvi">Pyh\xe4j\xe4rvi</option>\n<option value="pyhanta">Pyh\xe4nt\xe4</option>\n<option value="pyharanta">Pyh\xe4ranta</option>\n<option value="pyhaselka">Pyh\xe4selk\xe4</option>\n<option value="pylkonmaki">Pylk\xf6nm\xe4ki</option>\n<option value="palkane">P\xe4lk\xe4ne</option>\n<option value="poytya">P\xf6yty\xe4</option>\n<option value="raahe">Raahe</option>\n<option value="raisio">Raisio</option>\n<option value="rantasalmi">Rantasalmi</option>\n<option value="rantsila">Rantsila</option>\n<option value="ranua">Ranua</option>\n<option value="rauma">Rauma</option>\n<option value="rautalampi">Rautalampi</option>\n<option value="rautavaara">Rautavaara</option>\n<option value="rautjarvi">Rautj\xe4rvi</option>\n<option value="reisjarvi">Reisj\xe4rvi</option>\n<option value="renko">Renko</option>\n<option value="riihimaki">Riihim\xe4ki</option>\n<option value="ristiina">Ristiina</option>\n<option value="ristijarvi">Ristij\xe4rvi</option>\n<option value="rovaniemi">Rovaniemi</option>\n<option value="ruokolahti">Ruokolahti</option>\n<option value="ruotsinpyhtaa">Ruotsinpyht\xe4\xe4</option>\n<option value="ruovesi">Ruovesi</option>\n<option value="rusko">Rusko</option>\n<option value="rymattyla">Rym\xe4ttyl\xe4</option>\n<option value="raakkyla">R\xe4\xe4kkyl\xe4</option>\n<option value="saarijarvi">Saarij\xe4rvi</option>\n<option value="salla">Salla</option>\n<option value="salo">Salo</option>\n<option value="saltvik">Saltvik</option>\n<option value="sammatti">Sammatti</option>\n<option value="sauvo">Sauvo</option>\n<option value="savitaipale">Savitaipale</option>\n<option value="savonlinna">Savonlinna</option>\n<option value="savonranta">Savonranta</option>\n<option value="savukoski">Savukoski</option>\n<option value="seinajoki">Sein\xe4joki</option>\n<option value="sievi">Sievi</option>\n<option value="siikainen">Siikainen</option>\n<option value="siikajoki">Siikajoki</option>\n<option value="siilinjarvi">Siilinj\xe4rvi</option>\n<option value="simo">Simo</option>\n<option value="sipoo">Sipoo</option>\n<option value="siuntio">Siuntio</option>\n<option value="sodankyla">Sodankyl\xe4</option>\n<option value="soini">Soini</option>\n<option value="somero">Somero</option>\n<option value="sonkajarvi">Sonkaj\xe4rvi</option>\n<option value="sotkamo">Sotkamo</option>\n<option value="sottunga">Sottunga</option>\n<option value="sulkava">Sulkava</option>\n<option value="sund">Sund</option>\n<option value="suomenniemi">Suomenniemi</option>\n<option value="suomusjarvi">Suomusj\xe4rvi</option>\n<option value="suomussalmi">Suomussalmi</option>\n<option value="suonenjoki">Suonenjoki</option>\n<option value="sysma">Sysm\xe4</option>\n<option value="sakyla">S\xe4kyl\xe4</option>\n<option value="sarkisalo">S\xe4rkisalo</option>\n<option value="taipalsaari">Taipalsaari</option>\n<option value="taivalkoski">Taivalkoski</option>\n<option value="taivassalo">Taivassalo</option>\n<option value="tammela">Tammela</option>\n<option value="tammisaari">Tammisaari</option>\n<option value="tampere">Tampere</option>\n<option value="tarvasjoki">Tarvasjoki</option>\n<option value="tervo">Tervo</option>\n<option value="tervola">Tervola</option>\n<option value="teuva">Teuva</option>\n<option value="tohmajarvi">Tohmaj\xe4rvi</option>\n<option value="toholampi">Toholampi</option>\n<option value="toivakka">Toivakka</option>\n<option value="tornio">Tornio</option>\n<option value="turku" selected="selected">Turku</option>\n<option value="tuulos">Tuulos</option>\n<option value="tuusniemi">Tuusniemi</option>\n<option value="tuusula">Tuusula</option>\n<option value="tyrnava">Tyrn\xe4v\xe4</option>\n<option value="toysa">T\xf6ys\xe4</option>\n<option value="ullava">Ullava</option>\n<option value="ulvila">Ulvila</option>\n<option value="urjala">Urjala</option>\n<option value="utajarvi">Utaj\xe4rvi</option>\n<option value="utsjoki">Utsjoki</option>\n<option value="uurainen">Uurainen</option>\n<option value="uusikaarlepyy">Uusikaarlepyy</option>\n<option value="uusikaupunki">Uusikaupunki</option>\n<option value="vaala">Vaala</option>\n<option value="vaasa">Vaasa</option>\n<option value="vahto">Vahto</option>\n<option value="valkeakoski">Valkeakoski</option>\n<option value="valkeala">Valkeala</option>\n<option value="valtimo">Valtimo</option>\n<option value="vammala">Vammala</option>\n<option value="vampula">Vampula</option>\n<option value="vantaa">Vantaa</option>\n<option value="varkaus">Varkaus</option>\n<option value="varpaisjarvi">Varpaisj\xe4rvi</option>\n<option value="vehmaa">Vehmaa</option>\n<option value="velkua">Velkua</option>\n<option value="vesanto">Vesanto</option>\n<option value="vesilahti">Vesilahti</option>\n<option value="veteli">Veteli</option>\n<option value="vierema">Vierem\xe4</option>\n<option value="vihanti">Vihanti</option>\n<option value="vihti">Vihti</option>\n<option value="viitasaari">Viitasaari</option>\n<option value="vilppula">Vilppula</option>\n<option value="vimpeli">Vimpeli</option>\n<option value="virolahti">Virolahti</option>\n<option value="virrat">Virrat</option>\n<option value="vardo">V\xe5rd\xf6</option>\n<option value="vahakyro">V\xe4h\xe4kyr\xf6</option>\n<option value="vastanfjard">V\xe4stanfj\xe4rd</option>\n<option value="voyri-maksamaa">V\xf6yri-Maksamaa</option>\n<option value="yliharma">Ylih\xe4rm\xe4</option>\n<option value="yli-ii">Yli-Ii</option>\n<option value="ylikiiminki">Ylikiiminki</option>\n<option value="ylistaro">Ylistaro</option>\n<option value="ylitornio">Ylitornio</option>\n<option value="ylivieska">Ylivieska</option>\n<option value="ylamaa">Yl\xe4maa</option>\n<option value="ylane">Yl\xe4ne</option>\n<option value="ylojarvi">Yl\xf6j\xe4rvi</option>\n<option value="ypaja">Yp\xe4j\xe4</option>\n<option value="aetsa">\xc4ets\xe4</option>\n<option value="ahtari">\xc4ht\xe4ri</option>\n<option value="aanekoski">\xc4\xe4nekoski</option>\n</select>' + +# FISocialSecurityNumber ############################################################## + +>>> from django.contrib.localflavor.fi.forms import FISocialSecurityNumber +>>> f = FISocialSecurityNumber() +>>> f.clean('010101-0101') +u'010101-0101' +>>> f.clean('010101+0101') +u'010101+0101' +>>> f.clean('010101A0101') +u'010101A0101' +>>> f.clean('101010-0102') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid Finnish social security number.'] +>>> f.clean('10a010-0101') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid Finnish social security number.'] +>>> f.clean('101010-0\xe401') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid Finnish social security number.'] +>>> f.clean('101010b0101') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid Finnish social security number.'] +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] + +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f = FISocialSecurityNumber(required=False) +>>> f.clean('010101-0101') +u'010101-0101' +>>> f.clean(None) +u'' +>>> f.clean('') +u'' +""" diff --git a/tests/regressiontests/forms/localflavor/fr.py b/tests/regressiontests/forms/localflavor/fr.py new file mode 100644 index 0000000000..ea6c7899aa --- /dev/null +++ b/tests/regressiontests/forms/localflavor/fr.py @@ -0,0 +1,224 @@ +# -*- coding: utf-8 -*- +# Tests for the contrib/localflavor/ FR form fields. + +tests = r""" +# FRZipCodeField ############################################################# + +FRZipCodeField validates that the data is a valid FR zipcode. +>>> from django.contrib.localflavor.fr.forms import FRZipCodeField +>>> f = FRZipCodeField() +>>> f.clean('75001') +u'75001' +>>> f.clean('93200') +u'93200' +>>> f.clean('2A200') +Traceback (most recent call last): +... +ValidationError: [u'Enter a zip code in the format XXXXX.'] +>>> f.clean('980001') +Traceback (most recent call last): +... +ValidationError: [u'Enter a zip code in the format XXXXX.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] + +>>> f = FRZipCodeField(required=False) +>>> f.clean('75001') +u'75001' +>>> f.clean('93200') +u'93200' +>>> f.clean('2A200') +Traceback (most recent call last): +... +ValidationError: [u'Enter a zip code in the format XXXXX.'] +>>> f.clean('980001') +Traceback (most recent call last): +... +ValidationError: [u'Enter a zip code in the format XXXXX.'] +>>> f.clean(None) +u'' +>>> f.clean('') +u'' + + +# FRPhoneNumberField ########################################################## + +FRPhoneNumberField validates that the data is a valid french phone number. +It's normalized to 0X XX XX XX XX format. Dots are valid too. +>>> from django.contrib.localflavor.fr.forms import FRPhoneNumberField +>>> f = FRPhoneNumberField() +>>> f.clean('01 55 44 58 64') +u'01 55 44 58 64' +>>> f.clean('0155445864') +u'01 55 44 58 64' +>>> f.clean('01 5544 5864') +u'01 55 44 58 64' +>>> f.clean('01 55.44.58.64') +u'01 55 44 58 64' +>>> f.clean('01.55.44.58.64') +u'01 55 44 58 64' +>>> f.clean('01,55,44,58,64') +Traceback (most recent call last): +... +ValidationError: [u'Phone numbers must be in 0X XX XX XX XX format.'] +>>> f.clean('555 015 544') +Traceback (most recent call last): +... +ValidationError: [u'Phone numbers must be in 0X XX XX XX XX format.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] + +>>> f = FRPhoneNumberField(required=False) +>>> f.clean('01 55 44 58 64') +u'01 55 44 58 64' +>>> f.clean('0155445864') +u'01 55 44 58 64' +>>> f.clean('01 5544 5864') +u'01 55 44 58 64' +>>> f.clean('01 55.44.58.64') +u'01 55 44 58 64' +>>> f.clean('01.55.44.58.64') +u'01 55 44 58 64' +>>> f.clean('01,55,44,58,64') +Traceback (most recent call last): +... +ValidationError: [u'Phone numbers must be in 0X XX XX XX XX format.'] +>>> f.clean('555 015 544') +Traceback (most recent call last): +... +ValidationError: [u'Phone numbers must be in 0X XX XX XX XX format.'] +>>> f.clean(None) +u'' +>>> f.clean('') +u'' + +# FRDepartmentSelect ############################################################### + +FRDepartmentSelect is a Select widget that uses a list of french departments +including DOM TOM +>>> from django.contrib.localflavor.fr.forms import FRDepartmentSelect +>>> w = FRDepartmentSelect() +>>> print w.render('dep', 'Paris') +<select name="dep"> +<option value="01">01 - Ain</option> +<option value="02">02 - Aisne</option> +<option value="03">03 - Allier</option> +<option value="04">04 - Alpes-de-Haute-Provence</option> +<option value="05">05 - Hautes-Alpes</option> +<option value="06">06 - Alpes-Maritimes</option> +<option value="07">07 - Ardeche</option> +<option value="08">08 - Ardennes</option> +<option value="09">09 - Ariege</option> +<option value="10">10 - Aube</option> +<option value="11">11 - Aude</option> +<option value="12">12 - Aveyron</option> +<option value="13">13 - Bouches-du-Rhone</option> +<option value="14">14 - Calvados</option> +<option value="15">15 - Cantal</option> +<option value="16">16 - Charente</option> +<option value="17">17 - Charente-Maritime</option> +<option value="18">18 - Cher</option> +<option value="19">19 - Correze</option> +<option value="21">21 - Cote-d'Or</option> +<option value="22">22 - Cotes-d'Armor</option> +<option value="23">23 - Creuse</option> +<option value="24">24 - Dordogne</option> +<option value="25">25 - Doubs</option> +<option value="26">26 - Drome</option> +<option value="27">27 - Eure</option> +<option value="28">28 - Eure-et-Loire</option> +<option value="29">29 - Finistere</option> +<option value="2A">2A - Corse-du-Sud</option> +<option value="2B">2B - Haute-Corse</option> +<option value="30">30 - Gard</option> +<option value="31">31 - Haute-Garonne</option> +<option value="32">32 - Gers</option> +<option value="33">33 - Gironde</option> +<option value="34">34 - Herault</option> +<option value="35">35 - Ille-et-Vilaine</option> +<option value="36">36 - Indre</option> +<option value="37">37 - Indre-et-Loire</option> +<option value="38">38 - Isere</option> +<option value="39">39 - Jura</option> +<option value="40">40 - Landes</option> +<option value="41">41 - Loir-et-Cher</option> +<option value="42">42 - Loire</option> +<option value="43">43 - Haute-Loire</option> +<option value="44">44 - Loire-Atlantique</option> +<option value="45">45 - Loiret</option> +<option value="46">46 - Lot</option> +<option value="47">47 - Lot-et-Garonne</option> +<option value="48">48 - Lozere</option> +<option value="49">49 - Maine-et-Loire</option> +<option value="50">50 - Manche</option> +<option value="51">51 - Marne</option> +<option value="52">52 - Haute-Marne</option> +<option value="53">53 - Mayenne</option> +<option value="54">54 - Meurthe-et-Moselle</option> +<option value="55">55 - Meuse</option> +<option value="56">56 - Morbihan</option> +<option value="57">57 - Moselle</option> +<option value="58">58 - Nievre</option> +<option value="59">59 - Nord</option> +<option value="60">60 - Oise</option> +<option value="61">61 - Orne</option> +<option value="62">62 - Pas-de-Calais</option> +<option value="63">63 - Puy-de-Dome</option> +<option value="64">64 - Pyrenees-Atlantiques</option> +<option value="65">65 - Hautes-Pyrenees</option> +<option value="66">66 - Pyrenees-Orientales</option> +<option value="67">67 - Bas-Rhin</option> +<option value="68">68 - Haut-Rhin</option> +<option value="69">69 - Rhone</option> +<option value="70">70 - Haute-Saone</option> +<option value="71">71 - Saone-et-Loire</option> +<option value="72">72 - Sarthe</option> +<option value="73">73 - Savoie</option> +<option value="74">74 - Haute-Savoie</option> +<option value="75">75 - Paris</option> +<option value="76">76 - Seine-Maritime</option> +<option value="77">77 - Seine-et-Marne</option> +<option value="78">78 - Yvelines</option> +<option value="79">79 - Deux-Sevres</option> +<option value="80">80 - Somme</option> +<option value="81">81 - Tarn</option> +<option value="82">82 - Tarn-et-Garonne</option> +<option value="83">83 - Var</option> +<option value="84">84 - Vaucluse</option> +<option value="85">85 - Vendee</option> +<option value="86">86 - Vienne</option> +<option value="87">87 - Haute-Vienne</option> +<option value="88">88 - Vosges</option> +<option value="89">89 - Yonne</option> +<option value="90">90 - Territoire de Belfort</option> +<option value="91">91 - Essonne</option> +<option value="92">92 - Hauts-de-Seine</option> +<option value="93">93 - Seine-Saint-Denis</option> +<option value="94">94 - Val-de-Marne</option> +<option value="95">95 - Val-d'Oise</option> +<option value="2A">2A - Corse du sud</option> +<option value="2B">2B - Haute Corse</option> +<option value="971">971 - Guadeloupe</option> +<option value="972">972 - Martinique</option> +<option value="973">973 - Guyane</option> +<option value="974">974 - La Reunion</option> +<option value="975">975 - Saint-Pierre-et-Miquelon</option> +<option value="976">976 - Mayotte</option> +<option value="984">984 - Terres Australes et Antarctiques</option> +<option value="986">986 - Wallis et Futuna</option> +<option value="987">987 - Polynesie Francaise</option> +<option value="988">988 - Nouvelle-Caledonie</option> +</select> +""" diff --git a/tests/regressiontests/forms/localflavor/generic.py b/tests/regressiontests/forms/localflavor/generic.py new file mode 100644 index 0000000000..0dbe30d709 --- /dev/null +++ b/tests/regressiontests/forms/localflavor/generic.py @@ -0,0 +1,163 @@ +# -*- coding: utf-8 -*- +# Tests for the contrib/localflavor/ generic form fields. + +tests = r""" +## Generic DateField ########################################################## + +>>> from django.contrib.localflavor.generic.forms import * + +A DateField that uses generic dd/mm/yy dates instead of mm/dd/yy where +appropriate. + +>>> import datetime +>>> f = DateField() +>>> f.clean(datetime.date(2006, 10, 25)) +datetime.date(2006, 10, 25) +>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30)) +datetime.date(2006, 10, 25) +>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59)) +datetime.date(2006, 10, 25) +>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59, 200)) +datetime.date(2006, 10, 25) +>>> f.clean('2006-10-25') +datetime.date(2006, 10, 25) +>>> f.clean('25/10/2006') +datetime.date(2006, 10, 25) +>>> f.clean('25/10/06') +datetime.date(2006, 10, 25) +>>> f.clean('Oct 25 2006') +datetime.date(2006, 10, 25) +>>> f.clean('October 25 2006') +datetime.date(2006, 10, 25) +>>> f.clean('October 25, 2006') +datetime.date(2006, 10, 25) +>>> f.clean('25 October 2006') +datetime.date(2006, 10, 25) +>>> f.clean('25 October, 2006') +datetime.date(2006, 10, 25) +>>> f.clean('2006-4-31') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid date.'] +>>> f.clean('200a-10-25') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid date.'] +>>> f.clean('10/25/06') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid date.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] + +>>> f = DateField(required=False) +>>> f.clean(None) +>>> repr(f.clean(None)) +'None' +>>> f.clean('') +>>> repr(f.clean('')) +'None' + +DateField accepts an optional input_formats parameter: +>>> f = DateField(input_formats=['%Y %m %d']) +>>> f.clean(datetime.date(2006, 10, 25)) +datetime.date(2006, 10, 25) +>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30)) +datetime.date(2006, 10, 25) +>>> f.clean('2006 10 25') +datetime.date(2006, 10, 25) + +The input_formats parameter overrides all default input formats, +so the default formats won't work unless you specify them: +>>> f.clean('2006-10-25') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid date.'] +>>> f.clean('25/10/2006') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid date.'] +>>> f.clean('25/10/06') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid date.'] + +## Generic DateTimeField ###################################################### + +A DateField that uses generic dd/mm/yy dates instead of mm/dd/yy where +appropriate. + +>>> import datetime +>>> f = DateTimeField() +>>> f.clean(datetime.date(2006, 10, 25)) +datetime.datetime(2006, 10, 25, 0, 0) +>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30)) +datetime.datetime(2006, 10, 25, 14, 30) +>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59)) +datetime.datetime(2006, 10, 25, 14, 30, 59) +>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59, 200)) +datetime.datetime(2006, 10, 25, 14, 30, 59, 200) +>>> f.clean('2006-10-25 14:30:45') +datetime.datetime(2006, 10, 25, 14, 30, 45) +>>> f.clean('2006-10-25 14:30:00') +datetime.datetime(2006, 10, 25, 14, 30) +>>> f.clean('2006-10-25 14:30') +datetime.datetime(2006, 10, 25, 14, 30) +>>> f.clean('2006-10-25') +datetime.datetime(2006, 10, 25, 0, 0) +>>> f.clean('25/10/2006 14:30:45') +datetime.datetime(2006, 10, 25, 14, 30, 45) +>>> f.clean('25/10/2006 14:30:00') +datetime.datetime(2006, 10, 25, 14, 30) +>>> f.clean('25/10/2006 14:30') +datetime.datetime(2006, 10, 25, 14, 30) +>>> f.clean('25/10/2006') +datetime.datetime(2006, 10, 25, 0, 0) +>>> f.clean('25/10/06 14:30:45') +datetime.datetime(2006, 10, 25, 14, 30, 45) +>>> f.clean('25/10/06 14:30:00') +datetime.datetime(2006, 10, 25, 14, 30) +>>> f.clean('25/10/06 14:30') +datetime.datetime(2006, 10, 25, 14, 30) +>>> f.clean('25/10/06') +datetime.datetime(2006, 10, 25, 0, 0) +>>> f.clean('hello') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid date/time.'] +>>> f.clean('2006-10-25 4:30 p.m.') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid date/time.'] + +DateField accepts an optional input_formats parameter: +>>> f = DateTimeField(input_formats=['%Y %m %d %I:%M %p']) +>>> f.clean(datetime.date(2006, 10, 25)) +datetime.datetime(2006, 10, 25, 0, 0) +>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30)) +datetime.datetime(2006, 10, 25, 14, 30) +>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59)) +datetime.datetime(2006, 10, 25, 14, 30, 59) +>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59, 200)) +datetime.datetime(2006, 10, 25, 14, 30, 59, 200) +>>> f.clean('2006 10 25 2:30 PM') +datetime.datetime(2006, 10, 25, 14, 30) + +The input_formats parameter overrides all default input formats, +so the default formats won't work unless you specify them: +>>> f.clean('2006-10-25 14:30:45') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid date/time.'] + +>>> f = DateTimeField(required=False) +>>> f.clean(None) +>>> repr(f.clean(None)) +'None' +>>> f.clean('') +>>> repr(f.clean('')) +'None' + +""" diff --git a/tests/regressiontests/forms/localflavor/is_.py b/tests/regressiontests/forms/localflavor/is_.py new file mode 100644 index 0000000000..6851441a79 --- /dev/null +++ b/tests/regressiontests/forms/localflavor/is_.py @@ -0,0 +1,103 @@ +# -*- coding: utf-8 -*- +# Tests for the contrib/localflavor/ IS form fields. + +tests = r""" +## ISIdNumberField ############################################################# + +>>> from django.contrib.localflavor.is_.forms import * +>>> f = ISIdNumberField() +>>> f.clean('2308803449') +u'230880-3449' +>>> f.clean('230880-3449') +u'230880-3449' +>>> f.clean('230880 3449') +u'230880-3449' +>>> f.clean('230880343') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value has at least 10 characters (it has 9).'] +>>> f.clean('230880343234') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value has at most 11 characters (it has 12).'] +>>> f.clean('abcdefghijk') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid Icelandic identification number. The format is XXXXXX-XXXX.'] +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('2308803439') +Traceback (most recent call last): +... +ValidationError: [u'The Icelandic identification number is not valid.'] +>>> f.clean('2308803440') +u'230880-3440' +>>> f = ISIdNumberField(required=False) +>>> f.clean(None) +u'' +>>> f.clean('') +u'' + +## ISPhoneNumberField ############################################################# + +>>> from django.contrib.localflavor.is_.forms import * +>>> f = ISPhoneNumberField() +>>> f.clean('1234567') +u'1234567' +>>> f.clean('123 4567') +u'1234567' +>>> f.clean('123-4567') +u'1234567' +>>> f.clean('123-456') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid value.'] +>>> f.clean('123456') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value has at least 7 characters (it has 6).'] +>>> f.clean('123456555') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value has at most 8 characters (it has 9).'] +>>> f.clean('abcdefg') +Traceback (most recent call last): +ValidationError: [u'Enter a valid value.'] +>>> f.clean(' 1234567 ') +Traceback (most recent call last): +... +ValidationError: [u'Ensure this value has at most 8 characters (it has 9).'] +>>> f.clean(' 12367 ') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid value.'] + +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f = ISPhoneNumberField(required=False) +>>> f.clean(None) +u'' +>>> f.clean('') +u'' + +## ISPostalCodeSelect ############################################################# + +>>> from django.contrib.localflavor.is_.forms import * +>>> f = ISPostalCodeSelect() + +>>> f.render('foo', 'bar') +u'<select name="foo">\n<option value="101">101 Reykjav\xedk</option>\n<option value="103">103 Reykjav\xedk</option>\n<option value="104">104 Reykjav\xedk</option>\n<option value="105">105 Reykjav\xedk</option>\n<option value="107">107 Reykjav\xedk</option>\n<option value="108">108 Reykjav\xedk</option>\n<option value="109">109 Reykjav\xedk</option>\n<option value="110">110 Reykjav\xedk</option>\n<option value="111">111 Reykjav\xedk</option>\n<option value="112">112 Reykjav\xedk</option>\n<option value="113">113 Reykjav\xedk</option>\n<option value="116">116 Kjalarnes</option>\n<option value="121">121 Reykjav\xedk</option>\n<option value="123">123 Reykjav\xedk</option>\n<option value="124">124 Reykjav\xedk</option>\n<option value="125">125 Reykjav\xedk</option>\n<option value="127">127 Reykjav\xedk</option>\n<option value="128">128 Reykjav\xedk</option>\n<option value="129">129 Reykjav\xedk</option>\n<option value="130">130 Reykjav\xedk</option>\n<option value="132">132 Reykjav\xedk</option>\n<option value="150">150 Reykjav\xedk</option>\n<option value="155">155 Reykjav\xedk</option>\n<option value="170">170 Seltjarnarnes</option>\n<option value="172">172 Seltjarnarnes</option>\n<option value="190">190 Vogar</option>\n<option value="200">200 K\xf3pavogur</option>\n<option value="201">201 K\xf3pavogur</option>\n<option value="202">202 K\xf3pavogur</option>\n<option value="203">203 K\xf3pavogur</option>\n<option value="210">210 Gar\xf0ab\xe6r</option>\n<option value="212">212 Gar\xf0ab\xe6r</option>\n<option value="220">220 Hafnarfj\xf6r\xf0ur</option>\n<option value="221">221 Hafnarfj\xf6r\xf0ur</option>\n<option value="222">222 Hafnarfj\xf6r\xf0ur</option>\n<option value="225">225 \xc1lftanes</option>\n<option value="230">230 Reykjanesb\xe6r</option>\n<option value="232">232 Reykjanesb\xe6r</option>\n<option value="233">233 Reykjanesb\xe6r</option>\n<option value="235">235 Keflav\xedkurflugv\xf6llur</option>\n<option value="240">240 Grindav\xedk</option>\n<option value="245">245 Sandger\xf0i</option>\n<option value="250">250 Gar\xf0ur</option>\n<option value="260">260 Reykjanesb\xe6r</option>\n<option value="270">270 Mosfellsb\xe6r</option>\n<option value="300">300 Akranes</option>\n<option value="301">301 Akranes</option>\n<option value="302">302 Akranes</option>\n<option value="310">310 Borgarnes</option>\n<option value="311">311 Borgarnes</option>\n<option value="320">320 Reykholt \xed Borgarfir\xf0i</option>\n<option value="340">340 Stykkish\xf3lmur</option>\n<option value="345">345 Flatey \xe1 Brei\xf0afir\xf0i</option>\n<option value="350">350 Grundarfj\xf6r\xf0ur</option>\n<option value="355">355 \xd3lafsv\xedk</option>\n<option value="356">356 Sn\xe6fellsb\xe6r</option>\n<option value="360">360 Hellissandur</option>\n<option value="370">370 B\xfa\xf0ardalur</option>\n<option value="371">371 B\xfa\xf0ardalur</option>\n<option value="380">380 Reykh\xf3lahreppur</option>\n<option value="400">400 \xcdsafj\xf6r\xf0ur</option>\n<option value="401">401 \xcdsafj\xf6r\xf0ur</option>\n<option value="410">410 Hn\xedfsdalur</option>\n<option value="415">415 Bolungarv\xedk</option>\n<option value="420">420 S\xfa\xf0av\xedk</option>\n<option value="425">425 Flateyri</option>\n<option value="430">430 Su\xf0ureyri</option>\n<option value="450">450 Patreksfj\xf6r\xf0ur</option>\n<option value="451">451 Patreksfj\xf6r\xf0ur</option>\n<option value="460">460 T\xe1lknafj\xf6r\xf0ur</option>\n<option value="465">465 B\xedldudalur</option>\n<option value="470">470 \xdeingeyri</option>\n<option value="471">471 \xdeingeyri</option>\n<option value="500">500 Sta\xf0ur</option>\n<option value="510">510 H\xf3lmav\xedk</option>\n<option value="512">512 H\xf3lmav\xedk</option>\n<option value="520">520 Drangsnes</option>\n<option value="522">522 Kj\xf6rvogur</option>\n<option value="523">523 B\xe6r</option>\n<option value="524">524 Nor\xf0urfj\xf6r\xf0ur</option>\n<option value="530">530 Hvammstangi</option>\n<option value="531">531 Hvammstangi</option>\n<option value="540">540 Bl\xf6ndu\xf3s</option>\n<option value="541">541 Bl\xf6ndu\xf3s</option>\n<option value="545">545 Skagastr\xf6nd</option>\n<option value="550">550 Sau\xf0\xe1rkr\xf3kur</option>\n<option value="551">551 Sau\xf0\xe1rkr\xf3kur</option>\n<option value="560">560 Varmahl\xed\xf0</option>\n<option value="565">565 Hofs\xf3s</option>\n<option value="566">566 Hofs\xf3s</option>\n<option value="570">570 Flj\xf3t</option>\n<option value="580">580 Siglufj\xf6r\xf0ur</option>\n<option value="600">600 Akureyri</option>\n<option value="601">601 Akureyri</option>\n<option value="602">602 Akureyri</option>\n<option value="603">603 Akureyri</option>\n<option value="610">610 Greniv\xedk</option>\n<option value="611">611 Gr\xedmsey</option>\n<option value="620">620 Dalv\xedk</option>\n<option value="621">621 Dalv\xedk</option>\n<option value="625">625 \xd3lafsfj\xf6r\xf0ur</option>\n<option value="630">630 Hr\xedsey</option>\n<option value="640">640 H\xfasav\xedk</option>\n<option value="641">641 H\xfasav\xedk</option>\n<option value="645">645 Fossh\xf3ll</option>\n<option value="650">650 Laugar</option>\n<option value="660">660 M\xfdvatn</option>\n<option value="670">670 K\xf3pasker</option>\n<option value="671">671 K\xf3pasker</option>\n<option value="675">675 Raufarh\xf6fn</option>\n<option value="680">680 \xde\xf3rsh\xf6fn</option>\n<option value="681">681 \xde\xf3rsh\xf6fn</option>\n<option value="685">685 Bakkafj\xf6r\xf0ur</option>\n<option value="690">690 Vopnafj\xf6r\xf0ur</option>\n<option value="700">700 Egilssta\xf0ir</option>\n<option value="701">701 Egilssta\xf0ir</option>\n<option value="710">710 Sey\xf0isfj\xf6r\xf0ur</option>\n<option value="715">715 Mj\xf3ifj\xf6r\xf0ur</option>\n<option value="720">720 Borgarfj\xf6r\xf0ur eystri</option>\n<option value="730">730 Rey\xf0arfj\xf6r\xf0ur</option>\n<option value="735">735 Eskifj\xf6r\xf0ur</option>\n<option value="740">740 Neskaupsta\xf0ur</option>\n<option value="750">750 F\xe1skr\xfa\xf0sfj\xf6r\xf0ur</option>\n<option value="755">755 St\xf6\xf0varfj\xf6r\xf0ur</option>\n<option value="760">760 Brei\xf0dalsv\xedk</option>\n<option value="765">765 Dj\xfapivogur</option>\n<option value="780">780 H\xf6fn \xed Hornafir\xf0i</option>\n<option value="781">781 H\xf6fn \xed Hornafir\xf0i</option>\n<option value="785">785 \xd6r\xe6fi</option>\n<option value="800">800 Selfoss</option>\n<option value="801">801 Selfoss</option>\n<option value="802">802 Selfoss</option>\n<option value="810">810 Hverager\xf0i</option>\n<option value="815">815 \xdeorl\xe1ksh\xf6fn</option>\n<option value="820">820 Eyrarbakki</option>\n<option value="825">825 Stokkseyri</option>\n<option value="840">840 Laugarvatn</option>\n<option value="845">845 Fl\xfa\xf0ir</option>\n<option value="850">850 Hella</option>\n<option value="851">851 Hella</option>\n<option value="860">860 Hvolsv\xf6llur</option>\n<option value="861">861 Hvolsv\xf6llur</option>\n<option value="870">870 V\xedk</option>\n<option value="871">871 V\xedk</option>\n<option value="880">880 Kirkjub\xe6jarklaustur</option>\n<option value="900">900 Vestmannaeyjar</option>\n<option value="902">902 Vestmannaeyjar</option>\n</select>' +""" + diff --git a/tests/regressiontests/forms/localflavor/it.py b/tests/regressiontests/forms/localflavor/it.py new file mode 100644 index 0000000000..10023a7cf6 --- /dev/null +++ b/tests/regressiontests/forms/localflavor/it.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Tests for the contrib/localflavor/ IT form fields. + +tests = r""" +# ITZipCodeField ############################################################# + +>>> from django.contrib.localflavor.it.forms import ITZipCodeField +>>> f = ITZipCodeField() +>>> f.clean('00100') +u'00100' +>>> f.clean(' 00100') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid zip code.'] + +# ITRegionSelect ############################################################# + +>>> from django.contrib.localflavor.it.forms import ITRegionSelect +>>> w = ITRegionSelect() +>>> w.render('regions', 'PMN') +u'<select name="regions">\n<option value="ABR">Abruzzo</option>\n<option value="BAS">Basilicata</option>\n<option value="CAL">Calabria</option>\n<option value="CAM">Campania</option>\n<option value="EMR">Emilia-Romagna</option>\n<option value="FVG">Friuli-Venezia Giulia</option>\n<option value="LAZ">Lazio</option>\n<option value="LIG">Liguria</option>\n<option value="LOM">Lombardia</option>\n<option value="MAR">Marche</option>\n<option value="MOL">Molise</option>\n<option value="PMN" selected="selected">Piemonte</option>\n<option value="PUG">Puglia</option>\n<option value="SAR">Sardegna</option>\n<option value="SIC">Sicilia</option>\n<option value="TOS">Toscana</option>\n<option value="TAA">Trentino-Alto Adige</option>\n<option value="UMB">Umbria</option>\n<option value="VAO">Valle d\u2019Aosta</option>\n<option value="VEN">Veneto</option>\n</select>' + +# ITSocialSecurityNumberField ################################################# + +>>> from django.contrib.localflavor.it.forms import ITSocialSecurityNumberField +>>> f = ITSocialSecurityNumberField() +>>> f.clean('LVSGDU99T71H501L') +u'LVSGDU99T71H501L' +>>> f.clean('LBRRME11A01L736W') +u'LBRRME11A01L736W' +>>> f.clean('lbrrme11a01l736w') +u'LBRRME11A01L736W' +>>> f.clean('LBR RME 11A01 L736W') +u'LBRRME11A01L736W' +>>> f.clean('LBRRME11A01L736A') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid Social Security number.'] +>>> f.clean('%BRRME11A01L736W') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid Social Security number.'] + +# ITVatNumberField ########################################################### + +>>> from django.contrib.localflavor.it.forms import ITVatNumberField +>>> f = ITVatNumberField() +>>> f.clean('07973780013') +u'07973780013' +>>> f.clean('7973780013') +u'07973780013' +>>> f.clean(7973780013) +u'07973780013' +>>> f.clean('07973780014') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid VAT number.'] +>>> f.clean('A7973780013') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid VAT number.'] +""" diff --git a/tests/regressiontests/forms/localflavor/jp.py b/tests/regressiontests/forms/localflavor/jp.py new file mode 100644 index 0000000000..7b5b82667c --- /dev/null +++ b/tests/regressiontests/forms/localflavor/jp.py @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- +# Tests for the contrib/localflavor/ JP form fields. + +tests = r""" +# JPPostalCodeField ############################################################### + +A form field that validates its input is a Japanese postcode. + +Accepts 7 digits(with/out hyphen). +>>> from django.contrib.localflavor.jp.forms import JPPostalCodeField +>>> f = JPPostalCodeField() +>>> f.clean('251-0032') +u'2510032' +>>> f.clean('2510032') +u'2510032' +>>> f.clean('2510-032') +Traceback (most recent call last): +... +ValidationError: [u'Enter a postal code in the format XXXXXXX or XXX-XXXX.'] +>>> f.clean('251a0032') +Traceback (most recent call last): +... +ValidationError: [u'Enter a postal code in the format XXXXXXX or XXX-XXXX.'] +>>> f.clean('a51-0032') +Traceback (most recent call last): +... +ValidationError: [u'Enter a postal code in the format XXXXXXX or XXX-XXXX.'] +>>> f.clean('25100321') +Traceback (most recent call last): +... +ValidationError: [u'Enter a postal code in the format XXXXXXX or XXX-XXXX.'] +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] + +>>> f = JPPostalCodeField(required=False) +>>> f.clean('251-0032') +u'2510032' +>>> f.clean('2510032') +u'2510032' +>>> f.clean('2510-032') +Traceback (most recent call last): +... +ValidationError: [u'Enter a postal code in the format XXXXXXX or XXX-XXXX.'] +>>> f.clean('') +u'' +>>> f.clean(None) +u'' + +# JPPrefectureSelect ############################################################### + +A Select widget that uses a list of Japanese prefectures as its choices. +>>> from django.contrib.localflavor.jp.forms import JPPrefectureSelect +>>> w = JPPrefectureSelect() +>>> print w.render('prefecture', 'kanagawa') +<select name="prefecture"> +<option value="hokkaido">Hokkaido</option> +<option value="aomori">Aomori</option> +<option value="iwate">Iwate</option> +<option value="miyagi">Miyagi</option> +<option value="akita">Akita</option> +<option value="yamagata">Yamagata</option> +<option value="fukushima">Fukushima</option> +<option value="ibaraki">Ibaraki</option> +<option value="tochigi">Tochigi</option> +<option value="gunma">Gunma</option> +<option value="saitama">Saitama</option> +<option value="chiba">Chiba</option> +<option value="tokyo">Tokyo</option> +<option value="kanagawa" selected="selected">Kanagawa</option> +<option value="yamanashi">Yamanashi</option> +<option value="nagano">Nagano</option> +<option value="niigata">Niigata</option> +<option value="toyama">Toyama</option> +<option value="ishikawa">Ishikawa</option> +<option value="fukui">Fukui</option> +<option value="gifu">Gifu</option> +<option value="shizuoka">Shizuoka</option> +<option value="aichi">Aichi</option> +<option value="mie">Mie</option> +<option value="shiga">Shiga</option> +<option value="kyoto">Kyoto</option> +<option value="osaka">Osaka</option> +<option value="hyogo">Hyogo</option> +<option value="nara">Nara</option> +<option value="wakayama">Wakayama</option> +<option value="tottori">Tottori</option> +<option value="shimane">Shimane</option> +<option value="okayama">Okayama</option> +<option value="hiroshima">Hiroshima</option> +<option value="yamaguchi">Yamaguchi</option> +<option value="tokushima">Tokushima</option> +<option value="kagawa">Kagawa</option> +<option value="ehime">Ehime</option> +<option value="kochi">Kochi</option> +<option value="fukuoka">Fukuoka</option> +<option value="saga">Saga</option> +<option value="nagasaki">Nagasaki</option> +<option value="kumamoto">Kumamoto</option> +<option value="oita">Oita</option> +<option value="miyazaki">Miyazaki</option> +<option value="kagoshima">Kagoshima</option> +<option value="okinawa">Okinawa</option> +</select> +""" diff --git a/tests/regressiontests/forms/localflavor/nl.py b/tests/regressiontests/forms/localflavor/nl.py new file mode 100644 index 0000000000..38bbf72384 --- /dev/null +++ b/tests/regressiontests/forms/localflavor/nl.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +# Tests for the contrib/localflavor/ NL form fields. + +tests = r""" +# NLPhoneNumberField ######################################################## + +>>> from django.contrib.localflavor.nl.forms import NLPhoneNumberField +>>> f = NLPhoneNumberField(required=False) +>>> f.clean('') +u'' +>>> f.clean('012-3456789') +'012-3456789' +>>> f.clean('0123456789') +'0123456789' +>>> f.clean('+31-12-3456789') +'+31-12-3456789' +>>> f.clean('(0123) 456789') +'(0123) 456789' +>>> f.clean('foo') +Traceback (most recent call last): + ... +ValidationError: [u'Enter a valid phone number'] + +# NLZipCodeField ############################################################ + +>>> from django.contrib.localflavor.nl.forms import NLZipCodeField +>>> f = NLZipCodeField(required=False) +>>> f.clean('') +u'' +>>> f.clean('1234ab') +u'1234 AB' +>>> f.clean('1234 ab') +u'1234 AB' +>>> f.clean('1234 AB') +u'1234 AB' +>>> f.clean('0123AB') +Traceback (most recent call last): + ... +ValidationError: [u'Enter a valid postal code'] +>>> f.clean('foo') +Traceback (most recent call last): + ... +ValidationError: [u'Enter a valid postal code'] + +# NLSoFiNumberField ######################################################### + +>>> from django.contrib.localflavor.nl.forms import NLSoFiNumberField +>>> f = NLSoFiNumberField(required=False) +>>> f.clean('') +u'' +>>> f.clean('123456782') +'123456782' +>>> f.clean('000000000') +Traceback (most recent call last): + ... +ValidationError: [u'Enter a valid SoFi number'] +>>> f.clean('123456789') +Traceback (most recent call last): + ... +ValidationError: [u'Enter a valid SoFi number'] +>>> f.clean('foo') +Traceback (most recent call last): + ... +ValidationError: [u'Enter a valid SoFi number'] + +# NLProvinceSelect ########################################################## + +>>> from django.contrib.localflavor.nl.forms import NLProvinceSelect +>>> s = NLProvinceSelect() +>>> s.render('provinces', 'OV') +u'<select name="provinces">\n<option value="DR">Drente</option>\n<option value="FL">Flevoland</option>\n<option value="FR">Friesland</option>\n<option value="GL">Gelderland</option>\n<option value="GR">Groningen</option>\n<option value="LB">Limburg</option>\n<option value="NB">Noord-Brabant</option>\n<option value="NH">Noord-Holland</option>\n<option value="OV" selected="selected">Overijssel</option>\n<option value="UT">Utrecht</option>\n<option value="ZE">Zeeland</option>\n<option value="ZH">Zuid-Holland</option>\n</select>' +""" diff --git a/tests/regressiontests/forms/localflavor/pl.py b/tests/regressiontests/forms/localflavor/pl.py new file mode 100644 index 0000000000..be8437208b --- /dev/null +++ b/tests/regressiontests/forms/localflavor/pl.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Tests for the contrib/localflavor/ PL form fields. + +tests = r""" +# PLVoivodeshipSelect ########################################################## + +>>> from django.contrib.localflavor.pl.forms import PLVoivodeshipSelect +>>> f = PLVoivodeshipSelect() +>>> f.render('voivodeships','pomerania') +u'<select name="voivodeships">\n<option value="lower_silesia">Lower Silesia</option>\n<option value="kuyavia-pomerania">Kuyavia-Pomerania</option>\n<option value="lublin">Lublin</option>\n<option value="lubusz">Lubusz</option>\n<option value="lodz">Lodz</option>\n<option value="lesser_poland">Lesser Poland</option>\n<option value="masovia">Masovia</option>\n<option value="opole">Opole</option>\n<option value="subcarpatia">Subcarpatia</option>\n<option value="podlasie">Podlasie</option>\n<option value="pomerania" selected="selected">Pomerania</option>\n<option value="silesia">Silesia</option>\n<option value="swietokrzyskie">Swietokrzyskie</option>\n<option value="warmia-masuria">Warmia-Masuria</option>\n<option value="greater_poland">Greater Poland</option>\n<option value="west_pomerania">West Pomerania</option>\n</select>' + +# PLAdministrativeUnitSelect ########################################################## + +>>> from django.contrib.localflavor.pl.forms import PLAdministrativeUnitSelect +>>> f = PLAdministrativeUnitSelect() +>>> f.render('administrativeunit','katowice') +u'<select name="administrativeunit">\n<option value="wroclaw">Wroc\u0142aw</option>\n<option value="jeleniagora">Jelenia G\xf3ra</option>\n<option value="legnica">Legnica</option>\n<option value="boleslawiecki">boles\u0142awiecki</option>\n<option value="dzierzoniowski">dzier\u017coniowski</option>\n<option value="glogowski">g\u0142ogowski</option>\n<option value="gorowski">g\xf3rowski</option>\n<option value="jaworski">jaworski</option>\n<option value="jeleniogorski">jeleniog\xf3rski</option>\n<option value="kamiennogorski">kamiennog\xf3rski</option>\n<option value="klodzki">k\u0142odzki</option>\n<option value="legnicki">legnicki</option>\n<option value="lubanski">luba\u0144ski</option>\n<option value="lubinski">lubi\u0144ski</option>\n<option value="lwowecki">lw\xf3wecki</option>\n<option value="milicki">milicki</option>\n<option value="olesnicki">ole\u015bnicki</option>\n<option value="olawski">o\u0142awski</option>\n<option value="polkowicki">polkowicki</option>\n<option value="strzelinski">strzeli\u0144ski</option>\n<option value="sredzki">\u015bredzki</option>\n<option value="swidnicki">\u015bwidnicki</option>\n<option value="trzebnicki">trzebnicki</option>\n<option value="walbrzyski">wa\u0142brzyski</option>\n<option value="wolowski">wo\u0142owski</option>\n<option value="wroclawski">wroc\u0142awski</option>\n<option value="zabkowicki">z\u0105bkowicki</option>\n<option value="zgorzelecki">zgorzelecki</option>\n<option value="zlotoryjski">z\u0142otoryjski</option>\n<option value="bydgoszcz">Bydgoszcz</option>\n<option value="torun">Toru\u0144</option>\n<option value="wloclawek">W\u0142oc\u0142awek</option>\n<option value="grudziadz">Grudzi\u0105dz</option>\n<option value="aleksandrowski">aleksandrowski</option>\n<option value="brodnicki">brodnicki</option>\n<option value="bydgoski">bydgoski</option>\n<option value="chelminski">che\u0142mi\u0144ski</option>\n<option value="golubsko-dobrzynski">golubsko-dobrzy\u0144ski</option>\n<option value="grudziadzki">grudzi\u0105dzki</option>\n<option value="inowroclawski">inowroc\u0142awski</option>\n<option value="lipnowski">lipnowski</option>\n<option value="mogilenski">mogile\u0144ski</option>\n<option value="nakielski">nakielski</option>\n<option value="radziejowski">radziejowski</option>\n<option value="rypinski">rypi\u0144ski</option>\n<option value="sepolenski">s\u0119pole\u0144ski</option>\n<option value="swiecki">\u015bwiecki</option>\n<option value="torunski">toru\u0144ski</option>\n<option value="tucholski">tucholski</option>\n<option value="wabrzeski">w\u0105brzeski</option>\n<option value="wloclawski">wroc\u0142awski</option>\n<option value="zninski">\u017ani\u0144ski</option>\n<option value="lublin">Lublin</option>\n<option value="biala-podlaska">Bia\u0142a Podlaska</option>\n<option value="chelm">Che\u0142m</option>\n<option value="zamosc">Zamo\u015b\u0107</option>\n<option value="bialski">bialski</option>\n<option value="bilgorajski">bi\u0142gorajski</option>\n<option value="chelmski">che\u0142mski</option>\n<option value="hrubieszowski">hrubieszowski</option>\n<option value="janowski">janowski</option>\n<option value="krasnostawski">krasnostawski</option>\n<option value="krasnicki">kra\u015bnicki</option>\n<option value="lubartowski">lubartowski</option>\n<option value="lubelski">lubelski</option>\n<option value="leczynski">\u0142\u0119czy\u0144ski</option>\n<option value="lukowski">\u0142ukowski</option>\n<option value="opolski">opolski</option>\n<option value="parczewski">parczewski</option>\n<option value="pulawski">pu\u0142awski</option>\n<option value="radzynski">radzy\u0144ski</option>\n<option value="rycki">rycki</option>\n<option value="swidnicki">\u015bwidnicki</option>\n<option value="tomaszowski">tomaszowski</option>\n<option value="wlodawski">w\u0142odawski</option>\n<option value="zamojski">zamojski</option>\n<option value="gorzow-wielkopolski">Gorz\xf3w Wielkopolski</option>\n<option value="zielona-gora">Zielona G\xf3ra</option>\n<option value="gorzowski">gorzowski</option>\n<option value="krosnienski">kro\u015bnie\u0144ski</option>\n<option value="miedzyrzecki">mi\u0119dzyrzecki</option>\n<option value="nowosolski">nowosolski</option>\n<option value="slubicki">s\u0142ubicki</option>\n<option value="strzelecko-drezdenecki">strzelecko-drezdenecki</option>\n<option value="sulecinski">sule\u0144ci\u0144ski</option>\n<option value="swiebodzinski">\u015bwiebodzi\u0144ski</option>\n<option value="wschowski">wschowski</option>\n<option value="zielonogorski">zielonog\xf3rski</option>\n<option value="zaganski">\u017caga\u0144ski</option>\n<option value="zarski">\u017carski</option>\n<option value="lodz">\u0141\xf3d\u017a</option>\n<option value="piotrkow-trybunalski">Piotrk\xf3w Trybunalski</option>\n<option value="skierniewice">Skierniewice</option>\n<option value="belchatowski">be\u0142chatowski</option>\n<option value="brzezinski">brzezi\u0144ski</option>\n<option value="kutnowski">kutnowski</option>\n<option value="laski">\u0142aski</option>\n<option value="leczycki">\u0142\u0119czycki</option>\n<option value="lowicki">\u0142owicki</option>\n<option value="lodzki wschodni">\u0142\xf3dzki wschodni</option>\n<option value="opoczynski">opoczy\u0144ski</option>\n<option value="pabianicki">pabianicki</option>\n<option value="pajeczanski">paj\u0119cza\u0144ski</option>\n<option value="piotrkowski">piotrkowski</option>\n<option value="poddebicki">podd\u0119bicki</option>\n<option value="radomszczanski">radomszcza\u0144ski</option>\n<option value="rawski">rawski</option>\n<option value="sieradzki">sieradzki</option>\n<option value="skierniewicki">skierniewicki</option>\n<option value="tomaszowski">tomaszowski</option>\n<option value="wielunski">wielu\u0144ski</option>\n<option value="wieruszowski">wieruszowski</option>\n<option value="zdunskowolski">zdu\u0144skowolski</option>\n<option value="zgierski">zgierski</option>\n<option value="krakow">Krak\xf3w</option>\n<option value="tarnow">Tarn\xf3w</option>\n<option value="nowy-sacz">Nowy S\u0105cz</option>\n<option value="bochenski">boche\u0144ski</option>\n<option value="brzeski">brzeski</option>\n<option value="chrzanowski">chrzanowski</option>\n<option value="dabrowski">d\u0105browski</option>\n<option value="gorlicki">gorlicki</option>\n<option value="krakowski">krakowski</option>\n<option value="limanowski">limanowski</option>\n<option value="miechowski">miechowski</option>\n<option value="myslenicki">my\u015blenicki</option>\n<option value="nowosadecki">nowos\u0105decki</option>\n<option value="nowotarski">nowotarski</option>\n<option value="olkuski">olkuski</option>\n<option value="oswiecimski">o\u015bwi\u0119cimski</option>\n<option value="proszowicki">proszowicki</option>\n<option value="suski">suski</option>\n<option value="tarnowski">tarnowski</option>\n<option value="tatrzanski">tatrza\u0144ski</option>\n<option value="wadowicki">wadowicki</option>\n<option value="wielicki">wielicki</option>\n<option value="warszawa">Warszawa</option>\n<option value="ostroleka">Ostro\u0142\u0119ka</option>\n<option value="plock">P\u0142ock</option>\n<option value="radom">Radom</option>\n<option value="siedlce">Siedlce</option>\n<option value="bialobrzeski">bia\u0142obrzeski</option>\n<option value="ciechanowski">ciechanowski</option>\n<option value="garwolinski">garwoli\u0144ski</option>\n<option value="gostyninski">gostyni\u0144ski</option>\n<option value="grodziski">grodziski</option>\n<option value="grojecki">gr\xf3jecki</option>\n<option value="kozienicki">kozenicki</option>\n<option value="legionowski">legionowski</option>\n<option value="lipski">lipski</option>\n<option value="losicki">\u0142osicki</option>\n<option value="makowski">makowski</option>\n<option value="minski">mi\u0144ski</option>\n<option value="mlawski">m\u0142awski</option>\n<option value="nowodworski">nowodworski</option>\n<option value="ostrolecki">ostro\u0142\u0119cki</option>\n<option value="ostrowski">ostrowski</option>\n<option value="otwocki">otwocki</option>\n<option value="piaseczynski">piaseczy\u0144ski</option>\n<option value="plocki">p\u0142ocki</option>\n<option value="plonski">p\u0142o\u0144ski</option>\n<option value="pruszkowski">pruszkowski</option>\n<option value="przasnyski">przasnyski</option>\n<option value="przysuski">przysuski</option>\n<option value="pultuski">pu\u0142tuski</option>\n<option value="radomski">radomski</option>\n<option value="siedlecki">siedlecki</option>\n<option value="sierpecki">sierpecki</option>\n<option value="sochaczewski">sochaczewski</option>\n<option value="sokolowski">soko\u0142owski</option>\n<option value="szydlowiecki">szyd\u0142owiecki</option>\n<option value="warszawski-zachodni">warszawski zachodni</option>\n<option value="wegrowski">w\u0119growski</option>\n<option value="wolominski">wo\u0142omi\u0144ski</option>\n<option value="wyszkowski">wyszkowski</option>\n<option value="zwolenski">zwole\u0144ski</option>\n<option value="zurominski">\u017curomi\u0144ski</option>\n<option value="zyrardowski">\u017cyrardowski</option>\n<option value="opole">Opole</option>\n<option value="brzeski">brzeski</option>\n<option value="glubczycki">g\u0142ubczyski</option>\n<option value="kedzierzynsko-kozielski">k\u0119dzierzy\u0144ski-kozielski</option>\n<option value="kluczborski">kluczborski</option>\n<option value="krapkowicki">krapkowicki</option>\n<option value="namyslowski">namys\u0142owski</option>\n<option value="nyski">nyski</option>\n<option value="oleski">oleski</option>\n<option value="opolski">opolski</option>\n<option value="prudnicki">prudnicki</option>\n<option value="strzelecki">strzelecki</option>\n<option value="rzeszow">Rzesz\xf3w</option>\n<option value="krosno">Krosno</option>\n<option value="przemysl">Przemy\u015bl</option>\n<option value="tarnobrzeg">Tarnobrzeg</option>\n<option value="bieszczadzki">bieszczadzki</option>\n<option value="brzozowski">brzozowski</option>\n<option value="debicki">d\u0119bicki</option>\n<option value="jaroslawski">jaros\u0142awski</option>\n<option value="jasielski">jasielski</option>\n<option value="kolbuszowski">kolbuszowski</option>\n<option value="krosnienski">kro\u015bnie\u0144ski</option>\n<option value="leski">leski</option>\n<option value="lezajski">le\u017cajski</option>\n<option value="lubaczowski">lubaczowski</option>\n<option value="lancucki">\u0142a\u0144cucki</option>\n<option value="mielecki">mielecki</option>\n<option value="nizanski">ni\u017ca\u0144ski</option>\n<option value="przemyski">przemyski</option>\n<option value="przeworski">przeworski</option>\n<option value="ropczycko-sedziszowski">ropczycko-s\u0119dziszowski</option>\n<option value="rzeszowski">rzeszowski</option>\n<option value="sanocki">sanocki</option>\n<option value="stalowowolski">stalowowolski</option>\n<option value="strzyzowski">strzy\u017cowski</option>\n<option value="tarnobrzeski">tarnobrzeski</option>\n<option value="bialystok">Bia\u0142ystok</option>\n<option value="lomza">\u0141om\u017ca</option>\n<option value="suwalki">Suwa\u0142ki</option>\n<option value="augustowski">augustowski</option>\n<option value="bialostocki">bia\u0142ostocki</option>\n<option value="bielski">bielski</option>\n<option value="grajewski">grajewski</option>\n<option value="hajnowski">hajnowski</option>\n<option value="kolnenski">kolne\u0144ski</option>\n<option value="\u0142omzynski">\u0142om\u017cy\u0144ski</option>\n<option value="moniecki">moniecki</option>\n<option value="sejnenski">sejne\u0144ski</option>\n<option value="siemiatycki">siematycki</option>\n<option value="sokolski">sok\xf3lski</option>\n<option value="suwalski">suwalski</option>\n<option value="wysokomazowiecki">wysokomazowiecki</option>\n<option value="zambrowski">zambrowski</option>\n<option value="gdansk">Gda\u0144sk</option>\n<option value="gdynia">Gdynia</option>\n<option value="slupsk">S\u0142upsk</option>\n<option value="sopot">Sopot</option>\n<option value="bytowski">bytowski</option>\n<option value="chojnicki">chojnicki</option>\n<option value="czluchowski">cz\u0142uchowski</option>\n<option value="kartuski">kartuski</option>\n<option value="koscierski">ko\u015bcierski</option>\n<option value="kwidzynski">kwidzy\u0144ski</option>\n<option value="leborski">l\u0119borski</option>\n<option value="malborski">malborski</option>\n<option value="nowodworski">nowodworski</option>\n<option value="gdanski">gda\u0144ski</option>\n<option value="pucki">pucki</option>\n<option value="slupski">s\u0142upski</option>\n<option value="starogardzki">starogardzki</option>\n<option value="sztumski">sztumski</option>\n<option value="tczewski">tczewski</option>\n<option value="wejherowski">wejcherowski</option>\n<option value="katowice" selected="selected">Katowice</option>\n<option value="bielsko-biala">Bielsko-Bia\u0142a</option>\n<option value="bytom">Bytom</option>\n<option value="chorzow">Chorz\xf3w</option>\n<option value="czestochowa">Cz\u0119stochowa</option>\n<option value="dabrowa-gornicza">D\u0105browa G\xf3rnicza</option>\n<option value="gliwice">Gliwice</option>\n<option value="jastrzebie-zdroj">Jastrz\u0119bie Zdr\xf3j</option>\n<option value="jaworzno">Jaworzno</option>\n<option value="myslowice">Mys\u0142owice</option>\n<option value="piekary-slaskie">Piekary \u015al\u0105skie</option>\n<option value="ruda-slaska">Ruda \u015al\u0105ska</option>\n<option value="rybnik">Rybnik</option>\n<option value="siemianowice-slaskie">Siemianowice \u015al\u0105skie</option>\n<option value="sosnowiec">Sosnowiec</option>\n<option value="swietochlowice">\u015awi\u0119toch\u0142owice</option>\n<option value="tychy">Tychy</option>\n<option value="zabrze">Zabrze</option>\n<option value="zory">\u017bory</option>\n<option value="bedzinski">b\u0119dzi\u0144ski</option>\n<option value="bielski">bielski</option>\n<option value="bierunsko-ledzinski">bieru\u0144sko-l\u0119dzi\u0144ski</option>\n<option value="cieszynski">cieszy\u0144ski</option>\n<option value="czestochowski">cz\u0119stochowski</option>\n<option value="gliwicki">gliwicki</option>\n<option value="klobucki">k\u0142obucki</option>\n<option value="lubliniecki">lubliniecki</option>\n<option value="mikolowski">miko\u0142owski</option>\n<option value="myszkowski">myszkowski</option>\n<option value="pszczynski">pszczy\u0144ski</option>\n<option value="raciborski">raciborski</option>\n<option value="rybnicki">rybnicki</option>\n<option value="tarnogorski">tarnog\xf3rski</option>\n<option value="wodzislawski">wodzis\u0142awski</option>\n<option value="zawiercianski">zawiercia\u0144ski</option>\n<option value="zywiecki">\u017cywiecki</option>\n<option value="kielce">Kielce</option>\n<option value="buski">buski</option>\n<option value="jedrzejowski">j\u0119drzejowski</option>\n<option value="kazimierski">kazimierski</option>\n<option value="kielecki">kielecki</option>\n<option value="konecki">konecki</option>\n<option value="opatowski">opatowski</option>\n<option value="ostrowiecki">ostrowiecki</option>\n<option value="pinczowski">pi\u0144czowski</option>\n<option value="sandomierski">sandomierski</option>\n<option value="skarzyski">skar\u017cyski</option>\n<option value="starachowicki">starachowicki</option>\n<option value="staszowski">staszowski</option>\n<option value="wloszczowski">w\u0142oszczowski</option>\n<option value="olsztyn">Olsztyn</option>\n<option value="elblag">Elbl\u0105g</option>\n<option value="bartoszycki">bartoszycki</option>\n<option value="braniewski">braniewski</option>\n<option value="dzialdowski">dzia\u0142dowski</option>\n<option value="elblaski">elbl\u0105ski</option>\n<option value="elcki">e\u0142cki</option>\n<option value="gizycki">gi\u017cycki</option>\n<option value="goldapski">go\u0142dapski</option>\n<option value="ilawski">i\u0142awski</option>\n<option value="ketrzynski">k\u0119trzy\u0144ski</option>\n<option value="lidzbarski">lidzbarski</option>\n<option value="mragowski">mr\u0105gowski</option>\n<option value="nidzicki">nidzicki</option>\n<option value="nowomiejski">nowomiejski</option>\n<option value="olecki">olecki</option>\n<option value="olsztynski">olszty\u0144ski</option>\n<option value="ostrodzki">ostr\xf3dzki</option>\n<option value="piski">piski</option>\n<option value="szczycienski">szczycie\u0144ski</option>\n<option value="wegorzewski">w\u0119gorzewski</option>\n<option value="poznan">Pozna\u0144</option>\n<option value="kalisz">Kalisz</option>\n<option value="konin">Konin</option>\n<option value="leszno">Leszno</option>\n<option value="chodzieski">chodziejski</option>\n<option value="czarnkowsko-trzcianecki">czarnkowsko-trzcianecki</option>\n<option value="gnieznienski">gnie\u017anie\u0144ski</option>\n<option value="gostynski">gosty\u0144ski</option>\n<option value="grodziski">grodziski</option>\n<option value="jarocinski">jaroci\u0144ski</option>\n<option value="kaliski">kaliski</option>\n<option value="kepinski">k\u0119pi\u0144ski</option>\n<option value="kolski">kolski</option>\n<option value="koninski">koni\u0144ski</option>\n<option value="koscianski">ko\u015bcia\u0144ski</option>\n<option value="krotoszynski">krotoszy\u0144ski</option>\n<option value="leszczynski">leszczy\u0144ski</option>\n<option value="miedzychodzki">mi\u0119dzychodzki</option>\n<option value="nowotomyski">nowotomyski</option>\n<option value="obornicki">obornicki</option>\n<option value="ostrowski">ostrowski</option>\n<option value="ostrzeszowski">ostrzeszowski</option>\n<option value="pilski">pilski</option>\n<option value="pleszewski">pleszewski</option>\n<option value="poznanski">pozna\u0144ski</option>\n<option value="rawicki">rawicki</option>\n<option value="slupecki">s\u0142upecki</option>\n<option value="szamotulski">szamotulski</option>\n<option value="sredzki">\u015bredzki</option>\n<option value="sremski">\u015bremski</option>\n<option value="turecki">turecki</option>\n<option value="wagrowiecki">w\u0105growiecki</option>\n<option value="wolsztynski">wolszty\u0144ski</option>\n<option value="wrzesinski">wrzesi\u0144ski</option>\n<option value="zlotowski">z\u0142otowski</option>\n<option value="bialogardzki">bia\u0142ogardzki</option>\n<option value="choszczenski">choszcze\u0144ski</option>\n<option value="drawski">drawski</option>\n<option value="goleniowski">goleniowski</option>\n<option value="gryficki">gryficki</option>\n<option value="gryfinski">gryfi\u0144ski</option>\n<option value="kamienski">kamie\u0144ski</option>\n<option value="kolobrzeski">ko\u0142obrzeski</option>\n<option value="koszalinski">koszali\u0144ski</option>\n<option value="lobeski">\u0142obeski</option>\n<option value="mysliborski">my\u015bliborski</option>\n<option value="policki">policki</option>\n<option value="pyrzycki">pyrzycki</option>\n<option value="slawienski">s\u0142awie\u0144ski</option>\n<option value="stargardzki">stargardzki</option>\n<option value="szczecinecki">szczecinecki</option>\n<option value="swidwinski">\u015bwidwi\u0144ski</option>\n<option value="walecki">wa\u0142ecki</option>\n</select>' + +# PLPostalCodeField ############################################################## + +>>> from django.contrib.localflavor.pl.forms import PLPostalCodeField +>>> f = PLPostalCodeField() +>>> f.clean('43--434') +Traceback (most recent call last): +... +ValidationError: [u'Enter a postal code in the format XX-XXX.'] +>>> f.clean('41-403') +u'41-403' + +# PLTaxNumberField ############################################################### + +>>> from django.contrib.localflavor.pl.forms import PLTaxNumberField +>>> f = PLTaxNumberField() +>>> f.clean('43-343-234-323') +Traceback (most recent call last): +... +ValidationError: [u'Enter a tax number field (NIP) in the format XXX-XXX-XX-XX or XX-XX-XXX-XXX.'] +>>> f.clean('43-34-234-323') +u'43-34-234-323' +>>> f.clean('433-344-24-23') +u'433-344-24-23' + +# PLNationalIdentificationNumberField ############################################ + +>>> from django.contrib.localflavor.pl.forms import PLNationalIdentificationNumberField +>>> f = PLNationalIdentificationNumberField() +>>> f.clean('80071610614') +u'80071610614' +>>> f.clean('80071610610') +Traceback (most recent call last): +... +ValidationError: [u'Wrong checksum for the National Identification Number.'] +>>> f.clean('80') +Traceback (most recent call last): +... +ValidationError: [u'National Identification Number consists of 11 digits.'] +>>> f.clean('800716106AA') +Traceback (most recent call last): +... +ValidationError: [u'National Identification Number consists of 11 digits.'] +""" diff --git a/tests/regressiontests/forms/localflavor/sk.py b/tests/regressiontests/forms/localflavor/sk.py new file mode 100644 index 0000000000..069a99b2d2 --- /dev/null +++ b/tests/regressiontests/forms/localflavor/sk.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# Tests for the contrib/localflavor/ SK form fields. + +tests = r""" +# SKPostalCodeField ######################################################### + +>>> from django.contrib.localflavor.sk.forms import SKPostalCodeField +>>> f = SKPostalCodeField() +>>> f.clean('84545x') +Traceback (most recent call last): +... +ValidationError: [u'Enter a postal code in the format XXXXX or XXX XX.'] +>>> f.clean('91909') +u'91909' +>>> f.clean('917 01') +u'91701' + +# SKRegionSelect ############################################################ + +>>> from django.contrib.localflavor.sk.forms import SKRegionSelect +>>> w = SKRegionSelect() +>>> w.render('regions', 'TT') +u'<select name="regions">\n<option value="BB">Banska Bystrica region</option>\n<option value="BA">Bratislava region</option>\n<option value="KE">Kosice region</option>\n<option value="NR">Nitra region</option>\n<option value="PO">Presov region</option>\n<option value="TN">Trencin region</option>\n<option value="TT" selected="selected">Trnava region</option>\n<option value="ZA">Zilina region</option>\n</select>' + +# SKDistrictSelect ########################################################## + +>>> from django.contrib.localflavor.sk.forms import SKDistrictSelect +>>> w = SKDistrictSelect() +>>> w.render('Districts', 'RK') +u'<select name="Districts">\n<option value="BB">Banska Bystrica</option>\n<option value="BS">Banska Stiavnica</option>\n<option value="BJ">Bardejov</option>\n<option value="BN">Banovce nad Bebravou</option>\n<option value="BR">Brezno</option>\n<option value="BA1">Bratislava I</option>\n<option value="BA2">Bratislava II</option>\n<option value="BA3">Bratislava III</option>\n<option value="BA4">Bratislava IV</option>\n<option value="BA5">Bratislava V</option>\n<option value="BY">Bytca</option>\n<option value="CA">Cadca</option>\n<option value="DT">Detva</option>\n<option value="DK">Dolny Kubin</option>\n<option value="DS">Dunajska Streda</option>\n<option value="GA">Galanta</option>\n<option value="GL">Gelnica</option>\n<option value="HC">Hlohovec</option>\n<option value="HE">Humenne</option>\n<option value="IL">Ilava</option>\n<option value="KK">Kezmarok</option>\n<option value="KN">Komarno</option>\n<option value="KE1">Kosice I</option>\n<option value="KE2">Kosice II</option>\n<option value="KE3">Kosice III</option>\n<option value="KE4">Kosice IV</option>\n<option value="KEO">Kosice - okolie</option>\n<option value="KA">Krupina</option>\n<option value="KM">Kysucke Nove Mesto</option>\n<option value="LV">Levice</option>\n<option value="LE">Levoca</option>\n<option value="LM">Liptovsky Mikulas</option>\n<option value="LC">Lucenec</option>\n<option value="MA">Malacky</option>\n<option value="MT">Martin</option>\n<option value="ML">Medzilaborce</option>\n<option value="MI">Michalovce</option>\n<option value="MY">Myjava</option>\n<option value="NO">Namestovo</option>\n<option value="NR">Nitra</option>\n<option value="NM">Nove Mesto nad Vahom</option>\n<option value="NZ">Nove Zamky</option>\n<option value="PE">Partizanske</option>\n<option value="PK">Pezinok</option>\n<option value="PN">Piestany</option>\n<option value="PT">Poltar</option>\n<option value="PP">Poprad</option>\n<option value="PB">Povazska Bystrica</option>\n<option value="PO">Presov</option>\n<option value="PD">Prievidza</option>\n<option value="PU">Puchov</option>\n<option value="RA">Revuca</option>\n<option value="RS">Rimavska Sobota</option>\n<option value="RV">Roznava</option>\n<option value="RK" selected="selected">Ruzomberok</option>\n<option value="SB">Sabinov</option>\n<option value="SC">Senec</option>\n<option value="SE">Senica</option>\n<option value="SI">Skalica</option>\n<option value="SV">Snina</option>\n<option value="SO">Sobrance</option>\n<option value="SN">Spisska Nova Ves</option>\n<option value="SL">Stara Lubovna</option>\n<option value="SP">Stropkov</option>\n<option value="SK">Svidnik</option>\n<option value="SA">Sala</option>\n<option value="TO">Topolcany</option>\n<option value="TV">Trebisov</option>\n<option value="TN">Trencin</option>\n<option value="TT">Trnava</option>\n<option value="TR">Turcianske Teplice</option>\n<option value="TS">Tvrdosin</option>\n<option value="VK">Velky Krtis</option>\n<option value="VT">Vranov nad Toplou</option>\n<option value="ZM">Zlate Moravce</option>\n<option value="ZV">Zvolen</option>\n<option value="ZC">Zarnovica</option>\n<option value="ZH">Ziar nad Hronom</option>\n<option value="ZA">Zilina</option>\n</select>' +""" diff --git a/tests/regressiontests/forms/localflavor/uk.py b/tests/regressiontests/forms/localflavor/uk.py new file mode 100644 index 0000000000..d7848f70a8 --- /dev/null +++ b/tests/regressiontests/forms/localflavor/uk.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Tests for the contrib/localflavor/ UK form fields. + +tests = r""" +# UKPostcodeField ############################################################# + +UKPostcodeField validates that the data is a valid UK postcode. +>>> from django.contrib.localflavor.uk.forms import UKPostcodeField +>>> f = UKPostcodeField() +>>> f.clean('BT32 4PX') +u'BT32 4PX' +>>> f.clean('GIR 0AA') +u'GIR 0AA' +>>> f.clean('BT324PX') +Traceback (most recent call last): +... +ValidationError: [u'Enter a postcode. A space is required between the two postcode parts.'] +>>> f.clean('1NV 4L1D') +Traceback (most recent call last): +... +ValidationError: [u'Enter a postcode. A space is required between the two postcode parts.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] + +>>> f = UKPostcodeField(required=False) +>>> f.clean('BT32 4PX') +u'BT32 4PX' +>>> f.clean('GIR 0AA') +u'GIR 0AA' +>>> f.clean('1NV 4L1D') +Traceback (most recent call last): +... +ValidationError: [u'Enter a postcode. A space is required between the two postcode parts.'] +>>> f.clean('BT324PX') +Traceback (most recent call last): +... +ValidationError: [u'Enter a postcode. A space is required between the two postcode parts.'] +>>> f.clean(None) +u'' +>>> f.clean('') +u'' +""" diff --git a/tests/regressiontests/forms/localflavor/us.py b/tests/regressiontests/forms/localflavor/us.py new file mode 100644 index 0000000000..dfbfef681d --- /dev/null +++ b/tests/regressiontests/forms/localflavor/us.py @@ -0,0 +1,260 @@ +# -*- coding: utf-8 -*- +# Tests for the contrib/localflavor/ US form fields. + +tests = r""" +# USZipCodeField ############################################################## + +USZipCodeField validates that the data is either a five-digit U.S. zip code or +a zip+4. +>>> from django.contrib.localflavor.us.forms import USZipCodeField +>>> f = USZipCodeField() +>>> f.clean('60606') +u'60606' +>>> f.clean(60606) +u'60606' +>>> f.clean('04000') +u'04000' +>>> f.clean('4000') +Traceback (most recent call last): +... +ValidationError: [u'Enter a zip code in the format XXXXX or XXXXX-XXXX.'] +>>> f.clean('60606-1234') +u'60606-1234' +>>> f.clean('6060-1234') +Traceback (most recent call last): +... +ValidationError: [u'Enter a zip code in the format XXXXX or XXXXX-XXXX.'] +>>> f.clean('60606-') +Traceback (most recent call last): +... +ValidationError: [u'Enter a zip code in the format XXXXX or XXXXX-XXXX.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] + +>>> f = USZipCodeField(required=False) +>>> f.clean('60606') +u'60606' +>>> f.clean(60606) +u'60606' +>>> f.clean('04000') +u'04000' +>>> f.clean('4000') +Traceback (most recent call last): +... +ValidationError: [u'Enter a zip code in the format XXXXX or XXXXX-XXXX.'] +>>> f.clean('60606-1234') +u'60606-1234' +>>> f.clean('6060-1234') +Traceback (most recent call last): +... +ValidationError: [u'Enter a zip code in the format XXXXX or XXXXX-XXXX.'] +>>> f.clean('60606-') +Traceback (most recent call last): +... +ValidationError: [u'Enter a zip code in the format XXXXX or XXXXX-XXXX.'] +>>> f.clean(None) +u'' +>>> f.clean('') +u'' + +# USPhoneNumberField ########################################################## + +USPhoneNumberField validates that the data is a valid U.S. phone number, +including the area code. It's normalized to XXX-XXX-XXXX format. +>>> from django.contrib.localflavor.us.forms import USPhoneNumberField +>>> f = USPhoneNumberField() +>>> f.clean('312-555-1212') +u'312-555-1212' +>>> f.clean('3125551212') +u'312-555-1212' +>>> f.clean('312 555-1212') +u'312-555-1212' +>>> f.clean('(312) 555-1212') +u'312-555-1212' +>>> f.clean('312 555 1212') +u'312-555-1212' +>>> f.clean('312.555.1212') +u'312-555-1212' +>>> f.clean('312.555-1212') +u'312-555-1212' +>>> f.clean(' (312) 555.1212 ') +u'312-555-1212' +>>> f.clean('555-1212') +Traceback (most recent call last): +... +ValidationError: [u'Phone numbers must be in XXX-XXX-XXXX format.'] +>>> f.clean('312-55-1212') +Traceback (most recent call last): +... +ValidationError: [u'Phone numbers must be in XXX-XXX-XXXX format.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] + +>>> f = USPhoneNumberField(required=False) +>>> f.clean('312-555-1212') +u'312-555-1212' +>>> f.clean('3125551212') +u'312-555-1212' +>>> f.clean('312 555-1212') +u'312-555-1212' +>>> f.clean('(312) 555-1212') +u'312-555-1212' +>>> f.clean('312 555 1212') +u'312-555-1212' +>>> f.clean('312.555.1212') +u'312-555-1212' +>>> f.clean('312.555-1212') +u'312-555-1212' +>>> f.clean(' (312) 555.1212 ') +u'312-555-1212' +>>> f.clean('555-1212') +Traceback (most recent call last): +... +ValidationError: [u'Phone numbers must be in XXX-XXX-XXXX format.'] +>>> f.clean('312-55-1212') +Traceback (most recent call last): +... +ValidationError: [u'Phone numbers must be in XXX-XXX-XXXX format.'] +>>> f.clean(None) +u'' +>>> f.clean('') +u'' + +# USStateField ################################################################ + +USStateField validates that the data is either an abbreviation or name of a +U.S. state. +>>> from django.contrib.localflavor.us.forms import USStateField +>>> f = USStateField() +>>> f.clean('il') +u'IL' +>>> f.clean('IL') +u'IL' +>>> f.clean('illinois') +u'IL' +>>> f.clean(' illinois ') +u'IL' +>>> f.clean(60606) +Traceback (most recent call last): +... +ValidationError: [u'Enter a U.S. state or territory.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] + +>>> f = USStateField(required=False) +>>> f.clean('il') +u'IL' +>>> f.clean('IL') +u'IL' +>>> f.clean('illinois') +u'IL' +>>> f.clean(' illinois ') +u'IL' +>>> f.clean(60606) +Traceback (most recent call last): +... +ValidationError: [u'Enter a U.S. state or territory.'] +>>> f.clean(None) +u'' +>>> f.clean('') +u'' + +# USStateSelect ############################################################### + +USStateSelect is a Select widget that uses a list of U.S. states/territories +as its choices. +>>> from django.contrib.localflavor.us.forms import USStateSelect +>>> w = USStateSelect() +>>> print w.render('state', 'IL') +<select name="state"> +<option value="AL">Alabama</option> +<option value="AK">Alaska</option> +<option value="AS">American Samoa</option> +<option value="AZ">Arizona</option> +<option value="AR">Arkansas</option> +<option value="CA">California</option> +<option value="CO">Colorado</option> +<option value="CT">Connecticut</option> +<option value="DE">Delaware</option> +<option value="DC">District of Columbia</option> +<option value="FM">Federated States of Micronesia</option> +<option value="FL">Florida</option> +<option value="GA">Georgia</option> +<option value="GU">Guam</option> +<option value="HI">Hawaii</option> +<option value="ID">Idaho</option> +<option value="IL" selected="selected">Illinois</option> +<option value="IN">Indiana</option> +<option value="IA">Iowa</option> +<option value="KS">Kansas</option> +<option value="KY">Kentucky</option> +<option value="LA">Louisiana</option> +<option value="ME">Maine</option> +<option value="MH">Marshall Islands</option> +<option value="MD">Maryland</option> +<option value="MA">Massachusetts</option> +<option value="MI">Michigan</option> +<option value="MN">Minnesota</option> +<option value="MS">Mississippi</option> +<option value="MO">Missouri</option> +<option value="MT">Montana</option> +<option value="NE">Nebraska</option> +<option value="NV">Nevada</option> +<option value="NH">New Hampshire</option> +<option value="NJ">New Jersey</option> +<option value="NM">New Mexico</option> +<option value="NY">New York</option> +<option value="NC">North Carolina</option> +<option value="ND">North Dakota</option> +<option value="MP">Northern Mariana Islands</option> +<option value="OH">Ohio</option> +<option value="OK">Oklahoma</option> +<option value="OR">Oregon</option> +<option value="PW">Palau</option> +<option value="PA">Pennsylvania</option> +<option value="PR">Puerto Rico</option> +<option value="RI">Rhode Island</option> +<option value="SC">South Carolina</option> +<option value="SD">South Dakota</option> +<option value="TN">Tennessee</option> +<option value="TX">Texas</option> +<option value="UT">Utah</option> +<option value="VT">Vermont</option> +<option value="VI">Virgin Islands</option> +<option value="VA">Virginia</option> +<option value="WA">Washington</option> +<option value="WV">West Virginia</option> +<option value="WI">Wisconsin</option> +<option value="WY">Wyoming</option> +</select> + +# USSocialSecurityNumberField ################################################# +>>> from django.contrib.localflavor.us.forms import USSocialSecurityNumberField +>>> f = USSocialSecurityNumberField() +>>> f.clean('987-65-4330') +u'987-65-4330' +>>> f.clean('987654330') +u'987-65-4330' +>>> f.clean('078-05-1120') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid U.S. Social Security number in XXX-XX-XXXX format.'] +""" diff --git a/tests/regressiontests/forms/models.py b/tests/regressiontests/forms/models.py index e69de29bb2..f4f8607193 100644 --- a/tests/regressiontests/forms/models.py +++ b/tests/regressiontests/forms/models.py @@ -0,0 +1,21 @@ +from django.db import models + +class BoundaryModel(models.Model): + positive_integer = models.PositiveIntegerField(null=True, blank=True) + +__test__ = {'API_TESTS': """ +>>> from django.newforms import form_for_model + +# Boundary conditions on a PostitiveIntegerField ######################### +>>> BoundaryForm = form_for_model(BoundaryModel) +>>> f = BoundaryForm({'positive_integer':100}) +>>> f.is_valid() +True +>>> f = BoundaryForm({'positive_integer':0}) +>>> f.is_valid() +True +>>> f = BoundaryForm({'positive_integer':-100}) +>>> f.is_valid() +False + +"""}
\ No newline at end of file diff --git a/tests/regressiontests/forms/regressions.py b/tests/regressiontests/forms/regressions.py index 784ef49902..1bfb425188 100644 --- a/tests/regressiontests/forms/regressions.py +++ b/tests/regressiontests/forms/regressions.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Tests to prevent against recurrences of earlier bugs. -regression_tests = r""" +tests = r""" It should be possible to re-use attribute dictionaries (#3810) >>> from django.newforms import * >>> extra_attrs = {'class': 'special'} @@ -60,19 +60,11 @@ Translated error messages used to be buggy. u'<ul class="errorlist"><li>\u041e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u043f\u043e\u043b\u0435.</li></ul>\n<p><label for="id_somechoice_0">\xc5\xf8\xdf:</label> <ul>\n<li><label><input type="radio" id="id_somechoice_0" value="\xc5" name="somechoice" /> En tied\xe4</label></li>\n<li><label><input type="radio" id="id_somechoice_1" value="\xf8" name="somechoice" /> Mies</label></li>\n<li><label><input type="radio" id="id_somechoice_2" value="\xdf" name="somechoice" /> Nainen</label></li>\n</ul></p>' >>> deactivate() -####################### -# Miscellaneous Tests # -####################### - -There once was a problem with Form fields called "data". Let's make sure that -doesn't come back. ->>> class DataForm(Form): -... data = CharField(max_length=10) ->>> f = DataForm({'data': 'xyzzy'}) ->>> f.is_valid() -True ->>> f.cleaned_data -{'data': u'xyzzy'} +Deep copying translated text shouldn't raise an error +>>> from django.utils.translation import gettext_lazy +>>> class CopyForm(Form): +... degree = IntegerField(widget=Select(choices=((1, gettext_lazy('test')),))) +>>> f = CopyForm() ####################### # Miscellaneous Tests # diff --git a/tests/regressiontests/forms/tests.py b/tests/regressiontests/forms/tests.py index 78442677eb..a732f9fdb0 100644 --- a/tests/regressiontests/forms/tests.py +++ b/tests/regressiontests/forms/tests.py @@ -1,3807 +1,54 @@ # -*- coding: utf-8 -*- -from localflavor import localflavor_tests -from regressions import regression_tests - -form_tests = r""" ->>> from django.newforms import * ->>> from django.newforms.widgets import RadioFieldRenderer ->>> import datetime ->>> import time ->>> import re ->>> try: -... from decimal import Decimal -... except ImportError: -... from django.utils._decimal import Decimal - -########### -# Widgets # -########### - -Each Widget class corresponds to an HTML form widget. A Widget knows how to -render itself, given a field name and some data. Widgets don't perform -validation. - -# TextInput Widget ############################################################ - ->>> w = TextInput() ->>> w.render('email', '') -u'<input type="text" name="email" />' ->>> w.render('email', None) -u'<input type="text" name="email" />' ->>> w.render('email', 'test@example.com') -u'<input type="text" name="email" value="test@example.com" />' ->>> w.render('email', 'some "quoted" & ampersanded value') -u'<input type="text" name="email" value="some "quoted" & ampersanded value" />' ->>> w.render('email', 'test@example.com', attrs={'class': 'fun'}) -u'<input type="text" name="email" value="test@example.com" class="fun" />' - -# Note that doctest in Python 2.4 (and maybe 2.5?) doesn't support non-ascii -# characters in output, so we're displaying the repr() here. ->>> w.render('email', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'}) -u'<input type="text" name="email" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" class="fun" />' - -You can also pass 'attrs' to the constructor: ->>> w = TextInput(attrs={'class': 'fun'}) ->>> w.render('email', '') -u'<input type="text" class="fun" name="email" />' ->>> w.render('email', 'foo@example.com') -u'<input type="text" class="fun" value="foo@example.com" name="email" />' - -'attrs' passed to render() get precedence over those passed to the constructor: ->>> w = TextInput(attrs={'class': 'pretty'}) ->>> w.render('email', '', attrs={'class': 'special'}) -u'<input type="text" class="special" name="email" />' - -# PasswordInput Widget ############################################################ - ->>> w = PasswordInput() ->>> w.render('email', '') -u'<input type="password" name="email" />' ->>> w.render('email', None) -u'<input type="password" name="email" />' ->>> w.render('email', 'test@example.com') -u'<input type="password" name="email" value="test@example.com" />' ->>> w.render('email', 'some "quoted" & ampersanded value') -u'<input type="password" name="email" value="some "quoted" & ampersanded value" />' ->>> w.render('email', 'test@example.com', attrs={'class': 'fun'}) -u'<input type="password" name="email" value="test@example.com" class="fun" />' - -You can also pass 'attrs' to the constructor: ->>> w = PasswordInput(attrs={'class': 'fun'}) ->>> w.render('email', '') -u'<input type="password" class="fun" name="email" />' ->>> w.render('email', 'foo@example.com') -u'<input type="password" class="fun" value="foo@example.com" name="email" />' - -'attrs' passed to render() get precedence over those passed to the constructor: ->>> w = PasswordInput(attrs={'class': 'pretty'}) ->>> w.render('email', '', attrs={'class': 'special'}) -u'<input type="password" class="special" name="email" />' - ->>> w.render('email', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'}) -u'<input type="password" class="fun" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" name="email" />' - -The render_value argument lets you specify whether the widget should render -its value. You may want to do this for security reasons. ->>> w = PasswordInput(render_value=True) ->>> w.render('email', 'secret') -u'<input type="password" name="email" value="secret" />' ->>> w = PasswordInput(render_value=False) ->>> w.render('email', '') -u'<input type="password" name="email" />' ->>> w.render('email', None) -u'<input type="password" name="email" />' ->>> w.render('email', 'secret') -u'<input type="password" name="email" />' ->>> w = PasswordInput(attrs={'class': 'fun'}, render_value=False) ->>> w.render('email', 'secret') -u'<input type="password" class="fun" name="email" />' - -# HiddenInput Widget ############################################################ - ->>> w = HiddenInput() ->>> w.render('email', '') -u'<input type="hidden" name="email" />' ->>> w.render('email', None) -u'<input type="hidden" name="email" />' ->>> w.render('email', 'test@example.com') -u'<input type="hidden" name="email" value="test@example.com" />' ->>> w.render('email', 'some "quoted" & ampersanded value') -u'<input type="hidden" name="email" value="some "quoted" & ampersanded value" />' ->>> w.render('email', 'test@example.com', attrs={'class': 'fun'}) -u'<input type="hidden" name="email" value="test@example.com" class="fun" />' - -You can also pass 'attrs' to the constructor: ->>> w = HiddenInput(attrs={'class': 'fun'}) ->>> w.render('email', '') -u'<input type="hidden" class="fun" name="email" />' ->>> w.render('email', 'foo@example.com') -u'<input type="hidden" class="fun" value="foo@example.com" name="email" />' - -'attrs' passed to render() get precedence over those passed to the constructor: ->>> w = HiddenInput(attrs={'class': 'pretty'}) ->>> w.render('email', '', attrs={'class': 'special'}) -u'<input type="hidden" class="special" name="email" />' - ->>> w.render('email', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'}) -u'<input type="hidden" class="fun" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" name="email" />' - -'attrs' passed to render() get precedence over those passed to the constructor: ->>> w = HiddenInput(attrs={'class': 'pretty'}) ->>> w.render('email', '', attrs={'class': 'special'}) -u'<input type="hidden" class="special" name="email" />' - -# MultipleHiddenInput Widget ################################################## - ->>> w = MultipleHiddenInput() ->>> w.render('email', []) -u'' ->>> w.render('email', None) -u'' ->>> w.render('email', ['test@example.com']) -u'<input type="hidden" name="email" value="test@example.com" />' ->>> w.render('email', ['some "quoted" & ampersanded value']) -u'<input type="hidden" name="email" value="some "quoted" & ampersanded value" />' ->>> w.render('email', ['test@example.com', 'foo@example.com']) -u'<input type="hidden" name="email" value="test@example.com" />\n<input type="hidden" name="email" value="foo@example.com" />' ->>> w.render('email', ['test@example.com'], attrs={'class': 'fun'}) -u'<input type="hidden" name="email" value="test@example.com" class="fun" />' ->>> w.render('email', ['test@example.com', 'foo@example.com'], attrs={'class': 'fun'}) -u'<input type="hidden" name="email" value="test@example.com" class="fun" />\n<input type="hidden" name="email" value="foo@example.com" class="fun" />' - -You can also pass 'attrs' to the constructor: ->>> w = MultipleHiddenInput(attrs={'class': 'fun'}) ->>> w.render('email', []) -u'' ->>> w.render('email', ['foo@example.com']) -u'<input type="hidden" class="fun" value="foo@example.com" name="email" />' ->>> w.render('email', ['foo@example.com', 'test@example.com']) -u'<input type="hidden" class="fun" value="foo@example.com" name="email" />\n<input type="hidden" class="fun" value="test@example.com" name="email" />' - -'attrs' passed to render() get precedence over those passed to the constructor: ->>> w = MultipleHiddenInput(attrs={'class': 'pretty'}) ->>> w.render('email', ['foo@example.com'], attrs={'class': 'special'}) -u'<input type="hidden" class="special" value="foo@example.com" name="email" />' - ->>> w.render('email', ['ŠĐĆŽćžšđ'], attrs={'class': 'fun'}) -u'<input type="hidden" class="fun" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" name="email" />' - -'attrs' passed to render() get precedence over those passed to the constructor: ->>> w = MultipleHiddenInput(attrs={'class': 'pretty'}) ->>> w.render('email', ['foo@example.com'], attrs={'class': 'special'}) -u'<input type="hidden" class="special" value="foo@example.com" name="email" />' - -# FileInput Widget ############################################################ - -FileInput widgets don't ever show the value, because the old value is of no use -if you are updating the form or if the provided file generated an error. ->>> w = FileInput() ->>> w.render('email', '') -u'<input type="file" name="email" />' ->>> w.render('email', None) -u'<input type="file" name="email" />' ->>> w.render('email', 'test@example.com') -u'<input type="file" name="email" />' ->>> w.render('email', 'some "quoted" & ampersanded value') -u'<input type="file" name="email" />' ->>> w.render('email', 'test@example.com', attrs={'class': 'fun'}) -u'<input type="file" name="email" class="fun" />' - -You can also pass 'attrs' to the constructor: ->>> w = FileInput(attrs={'class': 'fun'}) ->>> w.render('email', '') -u'<input type="file" class="fun" name="email" />' ->>> w.render('email', 'foo@example.com') -u'<input type="file" class="fun" name="email" />' - ->>> w.render('email', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'}) -u'<input type="file" class="fun" name="email" />' - -# Textarea Widget ############################################################# - ->>> w = Textarea() ->>> w.render('msg', '') -u'<textarea rows="10" cols="40" name="msg"></textarea>' ->>> w.render('msg', None) -u'<textarea rows="10" cols="40" name="msg"></textarea>' ->>> w.render('msg', 'value') -u'<textarea rows="10" cols="40" name="msg">value</textarea>' ->>> w.render('msg', 'some "quoted" & ampersanded value') -u'<textarea rows="10" cols="40" name="msg">some "quoted" & ampersanded value</textarea>' ->>> w.render('msg', 'value', attrs={'class': 'pretty', 'rows': 20}) -u'<textarea class="pretty" rows="20" cols="40" name="msg">value</textarea>' - -You can also pass 'attrs' to the constructor: ->>> w = Textarea(attrs={'class': 'pretty'}) ->>> w.render('msg', '') -u'<textarea rows="10" cols="40" name="msg" class="pretty"></textarea>' ->>> w.render('msg', 'example') -u'<textarea rows="10" cols="40" name="msg" class="pretty">example</textarea>' - -'attrs' passed to render() get precedence over those passed to the constructor: ->>> w = Textarea(attrs={'class': 'pretty'}) ->>> w.render('msg', '', attrs={'class': 'special'}) -u'<textarea rows="10" cols="40" name="msg" class="special"></textarea>' - ->>> w.render('msg', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'}) -u'<textarea rows="10" cols="40" name="msg" class="fun">\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111</textarea>' - -# CheckboxInput Widget ######################################################## - ->>> w = CheckboxInput() ->>> w.render('is_cool', '') -u'<input type="checkbox" name="is_cool" />' ->>> w.render('is_cool', None) -u'<input type="checkbox" name="is_cool" />' ->>> w.render('is_cool', False) -u'<input type="checkbox" name="is_cool" />' ->>> w.render('is_cool', True) -u'<input checked="checked" type="checkbox" name="is_cool" />' - -Using any value that's not in ('', None, False, True) will check the checkbox -and set the 'value' attribute. ->>> w.render('is_cool', 'foo') -u'<input checked="checked" type="checkbox" name="is_cool" value="foo" />' - ->>> w.render('is_cool', False, attrs={'class': 'pretty'}) -u'<input type="checkbox" name="is_cool" class="pretty" />' - -You can also pass 'attrs' to the constructor: ->>> w = CheckboxInput(attrs={'class': 'pretty'}) ->>> w.render('is_cool', '') -u'<input type="checkbox" class="pretty" name="is_cool" />' - -'attrs' passed to render() get precedence over those passed to the constructor: ->>> w = CheckboxInput(attrs={'class': 'pretty'}) ->>> w.render('is_cool', '', attrs={'class': 'special'}) -u'<input type="checkbox" class="special" name="is_cool" />' - -You can pass 'check_test' to the constructor. This is a callable that takes the -value and returns True if the box should be checked. ->>> w = CheckboxInput(check_test=lambda value: value.startswith('hello')) ->>> w.render('greeting', '') -u'<input type="checkbox" name="greeting" />' ->>> w.render('greeting', 'hello') -u'<input checked="checked" type="checkbox" name="greeting" value="hello" />' ->>> w.render('greeting', 'hello there') -u'<input checked="checked" type="checkbox" name="greeting" value="hello there" />' ->>> w.render('greeting', 'hello & goodbye') -u'<input checked="checked" type="checkbox" name="greeting" value="hello & goodbye" />' - -A subtlety: If the 'check_test' argument cannot handle a value and raises any -exception during its __call__, then the exception will be swallowed and the box -will not be checked. In this example, the 'check_test' assumes the value has a -startswith() method, which fails for the values True, False and None. ->>> w.render('greeting', True) -u'<input type="checkbox" name="greeting" />' ->>> w.render('greeting', False) -u'<input type="checkbox" name="greeting" />' ->>> w.render('greeting', None) -u'<input type="checkbox" name="greeting" />' - -# Select Widget ############################################################### - ->>> w = Select() ->>> print w.render('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) -<select name="beatle"> -<option value="J" selected="selected">John</option> -<option value="P">Paul</option> -<option value="G">George</option> -<option value="R">Ringo</option> -</select> - -If the value is None, none of the options are selected: ->>> print w.render('beatle', None, choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) -<select name="beatle"> -<option value="J">John</option> -<option value="P">Paul</option> -<option value="G">George</option> -<option value="R">Ringo</option> -</select> - -If the value corresponds to a label (but not to an option value), none of the options are selected: ->>> print w.render('beatle', 'John', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) -<select name="beatle"> -<option value="J">John</option> -<option value="P">Paul</option> -<option value="G">George</option> -<option value="R">Ringo</option> -</select> - -The value is compared to its str(): ->>> print w.render('num', 2, choices=[('1', '1'), ('2', '2'), ('3', '3')]) -<select name="num"> -<option value="1">1</option> -<option value="2" selected="selected">2</option> -<option value="3">3</option> -</select> ->>> print w.render('num', '2', choices=[(1, 1), (2, 2), (3, 3)]) -<select name="num"> -<option value="1">1</option> -<option value="2" selected="selected">2</option> -<option value="3">3</option> -</select> ->>> print w.render('num', 2, choices=[(1, 1), (2, 2), (3, 3)]) -<select name="num"> -<option value="1">1</option> -<option value="2" selected="selected">2</option> -<option value="3">3</option> -</select> - -The 'choices' argument can be any iterable: ->>> from itertools import chain ->>> def get_choices(): -... for i in range(5): -... yield (i, i) ->>> print w.render('num', 2, choices=get_choices()) -<select name="num"> -<option value="0">0</option> -<option value="1">1</option> -<option value="2" selected="selected">2</option> -<option value="3">3</option> -<option value="4">4</option> -</select> ->>> things = ({'id': 1, 'name': 'And Boom'}, {'id': 2, 'name': 'One More Thing!'}) ->>> class SomeForm(Form): -... somechoice = ChoiceField(choices=chain((('', '-'*9),), [(thing['id'], thing['name']) for thing in things])) ->>> f = SomeForm() ->>> f.as_table() -u'<tr><th><label for="id_somechoice">Somechoice:</label></th><td><select name="somechoice" id="id_somechoice">\n<option value="" selected="selected">---------</option>\n<option value="1">And Boom</option>\n<option value="2">One More Thing!</option>\n</select></td></tr>' ->>> f.as_table() -u'<tr><th><label for="id_somechoice">Somechoice:</label></th><td><select name="somechoice" id="id_somechoice">\n<option value="" selected="selected">---------</option>\n<option value="1">And Boom</option>\n<option value="2">One More Thing!</option>\n</select></td></tr>' ->>> f = SomeForm({'somechoice': 2}) ->>> f.as_table() -u'<tr><th><label for="id_somechoice">Somechoice:</label></th><td><select name="somechoice" id="id_somechoice">\n<option value="">---------</option>\n<option value="1">And Boom</option>\n<option value="2" selected="selected">One More Thing!</option>\n</select></td></tr>' - -You can also pass 'choices' to the constructor: ->>> w = Select(choices=[(1, 1), (2, 2), (3, 3)]) ->>> print w.render('num', 2) -<select name="num"> -<option value="1">1</option> -<option value="2" selected="selected">2</option> -<option value="3">3</option> -</select> - -If 'choices' is passed to both the constructor and render(), then they'll both be in the output: ->>> print w.render('num', 2, choices=[(4, 4), (5, 5)]) -<select name="num"> -<option value="1">1</option> -<option value="2" selected="selected">2</option> -<option value="3">3</option> -<option value="4">4</option> -<option value="5">5</option> -</select> - ->>> w.render('email', 'ŠĐĆŽćžšđ', choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')]) -u'<select name="email">\n<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" selected="selected">\u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</option>\n<option value="\u0107\u017e\u0161\u0111">abc\u0107\u017e\u0161\u0111</option>\n</select>' - -If choices is passed to the constructor and is a generator, it can be iterated -over multiple times without getting consumed: ->>> w = Select(choices=get_choices()) ->>> print w.render('num', 2) -<select name="num"> -<option value="0">0</option> -<option value="1">1</option> -<option value="2" selected="selected">2</option> -<option value="3">3</option> -<option value="4">4</option> -</select> ->>> print w.render('num', 3) -<select name="num"> -<option value="0">0</option> -<option value="1">1</option> -<option value="2">2</option> -<option value="3" selected="selected">3</option> -<option value="4">4</option> -</select> - -# NullBooleanSelect Widget #################################################### - ->>> w = NullBooleanSelect() ->>> print w.render('is_cool', True) -<select name="is_cool"> -<option value="1">Unknown</option> -<option value="2" selected="selected">Yes</option> -<option value="3">No</option> -</select> ->>> print w.render('is_cool', False) -<select name="is_cool"> -<option value="1">Unknown</option> -<option value="2">Yes</option> -<option value="3" selected="selected">No</option> -</select> ->>> print w.render('is_cool', None) -<select name="is_cool"> -<option value="1" selected="selected">Unknown</option> -<option value="2">Yes</option> -<option value="3">No</option> -</select> ->>> print w.render('is_cool', '2') -<select name="is_cool"> -<option value="1">Unknown</option> -<option value="2" selected="selected">Yes</option> -<option value="3">No</option> -</select> ->>> print w.render('is_cool', '3') -<select name="is_cool"> -<option value="1">Unknown</option> -<option value="2">Yes</option> -<option value="3" selected="selected">No</option> -</select> - -# SelectMultiple Widget ####################################################### - ->>> w = SelectMultiple() ->>> print w.render('beatles', ['J'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) -<select multiple="multiple" name="beatles"> -<option value="J" selected="selected">John</option> -<option value="P">Paul</option> -<option value="G">George</option> -<option value="R">Ringo</option> -</select> ->>> print w.render('beatles', ['J', 'P'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) -<select multiple="multiple" name="beatles"> -<option value="J" selected="selected">John</option> -<option value="P" selected="selected">Paul</option> -<option value="G">George</option> -<option value="R">Ringo</option> -</select> ->>> print w.render('beatles', ['J', 'P', 'R'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) -<select multiple="multiple" name="beatles"> -<option value="J" selected="selected">John</option> -<option value="P" selected="selected">Paul</option> -<option value="G">George</option> -<option value="R" selected="selected">Ringo</option> -</select> - -If the value is None, none of the options are selected: ->>> print w.render('beatles', None, choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) -<select multiple="multiple" name="beatles"> -<option value="J">John</option> -<option value="P">Paul</option> -<option value="G">George</option> -<option value="R">Ringo</option> -</select> - -If the value corresponds to a label (but not to an option value), none of the options are selected: ->>> print w.render('beatles', ['John'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) -<select multiple="multiple" name="beatles"> -<option value="J">John</option> -<option value="P">Paul</option> -<option value="G">George</option> -<option value="R">Ringo</option> -</select> - -If multiple values are given, but some of them are not valid, the valid ones are selected: ->>> print w.render('beatles', ['J', 'G', 'foo'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) -<select multiple="multiple" name="beatles"> -<option value="J" selected="selected">John</option> -<option value="P">Paul</option> -<option value="G" selected="selected">George</option> -<option value="R">Ringo</option> -</select> - -The value is compared to its str(): ->>> print w.render('nums', [2], choices=[('1', '1'), ('2', '2'), ('3', '3')]) -<select multiple="multiple" name="nums"> -<option value="1">1</option> -<option value="2" selected="selected">2</option> -<option value="3">3</option> -</select> ->>> print w.render('nums', ['2'], choices=[(1, 1), (2, 2), (3, 3)]) -<select multiple="multiple" name="nums"> -<option value="1">1</option> -<option value="2" selected="selected">2</option> -<option value="3">3</option> -</select> ->>> print w.render('nums', [2], choices=[(1, 1), (2, 2), (3, 3)]) -<select multiple="multiple" name="nums"> -<option value="1">1</option> -<option value="2" selected="selected">2</option> -<option value="3">3</option> -</select> - -The 'choices' argument can be any iterable: ->>> def get_choices(): -... for i in range(5): -... yield (i, i) ->>> print w.render('nums', [2], choices=get_choices()) -<select multiple="multiple" name="nums"> -<option value="0">0</option> -<option value="1">1</option> -<option value="2" selected="selected">2</option> -<option value="3">3</option> -<option value="4">4</option> -</select> - -You can also pass 'choices' to the constructor: ->>> w = SelectMultiple(choices=[(1, 1), (2, 2), (3, 3)]) ->>> print w.render('nums', [2]) -<select multiple="multiple" name="nums"> -<option value="1">1</option> -<option value="2" selected="selected">2</option> -<option value="3">3</option> -</select> - -If 'choices' is passed to both the constructor and render(), then they'll both be in the output: ->>> print w.render('nums', [2], choices=[(4, 4), (5, 5)]) -<select multiple="multiple" name="nums"> -<option value="1">1</option> -<option value="2" selected="selected">2</option> -<option value="3">3</option> -<option value="4">4</option> -<option value="5">5</option> -</select> - ->>> w.render('nums', ['ŠĐĆŽćžšđ'], choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')]) -u'<select multiple="multiple" name="nums">\n<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" selected="selected">\u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</option>\n<option value="\u0107\u017e\u0161\u0111">abc\u0107\u017e\u0161\u0111</option>\n</select>' - -# RadioSelect Widget ########################################################## - ->>> w = RadioSelect() ->>> print w.render('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) -<ul> -<li><label><input checked="checked" type="radio" name="beatle" value="J" /> John</label></li> -<li><label><input type="radio" name="beatle" value="P" /> Paul</label></li> -<li><label><input type="radio" name="beatle" value="G" /> George</label></li> -<li><label><input type="radio" name="beatle" value="R" /> Ringo</label></li> -</ul> - -If the value is None, none of the options are checked: ->>> print w.render('beatle', None, choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) -<ul> -<li><label><input type="radio" name="beatle" value="J" /> John</label></li> -<li><label><input type="radio" name="beatle" value="P" /> Paul</label></li> -<li><label><input type="radio" name="beatle" value="G" /> George</label></li> -<li><label><input type="radio" name="beatle" value="R" /> Ringo</label></li> -</ul> - -If the value corresponds to a label (but not to an option value), none of the options are checked: ->>> print w.render('beatle', 'John', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) -<ul> -<li><label><input type="radio" name="beatle" value="J" /> John</label></li> -<li><label><input type="radio" name="beatle" value="P" /> Paul</label></li> -<li><label><input type="radio" name="beatle" value="G" /> George</label></li> -<li><label><input type="radio" name="beatle" value="R" /> Ringo</label></li> -</ul> - -The value is compared to its str(): ->>> print w.render('num', 2, choices=[('1', '1'), ('2', '2'), ('3', '3')]) -<ul> -<li><label><input type="radio" name="num" value="1" /> 1</label></li> -<li><label><input checked="checked" type="radio" name="num" value="2" /> 2</label></li> -<li><label><input type="radio" name="num" value="3" /> 3</label></li> -</ul> ->>> print w.render('num', '2', choices=[(1, 1), (2, 2), (3, 3)]) -<ul> -<li><label><input type="radio" name="num" value="1" /> 1</label></li> -<li><label><input checked="checked" type="radio" name="num" value="2" /> 2</label></li> -<li><label><input type="radio" name="num" value="3" /> 3</label></li> -</ul> ->>> print w.render('num', 2, choices=[(1, 1), (2, 2), (3, 3)]) -<ul> -<li><label><input type="radio" name="num" value="1" /> 1</label></li> -<li><label><input checked="checked" type="radio" name="num" value="2" /> 2</label></li> -<li><label><input type="radio" name="num" value="3" /> 3</label></li> -</ul> - -The 'choices' argument can be any iterable: ->>> def get_choices(): -... for i in range(5): -... yield (i, i) ->>> print w.render('num', 2, choices=get_choices()) -<ul> -<li><label><input type="radio" name="num" value="0" /> 0</label></li> -<li><label><input type="radio" name="num" value="1" /> 1</label></li> -<li><label><input checked="checked" type="radio" name="num" value="2" /> 2</label></li> -<li><label><input type="radio" name="num" value="3" /> 3</label></li> -<li><label><input type="radio" name="num" value="4" /> 4</label></li> -</ul> - -You can also pass 'choices' to the constructor: ->>> w = RadioSelect(choices=[(1, 1), (2, 2), (3, 3)]) ->>> print w.render('num', 2) -<ul> -<li><label><input type="radio" name="num" value="1" /> 1</label></li> -<li><label><input checked="checked" type="radio" name="num" value="2" /> 2</label></li> -<li><label><input type="radio" name="num" value="3" /> 3</label></li> -</ul> - -If 'choices' is passed to both the constructor and render(), then they'll both be in the output: ->>> print w.render('num', 2, choices=[(4, 4), (5, 5)]) -<ul> -<li><label><input type="radio" name="num" value="1" /> 1</label></li> -<li><label><input checked="checked" type="radio" name="num" value="2" /> 2</label></li> -<li><label><input type="radio" name="num" value="3" /> 3</label></li> -<li><label><input type="radio" name="num" value="4" /> 4</label></li> -<li><label><input type="radio" name="num" value="5" /> 5</label></li> -</ul> - -RadioSelect uses a RadioFieldRenderer to render the individual radio inputs. -You can manipulate that object directly to customize the way the RadioSelect -is rendered. ->>> w = RadioSelect() ->>> r = w.get_renderer('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) ->>> for inp in r: -... print inp -<label><input checked="checked" type="radio" name="beatle" value="J" /> John</label> -<label><input type="radio" name="beatle" value="P" /> Paul</label> -<label><input type="radio" name="beatle" value="G" /> George</label> -<label><input type="radio" name="beatle" value="R" /> Ringo</label> ->>> for inp in r: -... print '%s<br />' % inp -<label><input checked="checked" type="radio" name="beatle" value="J" /> John</label><br /> -<label><input type="radio" name="beatle" value="P" /> Paul</label><br /> -<label><input type="radio" name="beatle" value="G" /> George</label><br /> -<label><input type="radio" name="beatle" value="R" /> Ringo</label><br /> ->>> for inp in r: -... print '<p>%s %s</p>' % (inp.tag(), inp.choice_label) -<p><input checked="checked" type="radio" name="beatle" value="J" /> John</p> -<p><input type="radio" name="beatle" value="P" /> Paul</p> -<p><input type="radio" name="beatle" value="G" /> George</p> -<p><input type="radio" name="beatle" value="R" /> Ringo</p> ->>> for inp in r: -... print '%s %s %s %s %s' % (inp.name, inp.value, inp.choice_value, inp.choice_label, inp.is_checked()) -beatle J J John True -beatle J P Paul False -beatle J G George False -beatle J R Ringo False - -You can create your own custom renderers for RadioSelect to use. ->>> class MyRenderer(RadioFieldRenderer): -... def render(self): -... return u'<br />\n'.join([unicode(choice) for choice in self]) ->>> w = RadioSelect(renderer=MyRenderer) ->>> print w.render('beatle', 'G', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) -<label><input type="radio" name="beatle" value="J" /> John</label><br /> -<label><input type="radio" name="beatle" value="P" /> Paul</label><br /> -<label><input checked="checked" type="radio" name="beatle" value="G" /> George</label><br /> -<label><input type="radio" name="beatle" value="R" /> Ringo</label> - -A RadioFieldRenderer object also allows index access to individual RadioInput -objects. ->>> w = RadioSelect() ->>> r = w.get_renderer('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) ->>> print r[1] -<label><input type="radio" name="beatle" value="P" /> Paul</label> ->>> print r[0] -<label><input checked="checked" type="radio" name="beatle" value="J" /> John</label> ->>> r[0].is_checked() -True ->>> r[1].is_checked() -False ->>> r[1].name, r[1].value, r[1].choice_value, r[1].choice_label -('beatle', u'J', u'P', u'Paul') ->>> r[10] -Traceback (most recent call last): -... -IndexError: list index out of range - -# Unicode choices are correctly rendered as HTML ->>> w = RadioSelect() ->>> unicode(w.render('email', 'ŠĐĆŽćžšđ', choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')])) -u'<ul>\n<li><label><input checked="checked" type="radio" name="email" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" /> \u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</label></li>\n<li><label><input type="radio" name="email" value="\u0107\u017e\u0161\u0111" /> abc\u0107\u017e\u0161\u0111</label></li>\n</ul>' - -# Attributes provided at instantiation are passed to the constituent inputs ->>> w = RadioSelect(attrs={'id':'foo'}) ->>> print w.render('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) -<ul> -<li><label><input checked="checked" type="radio" id="foo_0" value="J" name="beatle" /> John</label></li> -<li><label><input type="radio" id="foo_1" value="P" name="beatle" /> Paul</label></li> -<li><label><input type="radio" id="foo_2" value="G" name="beatle" /> George</label></li> -<li><label><input type="radio" id="foo_3" value="R" name="beatle" /> Ringo</label></li> -</ul> - -# Attributes provided at render-time are passed to the constituent inputs ->>> w = RadioSelect() ->>> print w.render('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')), attrs={'id':'bar'}) -<ul> -<li><label><input checked="checked" type="radio" id="bar_0" value="J" name="beatle" /> John</label></li> -<li><label><input type="radio" id="bar_1" value="P" name="beatle" /> Paul</label></li> -<li><label><input type="radio" id="bar_2" value="G" name="beatle" /> George</label></li> -<li><label><input type="radio" id="bar_3" value="R" name="beatle" /> Ringo</label></li> -</ul> - -# CheckboxSelectMultiple Widget ############################################### - ->>> w = CheckboxSelectMultiple() ->>> print w.render('beatles', ['J'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) -<ul> -<li><label><input checked="checked" type="checkbox" name="beatles" value="J" /> John</label></li> -<li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li> -<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li> -<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li> -</ul> ->>> print w.render('beatles', ['J', 'P'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) -<ul> -<li><label><input checked="checked" type="checkbox" name="beatles" value="J" /> John</label></li> -<li><label><input checked="checked" type="checkbox" name="beatles" value="P" /> Paul</label></li> -<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li> -<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li> -</ul> ->>> print w.render('beatles', ['J', 'P', 'R'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) -<ul> -<li><label><input checked="checked" type="checkbox" name="beatles" value="J" /> John</label></li> -<li><label><input checked="checked" type="checkbox" name="beatles" value="P" /> Paul</label></li> -<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li> -<li><label><input checked="checked" type="checkbox" name="beatles" value="R" /> Ringo</label></li> -</ul> - -If the value is None, none of the options are selected: ->>> print w.render('beatles', None, choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) -<ul> -<li><label><input type="checkbox" name="beatles" value="J" /> John</label></li> -<li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li> -<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li> -<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li> -</ul> - -If the value corresponds to a label (but not to an option value), none of the options are selected: ->>> print w.render('beatles', ['John'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) -<ul> -<li><label><input type="checkbox" name="beatles" value="J" /> John</label></li> -<li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li> -<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li> -<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li> -</ul> - -If multiple values are given, but some of them are not valid, the valid ones are selected: ->>> print w.render('beatles', ['J', 'G', 'foo'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) -<ul> -<li><label><input checked="checked" type="checkbox" name="beatles" value="J" /> John</label></li> -<li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li> -<li><label><input checked="checked" type="checkbox" name="beatles" value="G" /> George</label></li> -<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li> -</ul> - -The value is compared to its str(): ->>> print w.render('nums', [2], choices=[('1', '1'), ('2', '2'), ('3', '3')]) -<ul> -<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> -<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> -<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> -</ul> ->>> print w.render('nums', ['2'], choices=[(1, 1), (2, 2), (3, 3)]) -<ul> -<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> -<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> -<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> -</ul> ->>> print w.render('nums', [2], choices=[(1, 1), (2, 2), (3, 3)]) -<ul> -<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> -<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> -<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> -</ul> - -The 'choices' argument can be any iterable: ->>> def get_choices(): -... for i in range(5): -... yield (i, i) ->>> print w.render('nums', [2], choices=get_choices()) -<ul> -<li><label><input type="checkbox" name="nums" value="0" /> 0</label></li> -<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> -<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> -<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> -<li><label><input type="checkbox" name="nums" value="4" /> 4</label></li> -</ul> - -You can also pass 'choices' to the constructor: ->>> w = CheckboxSelectMultiple(choices=[(1, 1), (2, 2), (3, 3)]) ->>> print w.render('nums', [2]) -<ul> -<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> -<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> -<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> -</ul> - -If 'choices' is passed to both the constructor and render(), then they'll both be in the output: ->>> print w.render('nums', [2], choices=[(4, 4), (5, 5)]) -<ul> -<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> -<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> -<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> -<li><label><input type="checkbox" name="nums" value="4" /> 4</label></li> -<li><label><input type="checkbox" name="nums" value="5" /> 5</label></li> -</ul> - ->>> w.render('nums', ['ŠĐĆŽćžšđ'], choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')]) -u'<ul>\n<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li>\n<li><label><input type="checkbox" name="nums" value="2" /> 2</label></li>\n<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li>\n<li><label><input checked="checked" type="checkbox" name="nums" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" /> \u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</label></li>\n<li><label><input type="checkbox" name="nums" value="\u0107\u017e\u0161\u0111" /> abc\u0107\u017e\u0161\u0111</label></li>\n</ul>' - -# MultiWidget ################################################################# - ->>> class MyMultiWidget(MultiWidget): -... def decompress(self, value): -... if value: -... return value.split('__') -... return ['', ''] -... def format_output(self, rendered_widgets): -... return u'<br />'.join(rendered_widgets) ->>> w = MyMultiWidget(widgets=(TextInput(attrs={'class': 'big'}), TextInput(attrs={'class': 'small'}))) ->>> w.render('name', ['john', 'lennon']) -u'<input type="text" class="big" value="john" name="name_0" /><br /><input type="text" class="small" value="lennon" name="name_1" />' ->>> w.render('name', 'john__lennon') -u'<input type="text" class="big" value="john" name="name_0" /><br /><input type="text" class="small" value="lennon" name="name_1" />' ->>> w.render('name', 'john__lennon', attrs={'id':'foo'}) -u'<input id="foo_0" type="text" class="big" value="john" name="name_0" /><br /><input id="foo_1" type="text" class="small" value="lennon" name="name_1" />' ->>> w = MyMultiWidget(widgets=(TextInput(attrs={'class': 'big'}), TextInput(attrs={'class': 'small'})), attrs={'id': 'bar'}) ->>> w.render('name', ['john', 'lennon']) -u'<input id="bar_0" type="text" class="big" value="john" name="name_0" /><br /><input id="bar_1" type="text" class="small" value="lennon" name="name_1" />' - -# SplitDateTimeWidget ######################################################### - ->>> w = SplitDateTimeWidget() ->>> w.render('date', '') -u'<input type="text" name="date_0" /><input type="text" name="date_1" />' ->>> w.render('date', None) -u'<input type="text" name="date_0" /><input type="text" name="date_1" />' ->>> w.render('date', datetime.datetime(2006, 1, 10, 7, 30)) -u'<input type="text" name="date_0" value="2006-01-10" /><input type="text" name="date_1" value="07:30:00" />' ->>> w.render('date', [datetime.date(2006, 1, 10), datetime.time(7, 30)]) -u'<input type="text" name="date_0" value="2006-01-10" /><input type="text" name="date_1" value="07:30:00" />' - -You can also pass 'attrs' to the constructor. In this case, the attrs will be -included on both widgets. ->>> w = SplitDateTimeWidget(attrs={'class': 'pretty'}) ->>> w.render('date', datetime.datetime(2006, 1, 10, 7, 30)) -u'<input type="text" class="pretty" value="2006-01-10" name="date_0" /><input type="text" class="pretty" value="07:30:00" name="date_1" />' - -########## -# Fields # -########## - -Each Field class does some sort of validation. Each Field has a clean() method, -which either raises django.newforms.ValidationError or returns the "clean" -data -- usually a Unicode object, but, in some rare cases, a list. - -Each Field's __init__() takes at least these parameters: - required -- Boolean that specifies whether the field is required. - True by default. - widget -- A Widget class, or instance of a Widget class, that should be - used for this Field when displaying it. Each Field has a default - Widget that it'll use if you don't specify this. In most cases, - the default widget is TextInput. - label -- A verbose name for this field, for use in displaying this field in - a form. By default, Django will use a "pretty" version of the form - field name, if the Field is part of a Form. - initial -- A value to use in this Field's initial display. This value is - *not* used as a fallback if data isn't given. - -Other than that, the Field subclasses have class-specific options for -__init__(). For example, CharField has a max_length option. - -# CharField ################################################################### - ->>> f = CharField() ->>> f.clean(1) -u'1' ->>> f.clean('hello') -u'hello' ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean([1, 2, 3]) -u'[1, 2, 3]' - ->>> f = CharField(required=False) ->>> f.clean(1) -u'1' ->>> f.clean('hello') -u'hello' ->>> f.clean(None) -u'' ->>> f.clean('') -u'' ->>> f.clean([1, 2, 3]) -u'[1, 2, 3]' - -CharField accepts an optional max_length parameter: ->>> f = CharField(max_length=10, required=False) ->>> f.clean('12345') -u'12345' ->>> f.clean('1234567890') -u'1234567890' ->>> f.clean('1234567890a') -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value has at most 10 characters (it has 11).'] - -CharField accepts an optional min_length parameter: ->>> f = CharField(min_length=10, required=False) ->>> f.clean('') -u'' ->>> f.clean('12345') -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value has at least 10 characters (it has 5).'] ->>> f.clean('1234567890') -u'1234567890' ->>> f.clean('1234567890a') -u'1234567890a' - ->>> f = CharField(min_length=10, required=True) ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean('12345') -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value has at least 10 characters (it has 5).'] ->>> f.clean('1234567890') -u'1234567890' ->>> f.clean('1234567890a') -u'1234567890a' - -# IntegerField ################################################################ - ->>> f = IntegerField() ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean('1') -1 ->>> isinstance(f.clean('1'), int) -True ->>> f.clean('23') -23 ->>> f.clean('a') -Traceback (most recent call last): -... -ValidationError: [u'Enter a whole number.'] ->>> f.clean('1 ') -1 ->>> f.clean(' 1') -1 ->>> f.clean(' 1 ') -1 ->>> f.clean('1a') -Traceback (most recent call last): -... -ValidationError: [u'Enter a whole number.'] - ->>> f = IntegerField(required=False) ->>> f.clean('') ->>> repr(f.clean('')) -'None' ->>> f.clean(None) ->>> repr(f.clean(None)) -'None' ->>> f.clean('1') -1 ->>> isinstance(f.clean('1'), int) -True ->>> f.clean('23') -23 ->>> f.clean('a') -Traceback (most recent call last): -... -ValidationError: [u'Enter a whole number.'] ->>> f.clean('1 ') -1 ->>> f.clean(' 1') -1 ->>> f.clean(' 1 ') -1 ->>> f.clean('1a') -Traceback (most recent call last): -... -ValidationError: [u'Enter a whole number.'] - -IntegerField accepts an optional max_value parameter: ->>> f = IntegerField(max_value=10) ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean(1) -1 ->>> f.clean(10) -10 ->>> f.clean(11) -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value is less than or equal to 10.'] ->>> f.clean('10') -10 ->>> f.clean('11') -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value is less than or equal to 10.'] - -IntegerField accepts an optional min_value parameter: ->>> f = IntegerField(min_value=10) ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean(1) -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value is greater than or equal to 10.'] ->>> f.clean(10) -10 ->>> f.clean(11) -11 ->>> f.clean('10') -10 ->>> f.clean('11') -11 - -min_value and max_value can be used together: ->>> f = IntegerField(min_value=10, max_value=20) ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean(1) -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value is greater than or equal to 10.'] ->>> f.clean(10) -10 ->>> f.clean(11) -11 ->>> f.clean('10') -10 ->>> f.clean('11') -11 ->>> f.clean(20) -20 ->>> f.clean(21) -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value is less than or equal to 20.'] - -# FloatField ################################################################## - ->>> f = FloatField() ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean('1') -1.0 ->>> isinstance(f.clean('1'), float) -True ->>> f.clean('23') -23.0 ->>> f.clean('3.14') -3.1400000000000001 ->>> f.clean('a') -Traceback (most recent call last): -... -ValidationError: [u'Enter a number.'] ->>> f.clean('1.0 ') -1.0 ->>> f.clean(' 1.0') -1.0 ->>> f.clean(' 1.0 ') -1.0 ->>> f.clean('1.0a') -Traceback (most recent call last): -... -ValidationError: [u'Enter a number.'] - ->>> f = FloatField(required=False) ->>> f.clean('') - ->>> f.clean(None) - ->>> f.clean('1') -1.0 - -FloatField accepts min_value and max_value just like IntegerField: ->>> f = FloatField(max_value=1.5, min_value=0.5) - ->>> f.clean('1.6') -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value is less than or equal to 1.5.'] ->>> f.clean('0.4') -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value is greater than or equal to 0.5.'] ->>> f.clean('1.5') -1.5 ->>> f.clean('0.5') -0.5 - -# DecimalField ################################################################ - ->>> f = DecimalField(max_digits=4, decimal_places=2) ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean('1') -Decimal("1") ->>> isinstance(f.clean('1'), Decimal) -True ->>> f.clean('23') -Decimal("23") ->>> f.clean('3.14') -Decimal("3.14") ->>> f.clean('a') -Traceback (most recent call last): -... -ValidationError: [u'Enter a number.'] ->>> f.clean('1.0 ') -Decimal("1.0") ->>> f.clean(' 1.0') -Decimal("1.0") ->>> f.clean(' 1.0 ') -Decimal("1.0") ->>> f.clean('1.0a') -Traceback (most recent call last): -... -ValidationError: [u'Enter a number.'] ->>> f.clean('123.45') -Traceback (most recent call last): -... -ValidationError: [u'Ensure that there are no more than 4 digits in total.'] ->>> f.clean('1.234') -Traceback (most recent call last): -... -ValidationError: [u'Ensure that there are no more than 2 decimal places.'] ->>> f.clean('123.4') -Traceback (most recent call last): -... -ValidationError: [u'Ensure that there are no more than 2 digits before the decimal point.'] ->>> f = DecimalField(max_digits=4, decimal_places=2, required=False) ->>> f.clean('') - ->>> f.clean(None) - ->>> f.clean('1') -Decimal("1") - -DecimalField accepts min_value and max_value just like IntegerField: ->>> f = DecimalField(max_digits=4, decimal_places=2, max_value=Decimal('1.5'), min_value=Decimal('0.5')) - ->>> f.clean('1.6') -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value is less than or equal to 1.5.'] ->>> f.clean('0.4') -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value is greater than or equal to 0.5.'] ->>> f.clean('1.5') -Decimal("1.5") ->>> f.clean('0.5') -Decimal("0.5") ->>> f.clean('.5') -Decimal("0.5") ->>> f.clean('00.50') -Decimal("0.50") - -# DateField ################################################################### - ->>> import datetime ->>> f = DateField() ->>> f.clean(datetime.date(2006, 10, 25)) -datetime.date(2006, 10, 25) ->>> f.clean(datetime.datetime(2006, 10, 25, 14, 30)) -datetime.date(2006, 10, 25) ->>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59)) -datetime.date(2006, 10, 25) ->>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59, 200)) -datetime.date(2006, 10, 25) ->>> f.clean('2006-10-25') -datetime.date(2006, 10, 25) ->>> f.clean('10/25/2006') -datetime.date(2006, 10, 25) ->>> f.clean('10/25/06') -datetime.date(2006, 10, 25) ->>> f.clean('Oct 25 2006') -datetime.date(2006, 10, 25) ->>> f.clean('October 25 2006') -datetime.date(2006, 10, 25) ->>> f.clean('October 25, 2006') -datetime.date(2006, 10, 25) ->>> f.clean('25 October 2006') -datetime.date(2006, 10, 25) ->>> f.clean('25 October, 2006') -datetime.date(2006, 10, 25) ->>> f.clean('2006-4-31') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid date.'] ->>> f.clean('200a-10-25') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid date.'] ->>> f.clean('25/10/06') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid date.'] ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] - ->>> f = DateField(required=False) ->>> f.clean(None) ->>> repr(f.clean(None)) -'None' ->>> f.clean('') ->>> repr(f.clean('')) -'None' - -DateField accepts an optional input_formats parameter: ->>> f = DateField(input_formats=['%Y %m %d']) ->>> f.clean(datetime.date(2006, 10, 25)) -datetime.date(2006, 10, 25) ->>> f.clean(datetime.datetime(2006, 10, 25, 14, 30)) -datetime.date(2006, 10, 25) ->>> f.clean('2006 10 25') -datetime.date(2006, 10, 25) - -The input_formats parameter overrides all default input formats, -so the default formats won't work unless you specify them: ->>> f.clean('2006-10-25') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid date.'] ->>> f.clean('10/25/2006') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid date.'] ->>> f.clean('10/25/06') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid date.'] - -# TimeField ################################################################### - ->>> import datetime ->>> f = TimeField() ->>> f.clean(datetime.time(14, 25)) -datetime.time(14, 25) ->>> f.clean(datetime.time(14, 25, 59)) -datetime.time(14, 25, 59) ->>> f.clean('14:25') -datetime.time(14, 25) ->>> f.clean('14:25:59') -datetime.time(14, 25, 59) ->>> f.clean('hello') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid time.'] ->>> f.clean('1:24 p.m.') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid time.'] - -TimeField accepts an optional input_formats parameter: ->>> f = TimeField(input_formats=['%I:%M %p']) ->>> f.clean(datetime.time(14, 25)) -datetime.time(14, 25) ->>> f.clean(datetime.time(14, 25, 59)) -datetime.time(14, 25, 59) ->>> f.clean('4:25 AM') -datetime.time(4, 25) ->>> f.clean('4:25 PM') -datetime.time(16, 25) - -The input_formats parameter overrides all default input formats, -so the default formats won't work unless you specify them: ->>> f.clean('14:30:45') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid time.'] - -# DateTimeField ############################################################### - ->>> import datetime ->>> f = DateTimeField() ->>> f.clean(datetime.date(2006, 10, 25)) -datetime.datetime(2006, 10, 25, 0, 0) ->>> f.clean(datetime.datetime(2006, 10, 25, 14, 30)) -datetime.datetime(2006, 10, 25, 14, 30) ->>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59)) -datetime.datetime(2006, 10, 25, 14, 30, 59) ->>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59, 200)) -datetime.datetime(2006, 10, 25, 14, 30, 59, 200) ->>> f.clean('2006-10-25 14:30:45') -datetime.datetime(2006, 10, 25, 14, 30, 45) ->>> f.clean('2006-10-25 14:30:00') -datetime.datetime(2006, 10, 25, 14, 30) ->>> f.clean('2006-10-25 14:30') -datetime.datetime(2006, 10, 25, 14, 30) ->>> f.clean('2006-10-25') -datetime.datetime(2006, 10, 25, 0, 0) ->>> f.clean('10/25/2006 14:30:45') -datetime.datetime(2006, 10, 25, 14, 30, 45) ->>> f.clean('10/25/2006 14:30:00') -datetime.datetime(2006, 10, 25, 14, 30) ->>> f.clean('10/25/2006 14:30') -datetime.datetime(2006, 10, 25, 14, 30) ->>> f.clean('10/25/2006') -datetime.datetime(2006, 10, 25, 0, 0) ->>> f.clean('10/25/06 14:30:45') -datetime.datetime(2006, 10, 25, 14, 30, 45) ->>> f.clean('10/25/06 14:30:00') -datetime.datetime(2006, 10, 25, 14, 30) ->>> f.clean('10/25/06 14:30') -datetime.datetime(2006, 10, 25, 14, 30) ->>> f.clean('10/25/06') -datetime.datetime(2006, 10, 25, 0, 0) ->>> f.clean('hello') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid date/time.'] ->>> f.clean('2006-10-25 4:30 p.m.') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid date/time.'] - -DateField accepts an optional input_formats parameter: ->>> f = DateTimeField(input_formats=['%Y %m %d %I:%M %p']) ->>> f.clean(datetime.date(2006, 10, 25)) -datetime.datetime(2006, 10, 25, 0, 0) ->>> f.clean(datetime.datetime(2006, 10, 25, 14, 30)) -datetime.datetime(2006, 10, 25, 14, 30) ->>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59)) -datetime.datetime(2006, 10, 25, 14, 30, 59) ->>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59, 200)) -datetime.datetime(2006, 10, 25, 14, 30, 59, 200) ->>> f.clean('2006 10 25 2:30 PM') -datetime.datetime(2006, 10, 25, 14, 30) - -The input_formats parameter overrides all default input formats, -so the default formats won't work unless you specify them: ->>> f.clean('2006-10-25 14:30:45') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid date/time.'] - ->>> f = DateTimeField(required=False) ->>> f.clean(None) ->>> repr(f.clean(None)) -'None' ->>> f.clean('') ->>> repr(f.clean('')) -'None' - -# RegexField ################################################################## - ->>> f = RegexField('^\d[A-F]\d$') ->>> f.clean('2A2') -u'2A2' ->>> f.clean('3F3') -u'3F3' ->>> f.clean('3G3') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid value.'] ->>> f.clean(' 2A2') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid value.'] ->>> f.clean('2A2 ') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid value.'] ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] - ->>> f = RegexField('^\d[A-F]\d$', required=False) ->>> f.clean('2A2') -u'2A2' ->>> f.clean('3F3') -u'3F3' ->>> f.clean('3G3') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid value.'] ->>> f.clean('') -u'' - -Alternatively, RegexField can take a compiled regular expression: ->>> f = RegexField(re.compile('^\d[A-F]\d$')) ->>> f.clean('2A2') -u'2A2' ->>> f.clean('3F3') -u'3F3' ->>> f.clean('3G3') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid value.'] ->>> f.clean(' 2A2') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid value.'] ->>> f.clean('2A2 ') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid value.'] - -RegexField takes an optional error_message argument: ->>> f = RegexField('^\d\d\d\d$', error_message='Enter a four-digit number.') ->>> f.clean('1234') -u'1234' ->>> f.clean('123') -Traceback (most recent call last): -... -ValidationError: [u'Enter a four-digit number.'] ->>> f.clean('abcd') -Traceback (most recent call last): -... -ValidationError: [u'Enter a four-digit number.'] - -RegexField also access min_length and max_length parameters, for convenience. ->>> f = RegexField('^\d+$', min_length=5, max_length=10) ->>> f.clean('123') -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value has at least 5 characters (it has 3).'] ->>> f.clean('abc') -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value has at least 5 characters (it has 3).'] ->>> f.clean('12345') -u'12345' ->>> f.clean('1234567890') -u'1234567890' ->>> f.clean('12345678901') -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value has at most 10 characters (it has 11).'] ->>> f.clean('12345a') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid value.'] - -# EmailField ################################################################## - ->>> f = EmailField() ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean('person@example.com') -u'person@example.com' ->>> f.clean('foo') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid e-mail address.'] ->>> f.clean('foo@') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid e-mail address.'] ->>> f.clean('foo@bar') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid e-mail address.'] - ->>> f = EmailField(required=False) ->>> f.clean('') -u'' ->>> f.clean(None) -u'' ->>> f.clean('person@example.com') -u'person@example.com' ->>> f.clean('foo') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid e-mail address.'] ->>> f.clean('foo@') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid e-mail address.'] ->>> f.clean('foo@bar') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid e-mail address.'] - -EmailField also access min_length and max_length parameters, for convenience. ->>> f = EmailField(min_length=10, max_length=15) ->>> f.clean('a@foo.com') -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value has at least 10 characters (it has 9).'] ->>> f.clean('alf@foo.com') -u'alf@foo.com' ->>> f.clean('alf123456788@foo.com') -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value has at most 15 characters (it has 20).'] - -# FileField ################################################################## - ->>> f = FileField() ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] - ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] - ->>> f.clean({}) -Traceback (most recent call last): -... -ValidationError: [u'No file was submitted.'] - ->>> f.clean('some content that is not a file') -Traceback (most recent call last): -... -ValidationError: [u'No file was submitted. Check the encoding type on the form.'] - ->>> f.clean({'filename': 'name', 'content':None}) -Traceback (most recent call last): -... -ValidationError: [u'The submitted file is empty.'] - ->>> f.clean({'filename': 'name', 'content':''}) -Traceback (most recent call last): -... -ValidationError: [u'The submitted file is empty.'] - ->>> type(f.clean({'filename': 'name', 'content':'Some File Content'})) -<class 'django.newforms.fields.UploadedFile'> - -# URLField ################################################################## - ->>> f = URLField() ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean('http://example.com') -u'http://example.com' ->>> f.clean('http://www.example.com') -u'http://www.example.com' ->>> f.clean('foo') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid URL.'] ->>> f.clean('example.com') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid URL.'] ->>> f.clean('http://') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid URL.'] ->>> f.clean('http://example') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid URL.'] ->>> f.clean('http://example.') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid URL.'] ->>> f.clean('http://.com') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid URL.'] - ->>> f = URLField(required=False) ->>> f.clean('') -u'' ->>> f.clean(None) -u'' ->>> f.clean('http://example.com') -u'http://example.com' ->>> f.clean('http://www.example.com') -u'http://www.example.com' ->>> f.clean('foo') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid URL.'] ->>> f.clean('example.com') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid URL.'] ->>> f.clean('http://') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid URL.'] ->>> f.clean('http://example') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid URL.'] ->>> f.clean('http://example.') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid URL.'] ->>> f.clean('http://.com') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid URL.'] - -URLField takes an optional verify_exists parameter, which is False by default. -This verifies that the URL is live on the Internet and doesn't return a 404 or 500: ->>> f = URLField(verify_exists=True) ->>> f.clean('http://www.google.com') # This will fail if there's no Internet connection -u'http://www.google.com' ->>> f.clean('http://example') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid URL.'] ->>> f.clean('http://www.jfoiwjfoi23jfoijoaijfoiwjofiwjefewl.com') # bad domain -Traceback (most recent call last): -... -ValidationError: [u'This URL appears to be a broken link.'] ->>> f.clean('http://google.com/we-love-microsoft.html') # good domain, bad page -Traceback (most recent call last): -... -ValidationError: [u'This URL appears to be a broken link.'] ->>> f = URLField(verify_exists=True, required=False) ->>> f.clean('') -u'' ->>> f.clean('http://www.google.com') # This will fail if there's no Internet connection -u'http://www.google.com' - -URLField also access min_length and max_length parameters, for convenience. ->>> f = URLField(min_length=15, max_length=20) ->>> f.clean('http://f.com') -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value has at least 15 characters (it has 12).'] ->>> f.clean('http://example.com') -u'http://example.com' ->>> f.clean('http://abcdefghijklmnopqrstuvwxyz.com') -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value has at most 20 characters (it has 37).'] - -# BooleanField ################################################################ - ->>> f = BooleanField() ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean(True) -True ->>> f.clean(False) -False ->>> f.clean(1) -True ->>> f.clean(0) -False ->>> f.clean('Django rocks') -True - ->>> f = BooleanField(required=False) ->>> f.clean('') -False ->>> f.clean(None) -False ->>> f.clean(True) -True ->>> f.clean(False) -False ->>> f.clean(1) -True ->>> f.clean(0) -False ->>> f.clean('Django rocks') -True - -# ChoiceField ################################################################# - ->>> f = ChoiceField(choices=[('1', '1'), ('2', '2')]) ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean(1) -u'1' ->>> f.clean('1') -u'1' ->>> f.clean('3') -Traceback (most recent call last): -... -ValidationError: [u'Select a valid choice. That choice is not one of the available choices.'] - ->>> f = ChoiceField(choices=[('1', '1'), ('2', '2')], required=False) ->>> f.clean('') -u'' ->>> f.clean(None) -u'' ->>> f.clean(1) -u'1' ->>> f.clean('1') -u'1' ->>> f.clean('3') -Traceback (most recent call last): -... -ValidationError: [u'Select a valid choice. That choice is not one of the available choices.'] - ->>> f = ChoiceField(choices=[('J', 'John'), ('P', 'Paul')]) ->>> f.clean('J') -u'J' ->>> f.clean('John') -Traceback (most recent call last): -... -ValidationError: [u'Select a valid choice. That choice is not one of the available choices.'] - -# NullBooleanField ############################################################ - ->>> f = NullBooleanField() ->>> f.clean('') ->>> f.clean(True) -True ->>> f.clean(False) -False ->>> f.clean(None) ->>> f.clean('1') ->>> f.clean('2') ->>> f.clean('3') ->>> f.clean('hello') - -# MultipleChoiceField ######################################################### - ->>> f = MultipleChoiceField(choices=[('1', '1'), ('2', '2')]) ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean([1]) -[u'1'] ->>> f.clean(['1']) -[u'1'] ->>> f.clean(['1', '2']) -[u'1', u'2'] ->>> f.clean([1, '2']) -[u'1', u'2'] ->>> f.clean((1, '2')) -[u'1', u'2'] ->>> f.clean('hello') -Traceback (most recent call last): -... -ValidationError: [u'Enter a list of values.'] ->>> f.clean([]) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean(()) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean(['3']) -Traceback (most recent call last): -... -ValidationError: [u'Select a valid choice. 3 is not one of the available choices.'] - ->>> f = MultipleChoiceField(choices=[('1', '1'), ('2', '2')], required=False) ->>> f.clean('') -[] ->>> f.clean(None) -[] ->>> f.clean([1]) -[u'1'] ->>> f.clean(['1']) -[u'1'] ->>> f.clean(['1', '2']) -[u'1', u'2'] ->>> f.clean([1, '2']) -[u'1', u'2'] ->>> f.clean((1, '2')) -[u'1', u'2'] ->>> f.clean('hello') -Traceback (most recent call last): -... -ValidationError: [u'Enter a list of values.'] ->>> f.clean([]) -[] ->>> f.clean(()) -[] ->>> f.clean(['3']) -Traceback (most recent call last): -... -ValidationError: [u'Select a valid choice. 3 is not one of the available choices.'] - -# ComboField ################################################################## - -ComboField takes a list of fields that should be used to validate a value, -in that order. ->>> f = ComboField(fields=[CharField(max_length=20), EmailField()]) ->>> f.clean('test@example.com') -u'test@example.com' ->>> f.clean('longemailaddress@example.com') -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value has at most 20 characters (it has 28).'] ->>> f.clean('not an e-mail') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid e-mail address.'] ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] - ->>> f = ComboField(fields=[CharField(max_length=20), EmailField()], required=False) ->>> f.clean('test@example.com') -u'test@example.com' ->>> f.clean('longemailaddress@example.com') -Traceback (most recent call last): -... -ValidationError: [u'Ensure this value has at most 20 characters (it has 28).'] ->>> f.clean('not an e-mail') -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid e-mail address.'] ->>> f.clean('') -u'' ->>> f.clean(None) -u'' - -# SplitDateTimeField ########################################################## - ->>> f = SplitDateTimeField() ->>> f.clean([datetime.date(2006, 1, 10), datetime.time(7, 30)]) -datetime.datetime(2006, 1, 10, 7, 30) ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean('hello') -Traceback (most recent call last): -... -ValidationError: [u'Enter a list of values.'] ->>> f.clean(['hello', 'there']) -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid date.', u'Enter a valid time.'] ->>> f.clean(['2006-01-10', 'there']) -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid time.'] ->>> f.clean(['hello', '07:30']) -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid date.'] - ->>> f = SplitDateTimeField(required=False) ->>> f.clean([datetime.date(2006, 1, 10), datetime.time(7, 30)]) -datetime.datetime(2006, 1, 10, 7, 30) ->>> f.clean(['2006-01-10', '07:30']) -datetime.datetime(2006, 1, 10, 7, 30) ->>> f.clean(None) ->>> f.clean('') ->>> f.clean(['']) ->>> f.clean(['', '']) ->>> f.clean('hello') -Traceback (most recent call last): -... -ValidationError: [u'Enter a list of values.'] ->>> f.clean(['hello', 'there']) -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid date.', u'Enter a valid time.'] ->>> f.clean(['2006-01-10', 'there']) -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid time.'] ->>> f.clean(['hello', '07:30']) -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid date.'] ->>> f.clean(['2006-01-10', '']) -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid time.'] ->>> f.clean(['2006-01-10']) -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid time.'] ->>> f.clean(['', '07:30']) -Traceback (most recent call last): -... -ValidationError: [u'Enter a valid date.'] - -######### -# Forms # -######### - -A Form is a collection of Fields. It knows how to validate a set of data and it -knows how to render itself in a couple of default ways (e.g., an HTML table). -You can pass it data in __init__(), as a dictionary. - -# Form ######################################################################## - ->>> class Person(Form): -... first_name = CharField() -... last_name = CharField() -... birthday = DateField() - -Pass a dictionary to a Form's __init__(). ->>> p = Person({'first_name': u'John', 'last_name': u'Lennon', 'birthday': u'1940-10-9'}) ->>> p.is_bound -True ->>> p.errors -{} ->>> p.is_valid() -True ->>> p.errors.as_ul() -u'' ->>> p.errors.as_text() -u'' ->>> p.cleaned_data -{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)} ->>> print p['first_name'] -<input type="text" name="first_name" value="John" id="id_first_name" /> ->>> print p['last_name'] -<input type="text" name="last_name" value="Lennon" id="id_last_name" /> ->>> print p['birthday'] -<input type="text" name="birthday" value="1940-10-9" id="id_birthday" /> ->>> print p['nonexistentfield'] -Traceback (most recent call last): -... -KeyError: "Key 'nonexistentfield' not found in Form" - ->>> for boundfield in p: -... print boundfield -<input type="text" name="first_name" value="John" id="id_first_name" /> -<input type="text" name="last_name" value="Lennon" id="id_last_name" /> -<input type="text" name="birthday" value="1940-10-9" id="id_birthday" /> ->>> for boundfield in p: -... print boundfield.label, boundfield.data -First name John -Last name Lennon -Birthday 1940-10-9 ->>> print p -<tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" value="John" id="id_first_name" /></td></tr> -<tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" value="Lennon" id="id_last_name" /></td></tr> -<tr><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" value="1940-10-9" id="id_birthday" /></td></tr> - -Empty dictionaries are valid, too. ->>> p = Person({}) ->>> p.is_bound -True ->>> p.errors -{'first_name': [u'This field is required.'], 'last_name': [u'This field is required.'], 'birthday': [u'This field is required.']} ->>> p.is_valid() -False ->>> p.cleaned_data -Traceback (most recent call last): -... -AttributeError: 'Person' object has no attribute 'cleaned_data' ->>> print p -<tr><th><label for="id_first_name">First name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="first_name" id="id_first_name" /></td></tr> -<tr><th><label for="id_last_name">Last name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="last_name" id="id_last_name" /></td></tr> -<tr><th><label for="id_birthday">Birthday:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="birthday" id="id_birthday" /></td></tr> ->>> print p.as_table() -<tr><th><label for="id_first_name">First name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="first_name" id="id_first_name" /></td></tr> -<tr><th><label for="id_last_name">Last name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="last_name" id="id_last_name" /></td></tr> -<tr><th><label for="id_birthday">Birthday:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="birthday" id="id_birthday" /></td></tr> ->>> print p.as_ul() -<li><ul class="errorlist"><li>This field is required.</li></ul><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></li> -<li><ul class="errorlist"><li>This field is required.</li></ul><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></li> -<li><ul class="errorlist"><li>This field is required.</li></ul><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /></li> ->>> print p.as_p() -<ul class="errorlist"><li>This field is required.</li></ul> -<p><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></p> -<ul class="errorlist"><li>This field is required.</li></ul> -<p><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></p> -<ul class="errorlist"><li>This field is required.</li></ul> -<p><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /></p> - -If you don't pass any values to the Form's __init__(), or if you pass None, -the Form will be considered unbound and won't do any validation. Form.errors -will be an empty dictionary *but* Form.is_valid() will return False. ->>> p = Person() ->>> p.is_bound -False ->>> p.errors -{} ->>> p.is_valid() -False ->>> p.cleaned_data -Traceback (most recent call last): -... -AttributeError: 'Person' object has no attribute 'cleaned_data' ->>> print p -<tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" id="id_first_name" /></td></tr> -<tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" id="id_last_name" /></td></tr> -<tr><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" id="id_birthday" /></td></tr> ->>> print p.as_table() -<tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" id="id_first_name" /></td></tr> -<tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" id="id_last_name" /></td></tr> -<tr><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" id="id_birthday" /></td></tr> ->>> print p.as_ul() -<li><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></li> -<li><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></li> -<li><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /></li> ->>> print p.as_p() -<p><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></p> -<p><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></p> -<p><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /></p> - -Unicode values are handled properly. ->>> p = Person({'first_name': u'John', 'last_name': u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111', 'birthday': '1940-10-9'}) ->>> p.as_table() -u'<tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" value="John" id="id_first_name" /></td></tr>\n<tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" id="id_last_name" /></td></tr>\n<tr><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" value="1940-10-9" id="id_birthday" /></td></tr>' ->>> p.as_ul() -u'<li><label for="id_first_name">First name:</label> <input type="text" name="first_name" value="John" id="id_first_name" /></li>\n<li><label for="id_last_name">Last name:</label> <input type="text" name="last_name" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" id="id_last_name" /></li>\n<li><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" value="1940-10-9" id="id_birthday" /></li>' ->>> p.as_p() -u'<p><label for="id_first_name">First name:</label> <input type="text" name="first_name" value="John" id="id_first_name" /></p>\n<p><label for="id_last_name">Last name:</label> <input type="text" name="last_name" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" id="id_last_name" /></p>\n<p><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" value="1940-10-9" id="id_birthday" /></p>' - ->>> p = Person({'last_name': u'Lennon'}) ->>> p.errors -{'first_name': [u'This field is required.'], 'birthday': [u'This field is required.']} ->>> p.is_valid() -False ->>> p.errors.as_ul() -u'<ul class="errorlist"><li>first_name<ul class="errorlist"><li>This field is required.</li></ul></li><li>birthday<ul class="errorlist"><li>This field is required.</li></ul></li></ul>' ->>> print p.errors.as_text() -* first_name - * This field is required. -* birthday - * This field is required. ->>> p.cleaned_data -Traceback (most recent call last): -... -AttributeError: 'Person' object has no attribute 'cleaned_data' ->>> p['first_name'].errors -[u'This field is required.'] ->>> p['first_name'].errors.as_ul() -u'<ul class="errorlist"><li>This field is required.</li></ul>' ->>> p['first_name'].errors.as_text() -u'* This field is required.' - ->>> p = Person() ->>> print p['first_name'] -<input type="text" name="first_name" id="id_first_name" /> ->>> print p['last_name'] -<input type="text" name="last_name" id="id_last_name" /> ->>> print p['birthday'] -<input type="text" name="birthday" id="id_birthday" /> - -cleaned_data will always *only* contain a key for fields defined in the -Form, even if you pass extra data when you define the Form. In this -example, we pass a bunch of extra fields to the form constructor, -but cleaned_data contains only the form's fields. ->>> data = {'first_name': u'John', 'last_name': u'Lennon', 'birthday': u'1940-10-9', 'extra1': 'hello', 'extra2': 'hello'} ->>> p = Person(data) ->>> p.is_valid() -True ->>> p.cleaned_data -{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)} - -cleaned_data will include a key and value for *all* fields defined in the Form, -even if the Form's data didn't include a value for fields that are not -required. In this example, the data dictionary doesn't include a value for the -"nick_name" field, but cleaned_data includes it. For CharFields, it's set to the -empty string. ->>> class OptionalPersonForm(Form): -... first_name = CharField() -... last_name = CharField() -... nick_name = CharField(required=False) ->>> data = {'first_name': u'John', 'last_name': u'Lennon'} ->>> f = OptionalPersonForm(data) ->>> f.is_valid() -True ->>> f.cleaned_data -{'nick_name': u'', 'first_name': u'John', 'last_name': u'Lennon'} - -For DateFields, it's set to None. ->>> class OptionalPersonForm(Form): -... first_name = CharField() -... last_name = CharField() -... birth_date = DateField(required=False) ->>> data = {'first_name': u'John', 'last_name': u'Lennon'} ->>> f = OptionalPersonForm(data) ->>> f.is_valid() -True ->>> f.cleaned_data -{'birth_date': None, 'first_name': u'John', 'last_name': u'Lennon'} - -"auto_id" tells the Form to add an "id" attribute to each form element. -If it's a string that contains '%s', Django will use that as a format string -into which the field's name will be inserted. It will also put a <label> around -the human-readable labels for a field. ->>> p = Person(auto_id='%s_id') ->>> print p.as_table() -<tr><th><label for="first_name_id">First name:</label></th><td><input type="text" name="first_name" id="first_name_id" /></td></tr> -<tr><th><label for="last_name_id">Last name:</label></th><td><input type="text" name="last_name" id="last_name_id" /></td></tr> -<tr><th><label for="birthday_id">Birthday:</label></th><td><input type="text" name="birthday" id="birthday_id" /></td></tr> ->>> print p.as_ul() -<li><label for="first_name_id">First name:</label> <input type="text" name="first_name" id="first_name_id" /></li> -<li><label for="last_name_id">Last name:</label> <input type="text" name="last_name" id="last_name_id" /></li> -<li><label for="birthday_id">Birthday:</label> <input type="text" name="birthday" id="birthday_id" /></li> ->>> print p.as_p() -<p><label for="first_name_id">First name:</label> <input type="text" name="first_name" id="first_name_id" /></p> -<p><label for="last_name_id">Last name:</label> <input type="text" name="last_name" id="last_name_id" /></p> -<p><label for="birthday_id">Birthday:</label> <input type="text" name="birthday" id="birthday_id" /></p> - -If auto_id is any True value whose str() does not contain '%s', the "id" -attribute will be the name of the field. ->>> p = Person(auto_id=True) ->>> print p.as_ul() -<li><label for="first_name">First name:</label> <input type="text" name="first_name" id="first_name" /></li> -<li><label for="last_name">Last name:</label> <input type="text" name="last_name" id="last_name" /></li> -<li><label for="birthday">Birthday:</label> <input type="text" name="birthday" id="birthday" /></li> - -If auto_id is any False value, an "id" attribute won't be output unless it -was manually entered. ->>> p = Person(auto_id=False) ->>> print p.as_ul() -<li>First name: <input type="text" name="first_name" /></li> -<li>Last name: <input type="text" name="last_name" /></li> -<li>Birthday: <input type="text" name="birthday" /></li> - -In this example, auto_id is False, but the "id" attribute for the "first_name" -field is given. Also note that field gets a <label>, while the others don't. ->>> class PersonNew(Form): -... first_name = CharField(widget=TextInput(attrs={'id': 'first_name_id'})) -... last_name = CharField() -... birthday = DateField() ->>> p = PersonNew(auto_id=False) ->>> print p.as_ul() -<li><label for="first_name_id">First name:</label> <input type="text" id="first_name_id" name="first_name" /></li> -<li>Last name: <input type="text" name="last_name" /></li> -<li>Birthday: <input type="text" name="birthday" /></li> - -If the "id" attribute is specified in the Form and auto_id is True, the "id" -attribute in the Form gets precedence. ->>> p = PersonNew(auto_id=True) ->>> print p.as_ul() -<li><label for="first_name_id">First name:</label> <input type="text" id="first_name_id" name="first_name" /></li> -<li><label for="last_name">Last name:</label> <input type="text" name="last_name" id="last_name" /></li> -<li><label for="birthday">Birthday:</label> <input type="text" name="birthday" id="birthday" /></li> - ->>> class SignupForm(Form): -... email = EmailField() -... get_spam = BooleanField() ->>> f = SignupForm(auto_id=False) ->>> print f['email'] -<input type="text" name="email" /> ->>> print f['get_spam'] -<input type="checkbox" name="get_spam" /> - ->>> f = SignupForm({'email': 'test@example.com', 'get_spam': True}, auto_id=False) ->>> print f['email'] -<input type="text" name="email" value="test@example.com" /> ->>> print f['get_spam'] -<input checked="checked" type="checkbox" name="get_spam" /> - -Any Field can have a Widget class passed to its constructor: ->>> class ContactForm(Form): -... subject = CharField() -... message = CharField(widget=Textarea) ->>> f = ContactForm(auto_id=False) ->>> print f['subject'] -<input type="text" name="subject" /> ->>> print f['message'] -<textarea rows="10" cols="40" name="message"></textarea> - -as_textarea(), as_text() and as_hidden() are shortcuts for changing the output -widget type: ->>> f['subject'].as_textarea() -u'<textarea rows="10" cols="40" name="subject"></textarea>' ->>> f['message'].as_text() -u'<input type="text" name="message" />' ->>> f['message'].as_hidden() -u'<input type="hidden" name="message" />' - -The 'widget' parameter to a Field can also be an instance: ->>> class ContactForm(Form): -... subject = CharField() -... message = CharField(widget=Textarea(attrs={'rows': 80, 'cols': 20})) ->>> f = ContactForm(auto_id=False) ->>> print f['message'] -<textarea rows="80" cols="20" name="message"></textarea> - -Instance-level attrs are *not* carried over to as_textarea(), as_text() and -as_hidden(): ->>> f['message'].as_text() -u'<input type="text" name="message" />' ->>> f = ContactForm({'subject': 'Hello', 'message': 'I love you.'}, auto_id=False) ->>> f['subject'].as_textarea() -u'<textarea rows="10" cols="40" name="subject">Hello</textarea>' ->>> f['message'].as_text() -u'<input type="text" name="message" value="I love you." />' ->>> f['message'].as_hidden() -u'<input type="hidden" name="message" value="I love you." />' - -For a form with a <select>, use ChoiceField: ->>> class FrameworkForm(Form): -... name = CharField() -... language = ChoiceField(choices=[('P', 'Python'), ('J', 'Java')]) ->>> f = FrameworkForm(auto_id=False) ->>> print f['language'] -<select name="language"> -<option value="P">Python</option> -<option value="J">Java</option> -</select> ->>> f = FrameworkForm({'name': 'Django', 'language': 'P'}, auto_id=False) ->>> print f['language'] -<select name="language"> -<option value="P" selected="selected">Python</option> -<option value="J">Java</option> -</select> - -A subtlety: If one of the choices' value is the empty string and the form is -unbound, then the <option> for the empty-string choice will get selected="selected". ->>> class FrameworkForm(Form): -... name = CharField() -... language = ChoiceField(choices=[('', '------'), ('P', 'Python'), ('J', 'Java')]) ->>> f = FrameworkForm(auto_id=False) ->>> print f['language'] -<select name="language"> -<option value="" selected="selected">------</option> -<option value="P">Python</option> -<option value="J">Java</option> -</select> - -You can specify widget attributes in the Widget constructor. ->>> class FrameworkForm(Form): -... name = CharField() -... language = ChoiceField(choices=[('P', 'Python'), ('J', 'Java')], widget=Select(attrs={'class': 'foo'})) ->>> f = FrameworkForm(auto_id=False) ->>> print f['language'] -<select class="foo" name="language"> -<option value="P">Python</option> -<option value="J">Java</option> -</select> ->>> f = FrameworkForm({'name': 'Django', 'language': 'P'}, auto_id=False) ->>> print f['language'] -<select class="foo" name="language"> -<option value="P" selected="selected">Python</option> -<option value="J">Java</option> -</select> - -When passing a custom widget instance to ChoiceField, note that setting -'choices' on the widget is meaningless. The widget will use the choices -defined on the Field, not the ones defined on the Widget. ->>> class FrameworkForm(Form): -... name = CharField() -... language = ChoiceField(choices=[('P', 'Python'), ('J', 'Java')], widget=Select(choices=[('R', 'Ruby'), ('P', 'Perl')], attrs={'class': 'foo'})) ->>> f = FrameworkForm(auto_id=False) ->>> print f['language'] -<select class="foo" name="language"> -<option value="P">Python</option> -<option value="J">Java</option> -</select> ->>> f = FrameworkForm({'name': 'Django', 'language': 'P'}, auto_id=False) ->>> print f['language'] -<select class="foo" name="language"> -<option value="P" selected="selected">Python</option> -<option value="J">Java</option> -</select> - -You can set a ChoiceField's choices after the fact. ->>> class FrameworkForm(Form): -... name = CharField() -... language = ChoiceField() ->>> f = FrameworkForm(auto_id=False) ->>> print f['language'] -<select name="language"> -</select> ->>> f.fields['language'].choices = [('P', 'Python'), ('J', 'Java')] ->>> print f['language'] -<select name="language"> -<option value="P">Python</option> -<option value="J">Java</option> -</select> - -Add widget=RadioSelect to use that widget with a ChoiceField. ->>> class FrameworkForm(Form): -... name = CharField() -... language = ChoiceField(choices=[('P', 'Python'), ('J', 'Java')], widget=RadioSelect) ->>> f = FrameworkForm(auto_id=False) ->>> print f['language'] -<ul> -<li><label><input type="radio" name="language" value="P" /> Python</label></li> -<li><label><input type="radio" name="language" value="J" /> Java</label></li> -</ul> ->>> print f -<tr><th>Name:</th><td><input type="text" name="name" /></td></tr> -<tr><th>Language:</th><td><ul> -<li><label><input type="radio" name="language" value="P" /> Python</label></li> -<li><label><input type="radio" name="language" value="J" /> Java</label></li> -</ul></td></tr> ->>> print f.as_ul() -<li>Name: <input type="text" name="name" /></li> -<li>Language: <ul> -<li><label><input type="radio" name="language" value="P" /> Python</label></li> -<li><label><input type="radio" name="language" value="J" /> Java</label></li> -</ul></li> - -Regarding auto_id and <label>, RadioSelect is a special case. Each radio button -gets a distinct ID, formed by appending an underscore plus the button's -zero-based index. ->>> f = FrameworkForm(auto_id='id_%s') ->>> print f['language'] -<ul> -<li><label><input type="radio" id="id_language_0" value="P" name="language" /> Python</label></li> -<li><label><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li> -</ul> - -When RadioSelect is used with auto_id, and the whole form is printed using -either as_table() or as_ul(), the label for the RadioSelect will point to the -ID of the *first* radio button. ->>> print f -<tr><th><label for="id_name">Name:</label></th><td><input type="text" name="name" id="id_name" /></td></tr> -<tr><th><label for="id_language_0">Language:</label></th><td><ul> -<li><label><input type="radio" id="id_language_0" value="P" name="language" /> Python</label></li> -<li><label><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li> -</ul></td></tr> ->>> print f.as_ul() -<li><label for="id_name">Name:</label> <input type="text" name="name" id="id_name" /></li> -<li><label for="id_language_0">Language:</label> <ul> -<li><label><input type="radio" id="id_language_0" value="P" name="language" /> Python</label></li> -<li><label><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li> -</ul></li> ->>> print f.as_p() -<p><label for="id_name">Name:</label> <input type="text" name="name" id="id_name" /></p> -<p><label for="id_language_0">Language:</label> <ul> -<li><label><input type="radio" id="id_language_0" value="P" name="language" /> Python</label></li> -<li><label><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li> -</ul></p> - -MultipleChoiceField is a special case, as its data is required to be a list: ->>> class SongForm(Form): -... name = CharField() -... composers = MultipleChoiceField() ->>> f = SongForm(auto_id=False) ->>> print f['composers'] -<select multiple="multiple" name="composers"> -</select> ->>> class SongForm(Form): -... name = CharField() -... composers = MultipleChoiceField(choices=[('J', 'John Lennon'), ('P', 'Paul McCartney')]) ->>> f = SongForm(auto_id=False) ->>> print f['composers'] -<select multiple="multiple" name="composers"> -<option value="J">John Lennon</option> -<option value="P">Paul McCartney</option> -</select> ->>> f = SongForm({'name': 'Yesterday', 'composers': ['P']}, auto_id=False) ->>> print f['name'] -<input type="text" name="name" value="Yesterday" /> ->>> print f['composers'] -<select multiple="multiple" name="composers"> -<option value="J">John Lennon</option> -<option value="P" selected="selected">Paul McCartney</option> -</select> - -MultipleChoiceField rendered as_hidden() is a special case. Because it can -have multiple values, its as_hidden() renders multiple <input type="hidden"> -tags. ->>> f = SongForm({'name': 'Yesterday', 'composers': ['P']}, auto_id=False) ->>> print f['composers'].as_hidden() -<input type="hidden" name="composers" value="P" /> ->>> f = SongForm({'name': 'From Me To You', 'composers': ['P', 'J']}, auto_id=False) ->>> print f['composers'].as_hidden() -<input type="hidden" name="composers" value="P" /> -<input type="hidden" name="composers" value="J" /> - -MultipleChoiceField can also be used with the CheckboxSelectMultiple widget. ->>> class SongForm(Form): -... name = CharField() -... composers = MultipleChoiceField(choices=[('J', 'John Lennon'), ('P', 'Paul McCartney')], widget=CheckboxSelectMultiple) ->>> f = SongForm(auto_id=False) ->>> print f['composers'] -<ul> -<li><label><input type="checkbox" name="composers" value="J" /> John Lennon</label></li> -<li><label><input type="checkbox" name="composers" value="P" /> Paul McCartney</label></li> -</ul> ->>> f = SongForm({'composers': ['J']}, auto_id=False) ->>> print f['composers'] -<ul> -<li><label><input checked="checked" type="checkbox" name="composers" value="J" /> John Lennon</label></li> -<li><label><input type="checkbox" name="composers" value="P" /> Paul McCartney</label></li> -</ul> ->>> f = SongForm({'composers': ['J', 'P']}, auto_id=False) ->>> print f['composers'] -<ul> -<li><label><input checked="checked" type="checkbox" name="composers" value="J" /> John Lennon</label></li> -<li><label><input checked="checked" type="checkbox" name="composers" value="P" /> Paul McCartney</label></li> -</ul> - -Regarding auto_id, CheckboxSelectMultiple is a special case. Each checkbox -gets a distinct ID, formed by appending an underscore plus the checkbox's -zero-based index. ->>> f = SongForm(auto_id='%s_id') ->>> print f['composers'] -<ul> -<li><label><input type="checkbox" name="composers" value="J" id="composers_id_0" /> John Lennon</label></li> -<li><label><input type="checkbox" name="composers" value="P" id="composers_id_1" /> Paul McCartney</label></li> -</ul> - -Data for a MultipleChoiceField should be a list. QueryDict and MultiValueDict -conveniently work with this. ->>> data = {'name': 'Yesterday', 'composers': ['J', 'P']} ->>> f = SongForm(data) ->>> f.errors -{} ->>> from django.http import QueryDict ->>> data = QueryDict('name=Yesterday&composers=J&composers=P') ->>> f = SongForm(data) ->>> f.errors -{} ->>> from django.utils.datastructures import MultiValueDict ->>> data = MultiValueDict(dict(name=['Yesterday'], composers=['J', 'P'])) ->>> f = SongForm(data) ->>> f.errors -{} - -The MultipleHiddenInput widget renders multiple values as hidden fields. ->>> class SongFormHidden(Form): -... name = CharField() -... composers = MultipleChoiceField(choices=[('J', 'John Lennon'), ('P', 'Paul McCartney')], widget=MultipleHiddenInput) ->>> f = SongFormHidden(MultiValueDict(dict(name=['Yesterday'], composers=['J', 'P'])), auto_id=False) ->>> print f.as_ul() -<li>Name: <input type="text" name="name" value="Yesterday" /><input type="hidden" name="composers" value="J" /> -<input type="hidden" name="composers" value="P" /></li> - -When using CheckboxSelectMultiple, the framework expects a list of input and -returns a list of input. ->>> f = SongForm({'name': 'Yesterday'}, auto_id=False) ->>> f.errors -{'composers': [u'This field is required.']} ->>> f = SongForm({'name': 'Yesterday', 'composers': ['J']}, auto_id=False) ->>> f.errors -{} ->>> f.cleaned_data -{'composers': [u'J'], 'name': u'Yesterday'} ->>> f = SongForm({'name': 'Yesterday', 'composers': ['J', 'P']}, auto_id=False) ->>> f.errors -{} ->>> f.cleaned_data -{'composers': [u'J', u'P'], 'name': u'Yesterday'} - -Validation errors are HTML-escaped when output as HTML. ->>> class EscapingForm(Form): -... special_name = CharField() -... def clean_special_name(self): -... raise ValidationError("Something's wrong with '%s'" % self.cleaned_data['special_name']) - ->>> f = EscapingForm({'special_name': "Nothing to escape"}, auto_id=False) ->>> print f -<tr><th>Special name:</th><td><ul class="errorlist"><li>Something's wrong with 'Nothing to escape'</li></ul><input type="text" name="special_name" value="Nothing to escape" /></td></tr> ->>> f = EscapingForm({'special_name': "Should escape < & > and <script>alert('xss')</script>"}, auto_id=False) ->>> print f -<tr><th>Special name:</th><td><ul class="errorlist"><li>Something's wrong with 'Should escape < & > and <script>alert('xss')</script>'</li></ul><input type="text" name="special_name" value="Should escape < & > and <script>alert('xss')</script>" /></td></tr> - -# Validating multiple fields in relation to another ########################### - -There are a couple of ways to do multiple-field validation. If you want the -validation message to be associated with a particular field, implement the -clean_XXX() method on the Form, where XXX is the field name. As in -Field.clean(), the clean_XXX() method should return the cleaned value. In the -clean_XXX() method, you have access to self.cleaned_data, which is a dictionary -of all the data that has been cleaned *so far*, in order by the fields, -including the current field (e.g., the field XXX if you're in clean_XXX()). ->>> class UserRegistration(Form): -... username = CharField(max_length=10) -... password1 = CharField(widget=PasswordInput) -... password2 = CharField(widget=PasswordInput) -... def clean_password2(self): -... if self.cleaned_data.get('password1') and self.cleaned_data.get('password2') and self.cleaned_data['password1'] != self.cleaned_data['password2']: -... raise ValidationError(u'Please make sure your passwords match.') -... return self.cleaned_data['password2'] ->>> f = UserRegistration(auto_id=False) ->>> f.errors -{} ->>> f = UserRegistration({}, auto_id=False) ->>> f.errors -{'username': [u'This field is required.'], 'password1': [u'This field is required.'], 'password2': [u'This field is required.']} ->>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'bar'}, auto_id=False) ->>> f.errors -{'password2': [u'Please make sure your passwords match.']} ->>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'foo'}, auto_id=False) ->>> f.errors -{} ->>> f.cleaned_data -{'username': u'adrian', 'password1': u'foo', 'password2': u'foo'} - -Another way of doing multiple-field validation is by implementing the -Form's clean() method. If you do this, any ValidationError raised by that -method will not be associated with a particular field; it will have a -special-case association with the field named '__all__'. -Note that in Form.clean(), you have access to self.cleaned_data, a dictionary of -all the fields/values that have *not* raised a ValidationError. Also note -Form.clean() is required to return a dictionary of all clean data. ->>> class UserRegistration(Form): -... username = CharField(max_length=10) -... password1 = CharField(widget=PasswordInput) -... password2 = CharField(widget=PasswordInput) -... def clean(self): -... if self.cleaned_data.get('password1') and self.cleaned_data.get('password2') and self.cleaned_data['password1'] != self.cleaned_data['password2']: -... raise ValidationError(u'Please make sure your passwords match.') -... return self.cleaned_data ->>> f = UserRegistration(auto_id=False) ->>> f.errors -{} ->>> f = UserRegistration({}, auto_id=False) ->>> print f.as_table() -<tr><th>Username:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="username" maxlength="10" /></td></tr> -<tr><th>Password1:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="password" name="password1" /></td></tr> -<tr><th>Password2:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="password" name="password2" /></td></tr> ->>> f.errors -{'username': [u'This field is required.'], 'password1': [u'This field is required.'], 'password2': [u'This field is required.']} ->>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'bar'}, auto_id=False) ->>> f.errors -{'__all__': [u'Please make sure your passwords match.']} ->>> print f.as_table() -<tr><td colspan="2"><ul class="errorlist"><li>Please make sure your passwords match.</li></ul></td></tr> -<tr><th>Username:</th><td><input type="text" name="username" value="adrian" maxlength="10" /></td></tr> -<tr><th>Password1:</th><td><input type="password" name="password1" value="foo" /></td></tr> -<tr><th>Password2:</th><td><input type="password" name="password2" value="bar" /></td></tr> ->>> print f.as_ul() -<li><ul class="errorlist"><li>Please make sure your passwords match.</li></ul></li> -<li>Username: <input type="text" name="username" value="adrian" maxlength="10" /></li> -<li>Password1: <input type="password" name="password1" value="foo" /></li> -<li>Password2: <input type="password" name="password2" value="bar" /></li> ->>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'foo'}, auto_id=False) ->>> f.errors -{} ->>> f.cleaned_data -{'username': u'adrian', 'password1': u'foo', 'password2': u'foo'} - -# Dynamic construction ######################################################## - -It's possible to construct a Form dynamically by adding to the self.fields -dictionary in __init__(). Don't forget to call Form.__init__() within the -subclass' __init__(). ->>> class Person(Form): -... first_name = CharField() -... last_name = CharField() -... def __init__(self, *args, **kwargs): -... super(Person, self).__init__(*args, **kwargs) -... self.fields['birthday'] = DateField() ->>> p = Person(auto_id=False) ->>> print p -<tr><th>First name:</th><td><input type="text" name="first_name" /></td></tr> -<tr><th>Last name:</th><td><input type="text" name="last_name" /></td></tr> -<tr><th>Birthday:</th><td><input type="text" name="birthday" /></td></tr> - -Instances of a dynamic Form do not persist fields from one Form instance to -the next. ->>> class MyForm(Form): -... def __init__(self, data=None, auto_id=False, field_list=[]): -... Form.__init__(self, data, auto_id=auto_id) -... for field in field_list: -... self.fields[field[0]] = field[1] ->>> field_list = [('field1', CharField()), ('field2', CharField())] ->>> my_form = MyForm(field_list=field_list) ->>> print my_form -<tr><th>Field1:</th><td><input type="text" name="field1" /></td></tr> -<tr><th>Field2:</th><td><input type="text" name="field2" /></td></tr> ->>> field_list = [('field3', CharField()), ('field4', CharField())] ->>> my_form = MyForm(field_list=field_list) ->>> print my_form -<tr><th>Field3:</th><td><input type="text" name="field3" /></td></tr> -<tr><th>Field4:</th><td><input type="text" name="field4" /></td></tr> - ->>> class MyForm(Form): -... default_field_1 = CharField() -... default_field_2 = CharField() -... def __init__(self, data=None, auto_id=False, field_list=[]): -... Form.__init__(self, data, auto_id=auto_id) -... for field in field_list: -... self.fields[field[0]] = field[1] ->>> field_list = [('field1', CharField()), ('field2', CharField())] ->>> my_form = MyForm(field_list=field_list) ->>> print my_form -<tr><th>Default field 1:</th><td><input type="text" name="default_field_1" /></td></tr> -<tr><th>Default field 2:</th><td><input type="text" name="default_field_2" /></td></tr> -<tr><th>Field1:</th><td><input type="text" name="field1" /></td></tr> -<tr><th>Field2:</th><td><input type="text" name="field2" /></td></tr> ->>> field_list = [('field3', CharField()), ('field4', CharField())] ->>> my_form = MyForm(field_list=field_list) ->>> print my_form -<tr><th>Default field 1:</th><td><input type="text" name="default_field_1" /></td></tr> -<tr><th>Default field 2:</th><td><input type="text" name="default_field_2" /></td></tr> -<tr><th>Field3:</th><td><input type="text" name="field3" /></td></tr> -<tr><th>Field4:</th><td><input type="text" name="field4" /></td></tr> - -Similarly, changes to field attributes do not persist from one Form instance -to the next. ->>> class Person(Form): -... first_name = CharField(required=False) -... last_name = CharField(required=False) -... def __init__(self, names_required=False, *args, **kwargs): -... super(Person, self).__init__(*args, **kwargs) -... if names_required: -... self.fields['first_name'].required = True -... self.fields['last_name'].required = True ->>> f = Person(names_required=False) ->>> f['first_name'].field.required, f['last_name'].field.required -(False, False) ->>> f = Person(names_required=True) ->>> f['first_name'].field.required, f['last_name'].field.required -(True, True) ->>> f = Person(names_required=False) ->>> f['first_name'].field.required, f['last_name'].field.required -(False, False) ->>> class Person(Form): -... first_name = CharField(max_length=30) -... last_name = CharField(max_length=30) -... def __init__(self, name_max_length=None, *args, **kwargs): -... super(Person, self).__init__(*args, **kwargs) -... if name_max_length: -... self.fields['first_name'].max_length = name_max_length -... self.fields['last_name'].max_length = name_max_length ->>> f = Person(name_max_length=None) ->>> f['first_name'].field.max_length, f['last_name'].field.max_length -(30, 30) ->>> f = Person(name_max_length=20) ->>> f['first_name'].field.max_length, f['last_name'].field.max_length -(20, 20) ->>> f = Person(name_max_length=None) ->>> f['first_name'].field.max_length, f['last_name'].field.max_length -(30, 30) - -HiddenInput widgets are displayed differently in the as_table(), as_ul() -and as_p() output of a Form -- their verbose names are not displayed, and a -separate row is not displayed. They're displayed in the last row of the -form, directly after that row's form element. ->>> class Person(Form): -... first_name = CharField() -... last_name = CharField() -... hidden_text = CharField(widget=HiddenInput) -... birthday = DateField() ->>> p = Person(auto_id=False) ->>> print p -<tr><th>First name:</th><td><input type="text" name="first_name" /></td></tr> -<tr><th>Last name:</th><td><input type="text" name="last_name" /></td></tr> -<tr><th>Birthday:</th><td><input type="text" name="birthday" /><input type="hidden" name="hidden_text" /></td></tr> ->>> print p.as_ul() -<li>First name: <input type="text" name="first_name" /></li> -<li>Last name: <input type="text" name="last_name" /></li> -<li>Birthday: <input type="text" name="birthday" /><input type="hidden" name="hidden_text" /></li> ->>> print p.as_p() -<p>First name: <input type="text" name="first_name" /></p> -<p>Last name: <input type="text" name="last_name" /></p> -<p>Birthday: <input type="text" name="birthday" /><input type="hidden" name="hidden_text" /></p> - -With auto_id set, a HiddenInput still gets an ID, but it doesn't get a label. ->>> p = Person(auto_id='id_%s') ->>> print p -<tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" id="id_first_name" /></td></tr> -<tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" id="id_last_name" /></td></tr> -<tr><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" id="id_birthday" /><input type="hidden" name="hidden_text" id="id_hidden_text" /></td></tr> ->>> print p.as_ul() -<li><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></li> -<li><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></li> -<li><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /><input type="hidden" name="hidden_text" id="id_hidden_text" /></li> ->>> print p.as_p() -<p><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></p> -<p><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></p> -<p><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /><input type="hidden" name="hidden_text" id="id_hidden_text" /></p> - -If a field with a HiddenInput has errors, the as_table() and as_ul() output -will include the error message(s) with the text "(Hidden field [fieldname]) " -prepended. This message is displayed at the top of the output, regardless of -its field's order in the form. ->>> p = Person({'first_name': 'John', 'last_name': 'Lennon', 'birthday': '1940-10-9'}, auto_id=False) ->>> print p -<tr><td colspan="2"><ul class="errorlist"><li>(Hidden field hidden_text) This field is required.</li></ul></td></tr> -<tr><th>First name:</th><td><input type="text" name="first_name" value="John" /></td></tr> -<tr><th>Last name:</th><td><input type="text" name="last_name" value="Lennon" /></td></tr> -<tr><th>Birthday:</th><td><input type="text" name="birthday" value="1940-10-9" /><input type="hidden" name="hidden_text" /></td></tr> ->>> print p.as_ul() -<li><ul class="errorlist"><li>(Hidden field hidden_text) This field is required.</li></ul></li> -<li>First name: <input type="text" name="first_name" value="John" /></li> -<li>Last name: <input type="text" name="last_name" value="Lennon" /></li> -<li>Birthday: <input type="text" name="birthday" value="1940-10-9" /><input type="hidden" name="hidden_text" /></li> ->>> print p.as_p() -<ul class="errorlist"><li>(Hidden field hidden_text) This field is required.</li></ul> -<p>First name: <input type="text" name="first_name" value="John" /></p> -<p>Last name: <input type="text" name="last_name" value="Lennon" /></p> -<p>Birthday: <input type="text" name="birthday" value="1940-10-9" /><input type="hidden" name="hidden_text" /></p> - -A corner case: It's possible for a form to have only HiddenInputs. ->>> class TestForm(Form): -... foo = CharField(widget=HiddenInput) -... bar = CharField(widget=HiddenInput) ->>> p = TestForm(auto_id=False) ->>> print p.as_table() -<input type="hidden" name="foo" /><input type="hidden" name="bar" /> ->>> print p.as_ul() -<input type="hidden" name="foo" /><input type="hidden" name="bar" /> ->>> print p.as_p() -<input type="hidden" name="foo" /><input type="hidden" name="bar" /> - -A Form's fields are displayed in the same order in which they were defined. ->>> class TestForm(Form): -... field1 = CharField() -... field2 = CharField() -... field3 = CharField() -... field4 = CharField() -... field5 = CharField() -... field6 = CharField() -... field7 = CharField() -... field8 = CharField() -... field9 = CharField() -... field10 = CharField() -... field11 = CharField() -... field12 = CharField() -... field13 = CharField() -... field14 = CharField() ->>> p = TestForm(auto_id=False) ->>> print p -<tr><th>Field1:</th><td><input type="text" name="field1" /></td></tr> -<tr><th>Field2:</th><td><input type="text" name="field2" /></td></tr> -<tr><th>Field3:</th><td><input type="text" name="field3" /></td></tr> -<tr><th>Field4:</th><td><input type="text" name="field4" /></td></tr> -<tr><th>Field5:</th><td><input type="text" name="field5" /></td></tr> -<tr><th>Field6:</th><td><input type="text" name="field6" /></td></tr> -<tr><th>Field7:</th><td><input type="text" name="field7" /></td></tr> -<tr><th>Field8:</th><td><input type="text" name="field8" /></td></tr> -<tr><th>Field9:</th><td><input type="text" name="field9" /></td></tr> -<tr><th>Field10:</th><td><input type="text" name="field10" /></td></tr> -<tr><th>Field11:</th><td><input type="text" name="field11" /></td></tr> -<tr><th>Field12:</th><td><input type="text" name="field12" /></td></tr> -<tr><th>Field13:</th><td><input type="text" name="field13" /></td></tr> -<tr><th>Field14:</th><td><input type="text" name="field14" /></td></tr> - -Some Field classes have an effect on the HTML attributes of their associated -Widget. If you set max_length in a CharField and its associated widget is -either a TextInput or PasswordInput, then the widget's rendered HTML will -include the "maxlength" attribute. ->>> class UserRegistration(Form): -... username = CharField(max_length=10) # uses TextInput by default -... password = CharField(max_length=10, widget=PasswordInput) -... realname = CharField(max_length=10, widget=TextInput) # redundantly define widget, just to test -... address = CharField() # no max_length defined here ->>> p = UserRegistration(auto_id=False) ->>> print p.as_ul() -<li>Username: <input type="text" name="username" maxlength="10" /></li> -<li>Password: <input type="password" name="password" maxlength="10" /></li> -<li>Realname: <input type="text" name="realname" maxlength="10" /></li> -<li>Address: <input type="text" name="address" /></li> - -If you specify a custom "attrs" that includes the "maxlength" attribute, -the Field's max_length attribute will override whatever "maxlength" you specify -in "attrs". ->>> class UserRegistration(Form): -... username = CharField(max_length=10, widget=TextInput(attrs={'maxlength': 20})) -... password = CharField(max_length=10, widget=PasswordInput) ->>> p = UserRegistration(auto_id=False) ->>> print p.as_ul() -<li>Username: <input type="text" name="username" maxlength="10" /></li> -<li>Password: <input type="password" name="password" maxlength="10" /></li> - -# Specifying labels ########################################################### - -You can specify the label for a field by using the 'label' argument to a Field -class. If you don't specify 'label', Django will use the field name with -underscores converted to spaces, and the initial letter capitalized. ->>> class UserRegistration(Form): -... username = CharField(max_length=10, label='Your username') -... password1 = CharField(widget=PasswordInput) -... password2 = CharField(widget=PasswordInput, label='Password (again)') ->>> p = UserRegistration(auto_id=False) ->>> print p.as_ul() -<li>Your username: <input type="text" name="username" maxlength="10" /></li> -<li>Password1: <input type="password" name="password1" /></li> -<li>Password (again): <input type="password" name="password2" /></li> - -Labels for as_* methods will only end in a colon if they don't end in other -punctuation already. ->>> class Questions(Form): -... q1 = CharField(label='The first question') -... q2 = CharField(label='What is your name?') -... q3 = CharField(label='The answer to life is:') -... q4 = CharField(label='Answer this question!') -... q5 = CharField(label='The last question. Period.') ->>> print Questions(auto_id=False).as_p() -<p>The first question: <input type="text" name="q1" /></p> -<p>What is your name? <input type="text" name="q2" /></p> -<p>The answer to life is: <input type="text" name="q3" /></p> -<p>Answer this question! <input type="text" name="q4" /></p> -<p>The last question. Period. <input type="text" name="q5" /></p> ->>> print Questions().as_p() -<p><label for="id_q1">The first question:</label> <input type="text" name="q1" id="id_q1" /></p> -<p><label for="id_q2">What is your name?</label> <input type="text" name="q2" id="id_q2" /></p> -<p><label for="id_q3">The answer to life is:</label> <input type="text" name="q3" id="id_q3" /></p> -<p><label for="id_q4">Answer this question!</label> <input type="text" name="q4" id="id_q4" /></p> -<p><label for="id_q5">The last question. Period.</label> <input type="text" name="q5" id="id_q5" /></p> - -A label can be a Unicode object or a bytestring with special characters. ->>> class UserRegistration(Form): -... username = CharField(max_length=10, label='ŠĐĆŽćžšđ') -... password = CharField(widget=PasswordInput, label=u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111') ->>> p = UserRegistration(auto_id=False) ->>> p.as_ul() -u'<li>\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111: <input type="text" name="username" maxlength="10" /></li>\n<li>\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111: <input type="password" name="password" /></li>' - -If a label is set to the empty string for a field, that field won't get a label. ->>> class UserRegistration(Form): -... username = CharField(max_length=10, label='') -... password = CharField(widget=PasswordInput) ->>> p = UserRegistration(auto_id=False) ->>> print p.as_ul() -<li> <input type="text" name="username" maxlength="10" /></li> -<li>Password: <input type="password" name="password" /></li> ->>> p = UserRegistration(auto_id='id_%s') ->>> print p.as_ul() -<li> <input id="id_username" type="text" name="username" maxlength="10" /></li> -<li><label for="id_password">Password:</label> <input type="password" name="password" id="id_password" /></li> - -If label is None, Django will auto-create the label from the field name. This -is default behavior. ->>> class UserRegistration(Form): -... username = CharField(max_length=10, label=None) -... password = CharField(widget=PasswordInput) ->>> p = UserRegistration(auto_id=False) ->>> print p.as_ul() -<li>Username: <input type="text" name="username" maxlength="10" /></li> -<li>Password: <input type="password" name="password" /></li> ->>> p = UserRegistration(auto_id='id_%s') ->>> print p.as_ul() -<li><label for="id_username">Username:</label> <input id="id_username" type="text" name="username" maxlength="10" /></li> -<li><label for="id_password">Password:</label> <input type="password" name="password" id="id_password" /></li> - -# Initial data ################################################################ - -You can specify initial data for a field by using the 'initial' argument to a -Field class. This initial data is displayed when a Form is rendered with *no* -data. It is not displayed when a Form is rendered with any data (including an -empty dictionary). Also, the initial value is *not* used if data for a -particular required field isn't provided. ->>> class UserRegistration(Form): -... username = CharField(max_length=10, initial='django') -... password = CharField(widget=PasswordInput) - -Here, we're not submitting any data, so the initial value will be displayed. ->>> p = UserRegistration(auto_id=False) ->>> print p.as_ul() -<li>Username: <input type="text" name="username" value="django" maxlength="10" /></li> -<li>Password: <input type="password" name="password" /></li> - -Here, we're submitting data, so the initial value will *not* be displayed. ->>> p = UserRegistration({}, auto_id=False) ->>> print p.as_ul() -<li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li> -<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li> ->>> p = UserRegistration({'username': u''}, auto_id=False) ->>> print p.as_ul() -<li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li> -<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li> ->>> p = UserRegistration({'username': u'foo'}, auto_id=False) ->>> print p.as_ul() -<li>Username: <input type="text" name="username" value="foo" maxlength="10" /></li> -<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li> - -An 'initial' value is *not* used as a fallback if data is not provided. In this -example, we don't provide a value for 'username', and the form raises a -validation error rather than using the initial value for 'username'. ->>> p = UserRegistration({'password': 'secret'}) ->>> p.errors -{'username': [u'This field is required.']} ->>> p.is_valid() -False - -# Dynamic initial data ######################################################## - -The previous technique dealt with "hard-coded" initial data, but it's also -possible to specify initial data after you've already created the Form class -(i.e., at runtime). Use the 'initial' parameter to the Form constructor. This -should be a dictionary containing initial values for one or more fields in the -form, keyed by field name. - ->>> class UserRegistration(Form): -... username = CharField(max_length=10) -... password = CharField(widget=PasswordInput) - -Here, we're not submitting any data, so the initial value will be displayed. ->>> p = UserRegistration(initial={'username': 'django'}, auto_id=False) ->>> print p.as_ul() -<li>Username: <input type="text" name="username" value="django" maxlength="10" /></li> -<li>Password: <input type="password" name="password" /></li> ->>> p = UserRegistration(initial={'username': 'stephane'}, auto_id=False) ->>> print p.as_ul() -<li>Username: <input type="text" name="username" value="stephane" maxlength="10" /></li> -<li>Password: <input type="password" name="password" /></li> - -The 'initial' parameter is meaningless if you pass data. ->>> p = UserRegistration({}, initial={'username': 'django'}, auto_id=False) ->>> print p.as_ul() -<li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li> -<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li> ->>> p = UserRegistration({'username': u''}, initial={'username': 'django'}, auto_id=False) ->>> print p.as_ul() -<li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li> -<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li> ->>> p = UserRegistration({'username': u'foo'}, initial={'username': 'django'}, auto_id=False) ->>> print p.as_ul() -<li>Username: <input type="text" name="username" value="foo" maxlength="10" /></li> -<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li> - -A dynamic 'initial' value is *not* used as a fallback if data is not provided. -In this example, we don't provide a value for 'username', and the form raises a -validation error rather than using the initial value for 'username'. ->>> p = UserRegistration({'password': 'secret'}, initial={'username': 'django'}) ->>> p.errors -{'username': [u'This field is required.']} ->>> p.is_valid() -False - -If a Form defines 'initial' *and* 'initial' is passed as a parameter to Form(), -then the latter will get precedence. ->>> class UserRegistration(Form): -... username = CharField(max_length=10, initial='django') -... password = CharField(widget=PasswordInput) ->>> p = UserRegistration(initial={'username': 'babik'}, auto_id=False) ->>> print p.as_ul() -<li>Username: <input type="text" name="username" value="babik" maxlength="10" /></li> -<li>Password: <input type="password" name="password" /></li> - -# Callable initial data ######################################################## - -The previous technique dealt with raw values as initial data, but it's also -possible to specify callable data. - ->>> class UserRegistration(Form): -... username = CharField(max_length=10) -... password = CharField(widget=PasswordInput) - -We need to define functions that get called later. ->>> def initial_django(): -... return 'django' ->>> def initial_stephane(): -... return 'stephane' - -Here, we're not submitting any data, so the initial value will be displayed. ->>> p = UserRegistration(initial={'username': initial_django}, auto_id=False) ->>> print p.as_ul() -<li>Username: <input type="text" name="username" value="django" maxlength="10" /></li> -<li>Password: <input type="password" name="password" /></li> - -The 'initial' parameter is meaningless if you pass data. ->>> p = UserRegistration({}, initial={'username': initial_django}, auto_id=False) ->>> print p.as_ul() -<li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li> -<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li> ->>> p = UserRegistration({'username': u''}, initial={'username': initial_django}, auto_id=False) ->>> print p.as_ul() -<li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li> -<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li> ->>> p = UserRegistration({'username': u'foo'}, initial={'username': initial_django}, auto_id=False) ->>> print p.as_ul() -<li>Username: <input type="text" name="username" value="foo" maxlength="10" /></li> -<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li> - -A callable 'initial' value is *not* used as a fallback if data is not provided. -In this example, we don't provide a value for 'username', and the form raises a -validation error rather than using the initial value for 'username'. ->>> p = UserRegistration({'password': 'secret'}, initial={'username': initial_django}) ->>> p.errors -{'username': [u'This field is required.']} ->>> p.is_valid() -False - -If a Form defines 'initial' *and* 'initial' is passed as a parameter to Form(), -then the latter will get precedence. ->>> class UserRegistration(Form): -... username = CharField(max_length=10, initial=initial_django) -... password = CharField(widget=PasswordInput) ->>> p = UserRegistration(auto_id=False) ->>> print p.as_ul() -<li>Username: <input type="text" name="username" value="django" maxlength="10" /></li> -<li>Password: <input type="password" name="password" /></li> ->>> p = UserRegistration(initial={'username': initial_stephane}, auto_id=False) ->>> print p.as_ul() -<li>Username: <input type="text" name="username" value="stephane" maxlength="10" /></li> -<li>Password: <input type="password" name="password" /></li> - -# Help text ################################################################### - -You can specify descriptive text for a field by using the 'help_text' argument -to a Field class. This help text is displayed when a Form is rendered. ->>> class UserRegistration(Form): -... username = CharField(max_length=10, help_text='e.g., user@example.com') -... password = CharField(widget=PasswordInput, help_text='Choose wisely.') ->>> p = UserRegistration(auto_id=False) ->>> print p.as_ul() -<li>Username: <input type="text" name="username" maxlength="10" /> e.g., user@example.com</li> -<li>Password: <input type="password" name="password" /> Choose wisely.</li> ->>> print p.as_p() -<p>Username: <input type="text" name="username" maxlength="10" /> e.g., user@example.com</p> -<p>Password: <input type="password" name="password" /> Choose wisely.</p> ->>> print p.as_table() -<tr><th>Username:</th><td><input type="text" name="username" maxlength="10" /><br />e.g., user@example.com</td></tr> -<tr><th>Password:</th><td><input type="password" name="password" /><br />Choose wisely.</td></tr> - -The help text is displayed whether or not data is provided for the form. ->>> p = UserRegistration({'username': u'foo'}, auto_id=False) ->>> print p.as_ul() -<li>Username: <input type="text" name="username" value="foo" maxlength="10" /> e.g., user@example.com</li> -<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /> Choose wisely.</li> - -help_text is not displayed for hidden fields. It can be used for documentation -purposes, though. ->>> class UserRegistration(Form): -... username = CharField(max_length=10, help_text='e.g., user@example.com') -... password = CharField(widget=PasswordInput) -... next = CharField(widget=HiddenInput, initial='/', help_text='Redirect destination') ->>> p = UserRegistration(auto_id=False) ->>> print p.as_ul() -<li>Username: <input type="text" name="username" maxlength="10" /> e.g., user@example.com</li> -<li>Password: <input type="password" name="password" /><input type="hidden" name="next" value="/" /></li> - -Help text can include arbitrary Unicode characters. ->>> class UserRegistration(Form): -... username = CharField(max_length=10, help_text='ŠĐĆŽćžšđ') ->>> p = UserRegistration(auto_id=False) ->>> p.as_ul() -u'<li>Username: <input type="text" name="username" maxlength="10" /> \u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111</li>' - -# Subclassing forms ########################################################### - -You can subclass a Form to add fields. The resulting form subclass will have -all of the fields of the parent Form, plus whichever fields you define in the -subclass. ->>> class Person(Form): -... first_name = CharField() -... last_name = CharField() -... birthday = DateField() ->>> class Musician(Person): -... instrument = CharField() ->>> p = Person(auto_id=False) ->>> print p.as_ul() -<li>First name: <input type="text" name="first_name" /></li> -<li>Last name: <input type="text" name="last_name" /></li> -<li>Birthday: <input type="text" name="birthday" /></li> ->>> m = Musician(auto_id=False) ->>> print m.as_ul() -<li>First name: <input type="text" name="first_name" /></li> -<li>Last name: <input type="text" name="last_name" /></li> -<li>Birthday: <input type="text" name="birthday" /></li> -<li>Instrument: <input type="text" name="instrument" /></li> - -Yes, you can subclass multiple forms. The fields are added in the order in -which the parent classes are listed. ->>> class Person(Form): -... first_name = CharField() -... last_name = CharField() -... birthday = DateField() ->>> class Instrument(Form): -... instrument = CharField() ->>> class Beatle(Person, Instrument): -... haircut_type = CharField() ->>> b = Beatle(auto_id=False) ->>> print b.as_ul() -<li>First name: <input type="text" name="first_name" /></li> -<li>Last name: <input type="text" name="last_name" /></li> -<li>Birthday: <input type="text" name="birthday" /></li> -<li>Instrument: <input type="text" name="instrument" /></li> -<li>Haircut type: <input type="text" name="haircut_type" /></li> - -# Forms with prefixes ######################################################### - -Sometimes it's necessary to have multiple forms display on the same HTML page, -or multiple copies of the same form. We can accomplish this with form prefixes. -Pass the keyword argument 'prefix' to the Form constructor to use this feature. -This value will be prepended to each HTML form field name. One way to think -about this is "namespaces for HTML forms". Notice that in the data argument, -each field's key has the prefix, in this case 'person1', prepended to the -actual field name. ->>> class Person(Form): -... first_name = CharField() -... last_name = CharField() -... birthday = DateField() ->>> data = { -... 'person1-first_name': u'John', -... 'person1-last_name': u'Lennon', -... 'person1-birthday': u'1940-10-9' -... } ->>> p = Person(data, prefix='person1') ->>> print p.as_ul() -<li><label for="id_person1-first_name">First name:</label> <input type="text" name="person1-first_name" value="John" id="id_person1-first_name" /></li> -<li><label for="id_person1-last_name">Last name:</label> <input type="text" name="person1-last_name" value="Lennon" id="id_person1-last_name" /></li> -<li><label for="id_person1-birthday">Birthday:</label> <input type="text" name="person1-birthday" value="1940-10-9" id="id_person1-birthday" /></li> ->>> print p['first_name'] -<input type="text" name="person1-first_name" value="John" id="id_person1-first_name" /> ->>> print p['last_name'] -<input type="text" name="person1-last_name" value="Lennon" id="id_person1-last_name" /> ->>> print p['birthday'] -<input type="text" name="person1-birthday" value="1940-10-9" id="id_person1-birthday" /> ->>> p.errors -{} ->>> p.is_valid() -True ->>> p.cleaned_data -{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)} - -Let's try submitting some bad data to make sure form.errors and field.errors -work as expected. ->>> data = { -... 'person1-first_name': u'', -... 'person1-last_name': u'', -... 'person1-birthday': u'' -... } ->>> p = Person(data, prefix='person1') ->>> p.errors -{'first_name': [u'This field is required.'], 'last_name': [u'This field is required.'], 'birthday': [u'This field is required.']} ->>> p['first_name'].errors -[u'This field is required.'] ->>> p['person1-first_name'].errors -Traceback (most recent call last): -... -KeyError: "Key 'person1-first_name' not found in Form" - -In this example, the data doesn't have a prefix, but the form requires it, so -the form doesn't "see" the fields. ->>> data = { -... 'first_name': u'John', -... 'last_name': u'Lennon', -... 'birthday': u'1940-10-9' -... } ->>> p = Person(data, prefix='person1') ->>> p.errors -{'first_name': [u'This field is required.'], 'last_name': [u'This field is required.'], 'birthday': [u'This field is required.']} - -With prefixes, a single data dictionary can hold data for multiple instances -of the same form. ->>> data = { -... 'person1-first_name': u'John', -... 'person1-last_name': u'Lennon', -... 'person1-birthday': u'1940-10-9', -... 'person2-first_name': u'Jim', -... 'person2-last_name': u'Morrison', -... 'person2-birthday': u'1943-12-8' -... } ->>> p1 = Person(data, prefix='person1') ->>> p1.is_valid() -True ->>> p1.cleaned_data -{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)} ->>> p2 = Person(data, prefix='person2') ->>> p2.is_valid() -True ->>> p2.cleaned_data -{'first_name': u'Jim', 'last_name': u'Morrison', 'birthday': datetime.date(1943, 12, 8)} - -By default, forms append a hyphen between the prefix and the field name, but a -form can alter that behavior by implementing the add_prefix() method. This -method takes a field name and returns the prefixed field, according to -self.prefix. ->>> class Person(Form): -... first_name = CharField() -... last_name = CharField() -... birthday = DateField() -... def add_prefix(self, field_name): -... return self.prefix and '%s-prefix-%s' % (self.prefix, field_name) or field_name ->>> p = Person(prefix='foo') ->>> print p.as_ul() -<li><label for="id_foo-prefix-first_name">First name:</label> <input type="text" name="foo-prefix-first_name" id="id_foo-prefix-first_name" /></li> -<li><label for="id_foo-prefix-last_name">Last name:</label> <input type="text" name="foo-prefix-last_name" id="id_foo-prefix-last_name" /></li> -<li><label for="id_foo-prefix-birthday">Birthday:</label> <input type="text" name="foo-prefix-birthday" id="id_foo-prefix-birthday" /></li> ->>> data = { -... 'foo-prefix-first_name': u'John', -... 'foo-prefix-last_name': u'Lennon', -... 'foo-prefix-birthday': u'1940-10-9' -... } ->>> p = Person(data, prefix='foo') ->>> p.is_valid() -True ->>> p.cleaned_data -{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)} - -# Forms with NullBooleanFields ################################################ - -NullBooleanField is a bit of a special case because its presentation (widget) -is different than its data. This is handled transparently, though. - ->>> class Person(Form): -... name = CharField() -... is_cool = NullBooleanField() ->>> p = Person({'name': u'Joe'}, auto_id=False) ->>> print p['is_cool'] -<select name="is_cool"> -<option value="1" selected="selected">Unknown</option> -<option value="2">Yes</option> -<option value="3">No</option> -</select> ->>> p = Person({'name': u'Joe', 'is_cool': u'1'}, auto_id=False) ->>> print p['is_cool'] -<select name="is_cool"> -<option value="1" selected="selected">Unknown</option> -<option value="2">Yes</option> -<option value="3">No</option> -</select> ->>> p = Person({'name': u'Joe', 'is_cool': u'2'}, auto_id=False) ->>> print p['is_cool'] -<select name="is_cool"> -<option value="1">Unknown</option> -<option value="2" selected="selected">Yes</option> -<option value="3">No</option> -</select> ->>> p = Person({'name': u'Joe', 'is_cool': u'3'}, auto_id=False) ->>> print p['is_cool'] -<select name="is_cool"> -<option value="1">Unknown</option> -<option value="2">Yes</option> -<option value="3" selected="selected">No</option> -</select> ->>> p = Person({'name': u'Joe', 'is_cool': True}, auto_id=False) ->>> print p['is_cool'] -<select name="is_cool"> -<option value="1">Unknown</option> -<option value="2" selected="selected">Yes</option> -<option value="3">No</option> -</select> ->>> p = Person({'name': u'Joe', 'is_cool': False}, auto_id=False) ->>> print p['is_cool'] -<select name="is_cool"> -<option value="1">Unknown</option> -<option value="2">Yes</option> -<option value="3" selected="selected">No</option> -</select> - -# Forms with FileFields ################################################ - -FileFields are a special case because they take their data from the request.FILES, -not request.POST. - ->>> class FileForm(Form): -... file1 = FileField() ->>> f = FileForm(auto_id=False) ->>> print f -<tr><th>File1:</th><td><input type="file" name="file1" /></td></tr> - ->>> f = FileForm(data={}, files={}, auto_id=False) ->>> print f -<tr><th>File1:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="file" name="file1" /></td></tr> - ->>> f = FileForm(data={}, files={'file1': {'filename': 'name', 'content':''}}, auto_id=False) ->>> print f -<tr><th>File1:</th><td><ul class="errorlist"><li>The submitted file is empty.</li></ul><input type="file" name="file1" /></td></tr> - ->>> f = FileForm(data={}, files={'file1': 'something that is not a file'}, auto_id=False) ->>> print f -<tr><th>File1:</th><td><ul class="errorlist"><li>No file was submitted. Check the encoding type on the form.</li></ul><input type="file" name="file1" /></td></tr> - ->>> f = FileForm(data={}, files={'file1': {'filename': 'name', 'content':'some content'}}, auto_id=False) ->>> print f -<tr><th>File1:</th><td><input type="file" name="file1" /></td></tr> ->>> f.is_valid() -True - -# Basic form processing in a view ############################################# - ->>> from django.template import Template, Context ->>> class UserRegistration(Form): -... username = CharField(max_length=10) -... password1 = CharField(widget=PasswordInput) -... password2 = CharField(widget=PasswordInput) -... def clean(self): -... if self.cleaned_data.get('password1') and self.cleaned_data.get('password2') and self.cleaned_data['password1'] != self.cleaned_data['password2']: -... raise ValidationError(u'Please make sure your passwords match.') -... return self.cleaned_data ->>> def my_function(method, post_data): -... if method == 'POST': -... form = UserRegistration(post_data, auto_id=False) -... else: -... form = UserRegistration(auto_id=False) -... if form.is_valid(): -... return 'VALID: %r' % form.cleaned_data -... t = Template('<form action="" method="post">\n<table>\n{{ form }}\n</table>\n<input type="submit" />\n</form>') -... return t.render(Context({'form': form})) - -Case 1: GET (an empty form, with no errors). ->>> print my_function('GET', {}) -<form action="" method="post"> -<table> -<tr><th>Username:</th><td><input type="text" name="username" maxlength="10" /></td></tr> -<tr><th>Password1:</th><td><input type="password" name="password1" /></td></tr> -<tr><th>Password2:</th><td><input type="password" name="password2" /></td></tr> -</table> -<input type="submit" /> -</form> - -Case 2: POST with erroneous data (a redisplayed form, with errors). ->>> print my_function('POST', {'username': 'this-is-a-long-username', 'password1': 'foo', 'password2': 'bar'}) -<form action="" method="post"> -<table> -<tr><td colspan="2"><ul class="errorlist"><li>Please make sure your passwords match.</li></ul></td></tr> -<tr><th>Username:</th><td><ul class="errorlist"><li>Ensure this value has at most 10 characters (it has 23).</li></ul><input type="text" name="username" value="this-is-a-long-username" maxlength="10" /></td></tr> -<tr><th>Password1:</th><td><input type="password" name="password1" value="foo" /></td></tr> -<tr><th>Password2:</th><td><input type="password" name="password2" value="bar" /></td></tr> -</table> -<input type="submit" /> -</form> - -Case 3: POST with valid data (the success message). ->>> print my_function('POST', {'username': 'adrian', 'password1': 'secret', 'password2': 'secret'}) -VALID: {'username': u'adrian', 'password1': u'secret', 'password2': u'secret'} - -# Some ideas for using templates with forms ################################### - ->>> class UserRegistration(Form): -... username = CharField(max_length=10, help_text="Good luck picking a username that doesn't already exist.") -... password1 = CharField(widget=PasswordInput) -... password2 = CharField(widget=PasswordInput) -... def clean(self): -... if self.cleaned_data.get('password1') and self.cleaned_data.get('password2') and self.cleaned_data['password1'] != self.cleaned_data['password2']: -... raise ValidationError(u'Please make sure your passwords match.') -... return self.cleaned_data - -You have full flexibility in displaying form fields in a template. Just pass a -Form instance to the template, and use "dot" access to refer to individual -fields. Note, however, that this flexibility comes with the responsibility of -displaying all the errors, including any that might not be associated with a -particular field. ->>> t = Template('''<form action=""> -... {{ form.username.errors.as_ul }}<p><label>Your username: {{ form.username }}</label></p> -... {{ form.password1.errors.as_ul }}<p><label>Password: {{ form.password1 }}</label></p> -... {{ form.password2.errors.as_ul }}<p><label>Password (again): {{ form.password2 }}</label></p> -... <input type="submit" /> -... </form>''') ->>> print t.render(Context({'form': UserRegistration(auto_id=False)})) -<form action=""> -<p><label>Your username: <input type="text" name="username" maxlength="10" /></label></p> -<p><label>Password: <input type="password" name="password1" /></label></p> -<p><label>Password (again): <input type="password" name="password2" /></label></p> -<input type="submit" /> -</form> ->>> print t.render(Context({'form': UserRegistration({'username': 'django'}, auto_id=False)})) -<form action=""> -<p><label>Your username: <input type="text" name="username" value="django" maxlength="10" /></label></p> -<ul class="errorlist"><li>This field is required.</li></ul><p><label>Password: <input type="password" name="password1" /></label></p> -<ul class="errorlist"><li>This field is required.</li></ul><p><label>Password (again): <input type="password" name="password2" /></label></p> -<input type="submit" /> -</form> - -Use form.[field].label to output a field's label. You can specify the label for -a field by using the 'label' argument to a Field class. If you don't specify -'label', Django will use the field name with underscores converted to spaces, -and the initial letter capitalized. ->>> t = Template('''<form action=""> -... <p><label>{{ form.username.label }}: {{ form.username }}</label></p> -... <p><label>{{ form.password1.label }}: {{ form.password1 }}</label></p> -... <p><label>{{ form.password2.label }}: {{ form.password2 }}</label></p> -... <input type="submit" /> -... </form>''') ->>> print t.render(Context({'form': UserRegistration(auto_id=False)})) -<form action=""> -<p><label>Username: <input type="text" name="username" maxlength="10" /></label></p> -<p><label>Password1: <input type="password" name="password1" /></label></p> -<p><label>Password2: <input type="password" name="password2" /></label></p> -<input type="submit" /> -</form> - -User form.[field].label_tag to output a field's label with a <label> tag -wrapped around it, but *only* if the given field has an "id" attribute. -Recall from above that passing the "auto_id" argument to a Form gives each -field an "id" attribute. ->>> t = Template('''<form action=""> -... <p>{{ form.username.label_tag }}: {{ form.username }}</p> -... <p>{{ form.password1.label_tag }}: {{ form.password1 }}</p> -... <p>{{ form.password2.label_tag }}: {{ form.password2 }}</p> -... <input type="submit" /> -... </form>''') ->>> print t.render(Context({'form': UserRegistration(auto_id=False)})) -<form action=""> -<p>Username: <input type="text" name="username" maxlength="10" /></p> -<p>Password1: <input type="password" name="password1" /></p> -<p>Password2: <input type="password" name="password2" /></p> -<input type="submit" /> -</form> ->>> print t.render(Context({'form': UserRegistration(auto_id='id_%s')})) -<form action=""> -<p><label for="id_username">Username</label>: <input id="id_username" type="text" name="username" maxlength="10" /></p> -<p><label for="id_password1">Password1</label>: <input type="password" name="password1" id="id_password1" /></p> -<p><label for="id_password2">Password2</label>: <input type="password" name="password2" id="id_password2" /></p> -<input type="submit" /> -</form> - -User form.[field].help_text to output a field's help text. If the given field -does not have help text, nothing will be output. ->>> t = Template('''<form action=""> -... <p>{{ form.username.label_tag }}: {{ form.username }}<br />{{ form.username.help_text }}</p> -... <p>{{ form.password1.label_tag }}: {{ form.password1 }}</p> -... <p>{{ form.password2.label_tag }}: {{ form.password2 }}</p> -... <input type="submit" /> -... </form>''') ->>> print t.render(Context({'form': UserRegistration(auto_id=False)})) -<form action=""> -<p>Username: <input type="text" name="username" maxlength="10" /><br />Good luck picking a username that doesn't already exist.</p> -<p>Password1: <input type="password" name="password1" /></p> -<p>Password2: <input type="password" name="password2" /></p> -<input type="submit" /> -</form> ->>> Template('{{ form.password1.help_text }}').render(Context({'form': UserRegistration(auto_id=False)})) -u'' - -The label_tag() method takes an optional attrs argument: a dictionary of HTML -attributes to add to the <label> tag. ->>> f = UserRegistration(auto_id='id_%s') ->>> for bf in f: -... print bf.label_tag(attrs={'class': 'pretty'}) -<label for="id_username" class="pretty">Username</label> -<label for="id_password1" class="pretty">Password1</label> -<label for="id_password2" class="pretty">Password2</label> - -To display the errors that aren't associated with a particular field -- e.g., -the errors caused by Form.clean() -- use {{ form.non_field_errors }} in the -template. If used on its own, it is displayed as a <ul> (or an empty string, if -the list of errors is empty). You can also use it in {% if %} statements. ->>> t = Template('''<form action=""> -... {{ form.username.errors.as_ul }}<p><label>Your username: {{ form.username }}</label></p> -... {{ form.password1.errors.as_ul }}<p><label>Password: {{ form.password1 }}</label></p> -... {{ form.password2.errors.as_ul }}<p><label>Password (again): {{ form.password2 }}</label></p> -... <input type="submit" /> -... </form>''') ->>> print t.render(Context({'form': UserRegistration({'username': 'django', 'password1': 'foo', 'password2': 'bar'}, auto_id=False)})) -<form action=""> -<p><label>Your username: <input type="text" name="username" value="django" maxlength="10" /></label></p> -<p><label>Password: <input type="password" name="password1" value="foo" /></label></p> -<p><label>Password (again): <input type="password" name="password2" value="bar" /></label></p> -<input type="submit" /> -</form> ->>> t = Template('''<form action=""> -... {{ form.non_field_errors }} -... {{ form.username.errors.as_ul }}<p><label>Your username: {{ form.username }}</label></p> -... {{ form.password1.errors.as_ul }}<p><label>Password: {{ form.password1 }}</label></p> -... {{ form.password2.errors.as_ul }}<p><label>Password (again): {{ form.password2 }}</label></p> -... <input type="submit" /> -... </form>''') ->>> print t.render(Context({'form': UserRegistration({'username': 'django', 'password1': 'foo', 'password2': 'bar'}, auto_id=False)})) -<form action=""> -<ul class="errorlist"><li>Please make sure your passwords match.</li></ul> -<p><label>Your username: <input type="text" name="username" value="django" maxlength="10" /></label></p> -<p><label>Password: <input type="password" name="password1" value="foo" /></label></p> -<p><label>Password (again): <input type="password" name="password2" value="bar" /></label></p> -<input type="submit" /> -</form> - -############### -# Extra stuff # -############### - -The newforms library comes with some extra, higher-level Field and Widget -classes that demonstrate some of the library's abilities. - -# SelectDateWidget ############################################################ - ->>> from django.newforms.extras import SelectDateWidget ->>> w = SelectDateWidget(years=('2007','2008','2009','2010','2011','2012','2013','2014','2015','2016')) ->>> print w.render('mydate', '') -<select name="mydate_month"> -<option value="1">January</option> -<option value="2">February</option> -<option value="3">March</option> -<option value="4">April</option> -<option value="5">May</option> -<option value="6">June</option> -<option value="7">July</option> -<option value="8">August</option> -<option value="9">September</option> -<option value="10">October</option> -<option value="11">November</option> -<option value="12">December</option> -</select> -<select name="mydate_day"> -<option value="1">1</option> -<option value="2">2</option> -<option value="3">3</option> -<option value="4">4</option> -<option value="5">5</option> -<option value="6">6</option> -<option value="7">7</option> -<option value="8">8</option> -<option value="9">9</option> -<option value="10">10</option> -<option value="11">11</option> -<option value="12">12</option> -<option value="13">13</option> -<option value="14">14</option> -<option value="15">15</option> -<option value="16">16</option> -<option value="17">17</option> -<option value="18">18</option> -<option value="19">19</option> -<option value="20">20</option> -<option value="21">21</option> -<option value="22">22</option> -<option value="23">23</option> -<option value="24">24</option> -<option value="25">25</option> -<option value="26">26</option> -<option value="27">27</option> -<option value="28">28</option> -<option value="29">29</option> -<option value="30">30</option> -<option value="31">31</option> -</select> -<select name="mydate_year"> -<option value="2007">2007</option> -<option value="2008">2008</option> -<option value="2009">2009</option> -<option value="2010">2010</option> -<option value="2011">2011</option> -<option value="2012">2012</option> -<option value="2013">2013</option> -<option value="2014">2014</option> -<option value="2015">2015</option> -<option value="2016">2016</option> -</select> ->>> w.render('mydate', None) == w.render('mydate', '') -True ->>> print w.render('mydate', '2010-04-15') -<select name="mydate_month"> -<option value="1">January</option> -<option value="2">February</option> -<option value="3">March</option> -<option value="4" selected="selected">April</option> -<option value="5">May</option> -<option value="6">June</option> -<option value="7">July</option> -<option value="8">August</option> -<option value="9">September</option> -<option value="10">October</option> -<option value="11">November</option> -<option value="12">December</option> -</select> -<select name="mydate_day"> -<option value="1">1</option> -<option value="2">2</option> -<option value="3">3</option> -<option value="4">4</option> -<option value="5">5</option> -<option value="6">6</option> -<option value="7">7</option> -<option value="8">8</option> -<option value="9">9</option> -<option value="10">10</option> -<option value="11">11</option> -<option value="12">12</option> -<option value="13">13</option> -<option value="14">14</option> -<option value="15" selected="selected">15</option> -<option value="16">16</option> -<option value="17">17</option> -<option value="18">18</option> -<option value="19">19</option> -<option value="20">20</option> -<option value="21">21</option> -<option value="22">22</option> -<option value="23">23</option> -<option value="24">24</option> -<option value="25">25</option> -<option value="26">26</option> -<option value="27">27</option> -<option value="28">28</option> -<option value="29">29</option> -<option value="30">30</option> -<option value="31">31</option> -</select> -<select name="mydate_year"> -<option value="2007">2007</option> -<option value="2008">2008</option> -<option value="2009">2009</option> -<option value="2010" selected="selected">2010</option> -<option value="2011">2011</option> -<option value="2012">2012</option> -<option value="2013">2013</option> -<option value="2014">2014</option> -<option value="2015">2015</option> -<option value="2016">2016</option> -</select> - -Using a SelectDateWidget in a form: - ->>> class GetDate(Form): -... mydate = DateField(widget=SelectDateWidget) ->>> a = GetDate({'mydate_month':'4', 'mydate_day':'1', 'mydate_year':'2008'}) ->>> print a.is_valid() -True ->>> print a.cleaned_data['mydate'] -2008-04-01 - -As with any widget that implements get_value_from_datadict, -we must be prepared to accept the input from the "as_hidden" -rendering as well. - ->>> print a['mydate'].as_hidden() -<input type="hidden" name="mydate" value="2008-4-1" id="id_mydate" /> ->>> b=GetDate({'mydate':'2008-4-1'}) ->>> print b.is_valid() -True ->>> print b.cleaned_data['mydate'] -2008-04-01 - - -# MultiWidget and MultiValueField ############################################# -# MultiWidgets are widgets composed of other widgets. They are usually -# combined with MultiValueFields - a field that is composed of other fields. -# MulitWidgets can themselved be composed of other MultiWidgets. -# SplitDateTimeWidget is one example of a MultiWidget. - ->>> class ComplexMultiWidget(MultiWidget): -... def __init__(self, attrs=None): -... widgets = ( -... TextInput(), -... SelectMultiple(choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))), -... SplitDateTimeWidget(), -... ) -... super(ComplexMultiWidget, self).__init__(widgets, attrs) -... -... def decompress(self, value): -... if value: -... data = value.split(',') -... return [data[0], data[1], datetime.datetime(*time.strptime(data[2], "%Y-%m-%d %H:%M:%S")[0:6])] -... return [None, None, None] -... def format_output(self, rendered_widgets): -... return u'\n'.join(rendered_widgets) ->>> w = ComplexMultiWidget() ->>> print w.render('name', 'some text,JP,2007-04-25 06:24:00') -<input type="text" name="name_0" value="some text" /> -<select multiple="multiple" name="name_1"> -<option value="J" selected="selected">John</option> -<option value="P" selected="selected">Paul</option> -<option value="G">George</option> -<option value="R">Ringo</option> -</select> -<input type="text" name="name_2_0" value="2007-04-25" /><input type="text" name="name_2_1" value="06:24:00" /> - ->>> class ComplexField(MultiValueField): -... def __init__(self, required=True, widget=None, label=None, initial=None): -... fields = ( -... CharField(), -... MultipleChoiceField(choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))), -... SplitDateTimeField() -... ) -... super(ComplexField, self).__init__(fields, required, widget, label, initial) -... -... def compress(self, data_list): -... if data_list: -... return '%s,%s,%s' % (data_list[0],''.join(data_list[1]),data_list[2]) -... return None - ->>> f = ComplexField(widget=w) ->>> f.clean(['some text', ['J','P'], ['2007-04-25','6:24:00']]) -u'some text,JP,2007-04-25 06:24:00' ->>> f.clean(['some text',['X'], ['2007-04-25','6:24:00']]) -Traceback (most recent call last): -... -ValidationError: [u'Select a valid choice. X is not one of the available choices.'] - -# If insufficient data is provided, None is substituted ->>> f.clean(['some text',['JP']]) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] - ->>> class ComplexFieldForm(Form): -... field1 = ComplexField(widget=w) ->>> f = ComplexFieldForm() ->>> print f -<tr><th><label for="id_field1_0">Field1:</label></th><td><input type="text" name="field1_0" id="id_field1_0" /> -<select multiple="multiple" name="field1_1" id="id_field1_1"> -<option value="J">John</option> -<option value="P">Paul</option> -<option value="G">George</option> -<option value="R">Ringo</option> -</select> -<input type="text" name="field1_2_0" id="id_field1_2_0" /><input type="text" name="field1_2_1" id="id_field1_2_1" /></td></tr> - ->>> f = ComplexFieldForm({'field1_0':'some text','field1_1':['J','P'], 'field1_2_0':'2007-04-25', 'field1_2_1':'06:24:00'}) ->>> print f -<tr><th><label for="id_field1_0">Field1:</label></th><td><input type="text" name="field1_0" value="some text" id="id_field1_0" /> -<select multiple="multiple" name="field1_1" id="id_field1_1"> -<option value="J" selected="selected">John</option> -<option value="P" selected="selected">Paul</option> -<option value="G">George</option> -<option value="R">Ringo</option> -</select> -<input type="text" name="field1_2_0" value="2007-04-25" id="id_field1_2_0" /><input type="text" name="field1_2_1" value="06:24:00" id="id_field1_2_1" /></td></tr> - ->>> f.cleaned_data -{'field1': u'some text,JP,2007-04-25 06:24:00'} - -################################# -# Tests of underlying functions # -################################# - -# smart_unicode tests ->>> from django.utils.encoding import smart_unicode ->>> class Test: -... def __str__(self): -... return 'ŠĐĆŽćžšđ' ->>> class TestU: -... def __str__(self): -... return 'Foo' -... def __unicode__(self): -... return u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111' ->>> smart_unicode(Test()) -u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111' ->>> smart_unicode(TestU()) -u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111' ->>> smart_unicode(1) -u'1' ->>> smart_unicode('foo') -u'foo' - -# flatatt tests ->>> from django.newforms.util import flatatt ->>> flatatt({'id': "header"}) -u' id="header"' ->>> flatatt({'class': "news", 'title': "Read this"}) -u' class="news" title="Read this"' ->>> flatatt({}) -u'' - -#################################### -# Test accessing errors in clean() # -#################################### - ->>> class UserForm(Form): -... username = CharField(max_length=10) -... password = CharField(widget=PasswordInput) -... def clean(self): -... data = self.cleaned_data -... if not self.errors: -... data['username'] = data['username'].lower() -... return data - ->>> f = UserForm({'username': 'SirRobin', 'password': 'blue'}) ->>> f.is_valid() -True ->>> f.cleaned_data['username'] -u'sirrobin' -""" +from extra import tests as extra_tests +from fields import tests as fields_tests +from forms import tests as form_tests +from localflavor.ar import tests as localflavor_ar_tests +from localflavor.au import tests as localflavor_au_tests +from localflavor.br import tests as localflavor_br_tests +from localflavor.ca import tests as localflavor_ca_tests +from localflavor.ch import tests as localflavor_ch_tests +from localflavor.cl import tests as localflavor_cl_tests +from localflavor.de import tests as localflavor_de_tests +from localflavor.fi import tests as localflavor_fi_tests +from localflavor.fr import tests as localflavor_fr_tests +from localflavor.generic import tests as localflavor_generic_tests +from localflavor.is_ import tests as localflavor_is_tests +from localflavor.it import tests as localflavor_it_tests +from localflavor.jp import tests as localflavor_jp_tests +from localflavor.nl import tests as localflavor_nl_tests +from localflavor.pl import tests as localflavor_pl_tests +from localflavor.sk import tests as localflavor_sk_tests +from localflavor.uk import tests as localflavor_uk_tests +from localflavor.us import tests as localflavor_us_tests +from regressions import tests as regression_tests +from util import tests as util_tests +from widgets import tests as widgets_tests __test__ = { + 'extra_tests': extra_tests, + 'fields_tests': fields_tests, 'form_tests': form_tests, - 'localflavor': localflavor_tests, - 'regressions': regression_tests, + 'localflavor_ar_tests': localflavor_ar_tests, + 'localflavor_au_tests': localflavor_au_tests, + 'localflavor_br_tests': localflavor_br_tests, + 'localflavor_ca_tests': localflavor_ca_tests, + 'localflavor_ch_tests': localflavor_ch_tests, + 'localflavor_cl_tests': localflavor_cl_tests, + 'localflavor_de_tests': localflavor_de_tests, + 'localflavor_fi_tests': localflavor_fi_tests, + 'localflavor_fr_tests': localflavor_fr_tests, + 'localflavor_generic_tests': localflavor_generic_tests, + 'localflavor_is_tests': localflavor_is_tests, + 'localflavor_it_tests': localflavor_it_tests, + 'localflavor_jp_tests': localflavor_jp_tests, + 'localflavor_nl_tests': localflavor_nl_tests, + 'localflavor_pl_tests': localflavor_pl_tests, + 'localflavor_sk_tests': localflavor_sk_tests, + 'localflavor_uk_tests': localflavor_uk_tests, + 'localflavor_us_tests': localflavor_us_tests, + 'regressions_tests': regression_tests, + 'util_tests': util_tests, + 'widgets_tests': widgets_tests, } if __name__ == "__main__": diff --git a/tests/regressiontests/forms/util.py b/tests/regressiontests/forms/util.py new file mode 100644 index 0000000000..4f81709082 --- /dev/null +++ b/tests/regressiontests/forms/util.py @@ -0,0 +1,45 @@ +# coding: utf-8 +""" +Tests for newforms/util.py module. +""" + +tests = r""" +>>> from django.newforms.util import * +>>> from django.utils.translation import ugettext_lazy + +########### +# flatatt # +########### + +>>> from django.newforms.util import flatatt +>>> flatatt({'id': "header"}) +u' id="header"' +>>> flatatt({'class': "news", 'title': "Read this"}) +u' class="news" title="Read this"' +>>> flatatt({}) +u'' + +################### +# ValidationError # +################### + +# Can take a string. +>>> print ValidationError("There was an error.").messages +<ul class="errorlist"><li>There was an error.</li></ul> + +# Can take a unicode string. +>>> print ValidationError(u"Not \u03C0.").messages +<ul class="errorlist"><li>Not π.</li></ul> + +# Can take a lazy string. +>>> print ValidationError(ugettext_lazy("Error.")).messages +<ul class="errorlist"><li>Error.</li></ul> + +# Can take a list. +>>> print ValidationError(["Error one.", "Error two."]).messages +<ul class="errorlist"><li>Error one.</li><li>Error two.</li></ul> + +# Can take a mixture in a list. +>>> print ValidationError(["First error.", u"Not \u03C0.", ugettext_lazy("Error.")]).messages +<ul class="errorlist"><li>First error.</li><li>Not π.</li><li>Error.</li></ul> +""" diff --git a/tests/regressiontests/forms/widgets.py b/tests/regressiontests/forms/widgets.py new file mode 100644 index 0000000000..1c3e873963 --- /dev/null +++ b/tests/regressiontests/forms/widgets.py @@ -0,0 +1,848 @@ +# -*- coding: utf-8 -*- +tests = r""" +>>> from django.newforms import * +>>> from django.newforms.widgets import RadioFieldRenderer +>>> import datetime +>>> import time +>>> import re +>>> try: +... from decimal import Decimal +... except ImportError: +... from django.utils._decimal import Decimal + +########### +# Widgets # +########### + +Each Widget class corresponds to an HTML form widget. A Widget knows how to +render itself, given a field name and some data. Widgets don't perform +validation. + +# TextInput Widget ############################################################ + +>>> w = TextInput() +>>> w.render('email', '') +u'<input type="text" name="email" />' +>>> w.render('email', None) +u'<input type="text" name="email" />' +>>> w.render('email', 'test@example.com') +u'<input type="text" name="email" value="test@example.com" />' +>>> w.render('email', 'some "quoted" & ampersanded value') +u'<input type="text" name="email" value="some "quoted" & ampersanded value" />' +>>> w.render('email', 'test@example.com', attrs={'class': 'fun'}) +u'<input type="text" name="email" value="test@example.com" class="fun" />' + +# Note that doctest in Python 2.4 (and maybe 2.5?) doesn't support non-ascii +# characters in output, so we're displaying the repr() here. +>>> w.render('email', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'}) +u'<input type="text" name="email" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" class="fun" />' + +You can also pass 'attrs' to the constructor: +>>> w = TextInput(attrs={'class': 'fun'}) +>>> w.render('email', '') +u'<input type="text" class="fun" name="email" />' +>>> w.render('email', 'foo@example.com') +u'<input type="text" class="fun" value="foo@example.com" name="email" />' + +'attrs' passed to render() get precedence over those passed to the constructor: +>>> w = TextInput(attrs={'class': 'pretty'}) +>>> w.render('email', '', attrs={'class': 'special'}) +u'<input type="text" class="special" name="email" />' + +# PasswordInput Widget ############################################################ + +>>> w = PasswordInput() +>>> w.render('email', '') +u'<input type="password" name="email" />' +>>> w.render('email', None) +u'<input type="password" name="email" />' +>>> w.render('email', 'test@example.com') +u'<input type="password" name="email" value="test@example.com" />' +>>> w.render('email', 'some "quoted" & ampersanded value') +u'<input type="password" name="email" value="some "quoted" & ampersanded value" />' +>>> w.render('email', 'test@example.com', attrs={'class': 'fun'}) +u'<input type="password" name="email" value="test@example.com" class="fun" />' + +You can also pass 'attrs' to the constructor: +>>> w = PasswordInput(attrs={'class': 'fun'}) +>>> w.render('email', '') +u'<input type="password" class="fun" name="email" />' +>>> w.render('email', 'foo@example.com') +u'<input type="password" class="fun" value="foo@example.com" name="email" />' + +'attrs' passed to render() get precedence over those passed to the constructor: +>>> w = PasswordInput(attrs={'class': 'pretty'}) +>>> w.render('email', '', attrs={'class': 'special'}) +u'<input type="password" class="special" name="email" />' + +>>> w.render('email', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'}) +u'<input type="password" class="fun" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" name="email" />' + +The render_value argument lets you specify whether the widget should render +its value. You may want to do this for security reasons. +>>> w = PasswordInput(render_value=True) +>>> w.render('email', 'secret') +u'<input type="password" name="email" value="secret" />' +>>> w = PasswordInput(render_value=False) +>>> w.render('email', '') +u'<input type="password" name="email" />' +>>> w.render('email', None) +u'<input type="password" name="email" />' +>>> w.render('email', 'secret') +u'<input type="password" name="email" />' +>>> w = PasswordInput(attrs={'class': 'fun'}, render_value=False) +>>> w.render('email', 'secret') +u'<input type="password" class="fun" name="email" />' + +# HiddenInput Widget ############################################################ + +>>> w = HiddenInput() +>>> w.render('email', '') +u'<input type="hidden" name="email" />' +>>> w.render('email', None) +u'<input type="hidden" name="email" />' +>>> w.render('email', 'test@example.com') +u'<input type="hidden" name="email" value="test@example.com" />' +>>> w.render('email', 'some "quoted" & ampersanded value') +u'<input type="hidden" name="email" value="some "quoted" & ampersanded value" />' +>>> w.render('email', 'test@example.com', attrs={'class': 'fun'}) +u'<input type="hidden" name="email" value="test@example.com" class="fun" />' + +You can also pass 'attrs' to the constructor: +>>> w = HiddenInput(attrs={'class': 'fun'}) +>>> w.render('email', '') +u'<input type="hidden" class="fun" name="email" />' +>>> w.render('email', 'foo@example.com') +u'<input type="hidden" class="fun" value="foo@example.com" name="email" />' + +'attrs' passed to render() get precedence over those passed to the constructor: +>>> w = HiddenInput(attrs={'class': 'pretty'}) +>>> w.render('email', '', attrs={'class': 'special'}) +u'<input type="hidden" class="special" name="email" />' + +>>> w.render('email', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'}) +u'<input type="hidden" class="fun" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" name="email" />' + +'attrs' passed to render() get precedence over those passed to the constructor: +>>> w = HiddenInput(attrs={'class': 'pretty'}) +>>> w.render('email', '', attrs={'class': 'special'}) +u'<input type="hidden" class="special" name="email" />' + +# MultipleHiddenInput Widget ################################################## + +>>> w = MultipleHiddenInput() +>>> w.render('email', []) +u'' +>>> w.render('email', None) +u'' +>>> w.render('email', ['test@example.com']) +u'<input type="hidden" name="email" value="test@example.com" />' +>>> w.render('email', ['some "quoted" & ampersanded value']) +u'<input type="hidden" name="email" value="some "quoted" & ampersanded value" />' +>>> w.render('email', ['test@example.com', 'foo@example.com']) +u'<input type="hidden" name="email" value="test@example.com" />\n<input type="hidden" name="email" value="foo@example.com" />' +>>> w.render('email', ['test@example.com'], attrs={'class': 'fun'}) +u'<input type="hidden" name="email" value="test@example.com" class="fun" />' +>>> w.render('email', ['test@example.com', 'foo@example.com'], attrs={'class': 'fun'}) +u'<input type="hidden" name="email" value="test@example.com" class="fun" />\n<input type="hidden" name="email" value="foo@example.com" class="fun" />' + +You can also pass 'attrs' to the constructor: +>>> w = MultipleHiddenInput(attrs={'class': 'fun'}) +>>> w.render('email', []) +u'' +>>> w.render('email', ['foo@example.com']) +u'<input type="hidden" class="fun" value="foo@example.com" name="email" />' +>>> w.render('email', ['foo@example.com', 'test@example.com']) +u'<input type="hidden" class="fun" value="foo@example.com" name="email" />\n<input type="hidden" class="fun" value="test@example.com" name="email" />' + +'attrs' passed to render() get precedence over those passed to the constructor: +>>> w = MultipleHiddenInput(attrs={'class': 'pretty'}) +>>> w.render('email', ['foo@example.com'], attrs={'class': 'special'}) +u'<input type="hidden" class="special" value="foo@example.com" name="email" />' + +>>> w.render('email', ['ŠĐĆŽćžšđ'], attrs={'class': 'fun'}) +u'<input type="hidden" class="fun" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" name="email" />' + +'attrs' passed to render() get precedence over those passed to the constructor: +>>> w = MultipleHiddenInput(attrs={'class': 'pretty'}) +>>> w.render('email', ['foo@example.com'], attrs={'class': 'special'}) +u'<input type="hidden" class="special" value="foo@example.com" name="email" />' + +# FileInput Widget ############################################################ + +FileInput widgets don't ever show the value, because the old value is of no use +if you are updating the form or if the provided file generated an error. +>>> w = FileInput() +>>> w.render('email', '') +u'<input type="file" name="email" />' +>>> w.render('email', None) +u'<input type="file" name="email" />' +>>> w.render('email', 'test@example.com') +u'<input type="file" name="email" />' +>>> w.render('email', 'some "quoted" & ampersanded value') +u'<input type="file" name="email" />' +>>> w.render('email', 'test@example.com', attrs={'class': 'fun'}) +u'<input type="file" name="email" class="fun" />' + +You can also pass 'attrs' to the constructor: +>>> w = FileInput(attrs={'class': 'fun'}) +>>> w.render('email', '') +u'<input type="file" class="fun" name="email" />' +>>> w.render('email', 'foo@example.com') +u'<input type="file" class="fun" name="email" />' + +>>> w.render('email', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'}) +u'<input type="file" class="fun" name="email" />' + +# Textarea Widget ############################################################# + +>>> w = Textarea() +>>> w.render('msg', '') +u'<textarea rows="10" cols="40" name="msg"></textarea>' +>>> w.render('msg', None) +u'<textarea rows="10" cols="40" name="msg"></textarea>' +>>> w.render('msg', 'value') +u'<textarea rows="10" cols="40" name="msg">value</textarea>' +>>> w.render('msg', 'some "quoted" & ampersanded value') +u'<textarea rows="10" cols="40" name="msg">some "quoted" & ampersanded value</textarea>' +>>> w.render('msg', 'value', attrs={'class': 'pretty', 'rows': 20}) +u'<textarea class="pretty" rows="20" cols="40" name="msg">value</textarea>' + +You can also pass 'attrs' to the constructor: +>>> w = Textarea(attrs={'class': 'pretty'}) +>>> w.render('msg', '') +u'<textarea rows="10" cols="40" name="msg" class="pretty"></textarea>' +>>> w.render('msg', 'example') +u'<textarea rows="10" cols="40" name="msg" class="pretty">example</textarea>' + +'attrs' passed to render() get precedence over those passed to the constructor: +>>> w = Textarea(attrs={'class': 'pretty'}) +>>> w.render('msg', '', attrs={'class': 'special'}) +u'<textarea rows="10" cols="40" name="msg" class="special"></textarea>' + +>>> w.render('msg', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'}) +u'<textarea rows="10" cols="40" name="msg" class="fun">\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111</textarea>' + +# CheckboxInput Widget ######################################################## + +>>> w = CheckboxInput() +>>> w.render('is_cool', '') +u'<input type="checkbox" name="is_cool" />' +>>> w.render('is_cool', None) +u'<input type="checkbox" name="is_cool" />' +>>> w.render('is_cool', False) +u'<input type="checkbox" name="is_cool" />' +>>> w.render('is_cool', True) +u'<input checked="checked" type="checkbox" name="is_cool" />' + +Using any value that's not in ('', None, False, True) will check the checkbox +and set the 'value' attribute. +>>> w.render('is_cool', 'foo') +u'<input checked="checked" type="checkbox" name="is_cool" value="foo" />' + +>>> w.render('is_cool', False, attrs={'class': 'pretty'}) +u'<input type="checkbox" name="is_cool" class="pretty" />' + +You can also pass 'attrs' to the constructor: +>>> w = CheckboxInput(attrs={'class': 'pretty'}) +>>> w.render('is_cool', '') +u'<input type="checkbox" class="pretty" name="is_cool" />' + +'attrs' passed to render() get precedence over those passed to the constructor: +>>> w = CheckboxInput(attrs={'class': 'pretty'}) +>>> w.render('is_cool', '', attrs={'class': 'special'}) +u'<input type="checkbox" class="special" name="is_cool" />' + +You can pass 'check_test' to the constructor. This is a callable that takes the +value and returns True if the box should be checked. +>>> w = CheckboxInput(check_test=lambda value: value.startswith('hello')) +>>> w.render('greeting', '') +u'<input type="checkbox" name="greeting" />' +>>> w.render('greeting', 'hello') +u'<input checked="checked" type="checkbox" name="greeting" value="hello" />' +>>> w.render('greeting', 'hello there') +u'<input checked="checked" type="checkbox" name="greeting" value="hello there" />' +>>> w.render('greeting', 'hello & goodbye') +u'<input checked="checked" type="checkbox" name="greeting" value="hello & goodbye" />' + +A subtlety: If the 'check_test' argument cannot handle a value and raises any +exception during its __call__, then the exception will be swallowed and the box +will not be checked. In this example, the 'check_test' assumes the value has a +startswith() method, which fails for the values True, False and None. +>>> w.render('greeting', True) +u'<input type="checkbox" name="greeting" />' +>>> w.render('greeting', False) +u'<input type="checkbox" name="greeting" />' +>>> w.render('greeting', None) +u'<input type="checkbox" name="greeting" />' + +# Select Widget ############################################################### + +>>> w = Select() +>>> print w.render('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) +<select name="beatle"> +<option value="J" selected="selected">John</option> +<option value="P">Paul</option> +<option value="G">George</option> +<option value="R">Ringo</option> +</select> + +If the value is None, none of the options are selected: +>>> print w.render('beatle', None, choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) +<select name="beatle"> +<option value="J">John</option> +<option value="P">Paul</option> +<option value="G">George</option> +<option value="R">Ringo</option> +</select> + +If the value corresponds to a label (but not to an option value), none of the options are selected: +>>> print w.render('beatle', 'John', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) +<select name="beatle"> +<option value="J">John</option> +<option value="P">Paul</option> +<option value="G">George</option> +<option value="R">Ringo</option> +</select> + +The value is compared to its str(): +>>> print w.render('num', 2, choices=[('1', '1'), ('2', '2'), ('3', '3')]) +<select name="num"> +<option value="1">1</option> +<option value="2" selected="selected">2</option> +<option value="3">3</option> +</select> +>>> print w.render('num', '2', choices=[(1, 1), (2, 2), (3, 3)]) +<select name="num"> +<option value="1">1</option> +<option value="2" selected="selected">2</option> +<option value="3">3</option> +</select> +>>> print w.render('num', 2, choices=[(1, 1), (2, 2), (3, 3)]) +<select name="num"> +<option value="1">1</option> +<option value="2" selected="selected">2</option> +<option value="3">3</option> +</select> + +The 'choices' argument can be any iterable: +>>> from itertools import chain +>>> def get_choices(): +... for i in range(5): +... yield (i, i) +>>> print w.render('num', 2, choices=get_choices()) +<select name="num"> +<option value="0">0</option> +<option value="1">1</option> +<option value="2" selected="selected">2</option> +<option value="3">3</option> +<option value="4">4</option> +</select> +>>> things = ({'id': 1, 'name': 'And Boom'}, {'id': 2, 'name': 'One More Thing!'}) +>>> class SomeForm(Form): +... somechoice = ChoiceField(choices=chain((('', '-'*9),), [(thing['id'], thing['name']) for thing in things])) +>>> f = SomeForm() +>>> f.as_table() +u'<tr><th><label for="id_somechoice">Somechoice:</label></th><td><select name="somechoice" id="id_somechoice">\n<option value="" selected="selected">---------</option>\n<option value="1">And Boom</option>\n<option value="2">One More Thing!</option>\n</select></td></tr>' +>>> f.as_table() +u'<tr><th><label for="id_somechoice">Somechoice:</label></th><td><select name="somechoice" id="id_somechoice">\n<option value="" selected="selected">---------</option>\n<option value="1">And Boom</option>\n<option value="2">One More Thing!</option>\n</select></td></tr>' +>>> f = SomeForm({'somechoice': 2}) +>>> f.as_table() +u'<tr><th><label for="id_somechoice">Somechoice:</label></th><td><select name="somechoice" id="id_somechoice">\n<option value="">---------</option>\n<option value="1">And Boom</option>\n<option value="2" selected="selected">One More Thing!</option>\n</select></td></tr>' + +You can also pass 'choices' to the constructor: +>>> w = Select(choices=[(1, 1), (2, 2), (3, 3)]) +>>> print w.render('num', 2) +<select name="num"> +<option value="1">1</option> +<option value="2" selected="selected">2</option> +<option value="3">3</option> +</select> + +If 'choices' is passed to both the constructor and render(), then they'll both be in the output: +>>> print w.render('num', 2, choices=[(4, 4), (5, 5)]) +<select name="num"> +<option value="1">1</option> +<option value="2" selected="selected">2</option> +<option value="3">3</option> +<option value="4">4</option> +<option value="5">5</option> +</select> + +>>> w.render('email', 'ŠĐĆŽćžšđ', choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')]) +u'<select name="email">\n<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" selected="selected">\u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</option>\n<option value="\u0107\u017e\u0161\u0111">abc\u0107\u017e\u0161\u0111</option>\n</select>' + +If choices is passed to the constructor and is a generator, it can be iterated +over multiple times without getting consumed: +>>> w = Select(choices=get_choices()) +>>> print w.render('num', 2) +<select name="num"> +<option value="0">0</option> +<option value="1">1</option> +<option value="2" selected="selected">2</option> +<option value="3">3</option> +<option value="4">4</option> +</select> +>>> print w.render('num', 3) +<select name="num"> +<option value="0">0</option> +<option value="1">1</option> +<option value="2">2</option> +<option value="3" selected="selected">3</option> +<option value="4">4</option> +</select> + +# NullBooleanSelect Widget #################################################### + +>>> w = NullBooleanSelect() +>>> print w.render('is_cool', True) +<select name="is_cool"> +<option value="1">Unknown</option> +<option value="2" selected="selected">Yes</option> +<option value="3">No</option> +</select> +>>> print w.render('is_cool', False) +<select name="is_cool"> +<option value="1">Unknown</option> +<option value="2">Yes</option> +<option value="3" selected="selected">No</option> +</select> +>>> print w.render('is_cool', None) +<select name="is_cool"> +<option value="1" selected="selected">Unknown</option> +<option value="2">Yes</option> +<option value="3">No</option> +</select> +>>> print w.render('is_cool', '2') +<select name="is_cool"> +<option value="1">Unknown</option> +<option value="2" selected="selected">Yes</option> +<option value="3">No</option> +</select> +>>> print w.render('is_cool', '3') +<select name="is_cool"> +<option value="1">Unknown</option> +<option value="2">Yes</option> +<option value="3" selected="selected">No</option> +</select> + +""" + \ +r""" # [This concatenation is to keep the string below the jython's 32K limit]. +# SelectMultiple Widget ####################################################### + +>>> w = SelectMultiple() +>>> print w.render('beatles', ['J'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) +<select multiple="multiple" name="beatles"> +<option value="J" selected="selected">John</option> +<option value="P">Paul</option> +<option value="G">George</option> +<option value="R">Ringo</option> +</select> +>>> print w.render('beatles', ['J', 'P'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) +<select multiple="multiple" name="beatles"> +<option value="J" selected="selected">John</option> +<option value="P" selected="selected">Paul</option> +<option value="G">George</option> +<option value="R">Ringo</option> +</select> +>>> print w.render('beatles', ['J', 'P', 'R'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) +<select multiple="multiple" name="beatles"> +<option value="J" selected="selected">John</option> +<option value="P" selected="selected">Paul</option> +<option value="G">George</option> +<option value="R" selected="selected">Ringo</option> +</select> + +If the value is None, none of the options are selected: +>>> print w.render('beatles', None, choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) +<select multiple="multiple" name="beatles"> +<option value="J">John</option> +<option value="P">Paul</option> +<option value="G">George</option> +<option value="R">Ringo</option> +</select> + +If the value corresponds to a label (but not to an option value), none of the options are selected: +>>> print w.render('beatles', ['John'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) +<select multiple="multiple" name="beatles"> +<option value="J">John</option> +<option value="P">Paul</option> +<option value="G">George</option> +<option value="R">Ringo</option> +</select> + +If multiple values are given, but some of them are not valid, the valid ones are selected: +>>> print w.render('beatles', ['J', 'G', 'foo'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) +<select multiple="multiple" name="beatles"> +<option value="J" selected="selected">John</option> +<option value="P">Paul</option> +<option value="G" selected="selected">George</option> +<option value="R">Ringo</option> +</select> + +The value is compared to its str(): +>>> print w.render('nums', [2], choices=[('1', '1'), ('2', '2'), ('3', '3')]) +<select multiple="multiple" name="nums"> +<option value="1">1</option> +<option value="2" selected="selected">2</option> +<option value="3">3</option> +</select> +>>> print w.render('nums', ['2'], choices=[(1, 1), (2, 2), (3, 3)]) +<select multiple="multiple" name="nums"> +<option value="1">1</option> +<option value="2" selected="selected">2</option> +<option value="3">3</option> +</select> +>>> print w.render('nums', [2], choices=[(1, 1), (2, 2), (3, 3)]) +<select multiple="multiple" name="nums"> +<option value="1">1</option> +<option value="2" selected="selected">2</option> +<option value="3">3</option> +</select> + +The 'choices' argument can be any iterable: +>>> def get_choices(): +... for i in range(5): +... yield (i, i) +>>> print w.render('nums', [2], choices=get_choices()) +<select multiple="multiple" name="nums"> +<option value="0">0</option> +<option value="1">1</option> +<option value="2" selected="selected">2</option> +<option value="3">3</option> +<option value="4">4</option> +</select> + +You can also pass 'choices' to the constructor: +>>> w = SelectMultiple(choices=[(1, 1), (2, 2), (3, 3)]) +>>> print w.render('nums', [2]) +<select multiple="multiple" name="nums"> +<option value="1">1</option> +<option value="2" selected="selected">2</option> +<option value="3">3</option> +</select> + +If 'choices' is passed to both the constructor and render(), then they'll both be in the output: +>>> print w.render('nums', [2], choices=[(4, 4), (5, 5)]) +<select multiple="multiple" name="nums"> +<option value="1">1</option> +<option value="2" selected="selected">2</option> +<option value="3">3</option> +<option value="4">4</option> +<option value="5">5</option> +</select> + +>>> w.render('nums', ['ŠĐĆŽćžšđ'], choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')]) +u'<select multiple="multiple" name="nums">\n<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" selected="selected">\u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</option>\n<option value="\u0107\u017e\u0161\u0111">abc\u0107\u017e\u0161\u0111</option>\n</select>' + +# RadioSelect Widget ########################################################## + +>>> w = RadioSelect() +>>> print w.render('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) +<ul> +<li><label><input checked="checked" type="radio" name="beatle" value="J" /> John</label></li> +<li><label><input type="radio" name="beatle" value="P" /> Paul</label></li> +<li><label><input type="radio" name="beatle" value="G" /> George</label></li> +<li><label><input type="radio" name="beatle" value="R" /> Ringo</label></li> +</ul> + +If the value is None, none of the options are checked: +>>> print w.render('beatle', None, choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) +<ul> +<li><label><input type="radio" name="beatle" value="J" /> John</label></li> +<li><label><input type="radio" name="beatle" value="P" /> Paul</label></li> +<li><label><input type="radio" name="beatle" value="G" /> George</label></li> +<li><label><input type="radio" name="beatle" value="R" /> Ringo</label></li> +</ul> + +If the value corresponds to a label (but not to an option value), none of the options are checked: +>>> print w.render('beatle', 'John', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) +<ul> +<li><label><input type="radio" name="beatle" value="J" /> John</label></li> +<li><label><input type="radio" name="beatle" value="P" /> Paul</label></li> +<li><label><input type="radio" name="beatle" value="G" /> George</label></li> +<li><label><input type="radio" name="beatle" value="R" /> Ringo</label></li> +</ul> + +The value is compared to its str(): +>>> print w.render('num', 2, choices=[('1', '1'), ('2', '2'), ('3', '3')]) +<ul> +<li><label><input type="radio" name="num" value="1" /> 1</label></li> +<li><label><input checked="checked" type="radio" name="num" value="2" /> 2</label></li> +<li><label><input type="radio" name="num" value="3" /> 3</label></li> +</ul> +>>> print w.render('num', '2', choices=[(1, 1), (2, 2), (3, 3)]) +<ul> +<li><label><input type="radio" name="num" value="1" /> 1</label></li> +<li><label><input checked="checked" type="radio" name="num" value="2" /> 2</label></li> +<li><label><input type="radio" name="num" value="3" /> 3</label></li> +</ul> +>>> print w.render('num', 2, choices=[(1, 1), (2, 2), (3, 3)]) +<ul> +<li><label><input type="radio" name="num" value="1" /> 1</label></li> +<li><label><input checked="checked" type="radio" name="num" value="2" /> 2</label></li> +<li><label><input type="radio" name="num" value="3" /> 3</label></li> +</ul> + +The 'choices' argument can be any iterable: +>>> def get_choices(): +... for i in range(5): +... yield (i, i) +>>> print w.render('num', 2, choices=get_choices()) +<ul> +<li><label><input type="radio" name="num" value="0" /> 0</label></li> +<li><label><input type="radio" name="num" value="1" /> 1</label></li> +<li><label><input checked="checked" type="radio" name="num" value="2" /> 2</label></li> +<li><label><input type="radio" name="num" value="3" /> 3</label></li> +<li><label><input type="radio" name="num" value="4" /> 4</label></li> +</ul> + +You can also pass 'choices' to the constructor: +>>> w = RadioSelect(choices=[(1, 1), (2, 2), (3, 3)]) +>>> print w.render('num', 2) +<ul> +<li><label><input type="radio" name="num" value="1" /> 1</label></li> +<li><label><input checked="checked" type="radio" name="num" value="2" /> 2</label></li> +<li><label><input type="radio" name="num" value="3" /> 3</label></li> +</ul> + +If 'choices' is passed to both the constructor and render(), then they'll both be in the output: +>>> print w.render('num', 2, choices=[(4, 4), (5, 5)]) +<ul> +<li><label><input type="radio" name="num" value="1" /> 1</label></li> +<li><label><input checked="checked" type="radio" name="num" value="2" /> 2</label></li> +<li><label><input type="radio" name="num" value="3" /> 3</label></li> +<li><label><input type="radio" name="num" value="4" /> 4</label></li> +<li><label><input type="radio" name="num" value="5" /> 5</label></li> +</ul> + +RadioSelect uses a RadioFieldRenderer to render the individual radio inputs. +You can manipulate that object directly to customize the way the RadioSelect +is rendered. +>>> w = RadioSelect() +>>> r = w.get_renderer('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) +>>> for inp in r: +... print inp +<label><input checked="checked" type="radio" name="beatle" value="J" /> John</label> +<label><input type="radio" name="beatle" value="P" /> Paul</label> +<label><input type="radio" name="beatle" value="G" /> George</label> +<label><input type="radio" name="beatle" value="R" /> Ringo</label> +>>> for inp in r: +... print '%s<br />' % inp +<label><input checked="checked" type="radio" name="beatle" value="J" /> John</label><br /> +<label><input type="radio" name="beatle" value="P" /> Paul</label><br /> +<label><input type="radio" name="beatle" value="G" /> George</label><br /> +<label><input type="radio" name="beatle" value="R" /> Ringo</label><br /> +>>> for inp in r: +... print '<p>%s %s</p>' % (inp.tag(), inp.choice_label) +<p><input checked="checked" type="radio" name="beatle" value="J" /> John</p> +<p><input type="radio" name="beatle" value="P" /> Paul</p> +<p><input type="radio" name="beatle" value="G" /> George</p> +<p><input type="radio" name="beatle" value="R" /> Ringo</p> +>>> for inp in r: +... print '%s %s %s %s %s' % (inp.name, inp.value, inp.choice_value, inp.choice_label, inp.is_checked()) +beatle J J John True +beatle J P Paul False +beatle J G George False +beatle J R Ringo False + +You can create your own custom renderers for RadioSelect to use. +>>> class MyRenderer(RadioFieldRenderer): +... def render(self): +... return u'<br />\n'.join([unicode(choice) for choice in self]) +>>> w = RadioSelect(renderer=MyRenderer) +>>> print w.render('beatle', 'G', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) +<label><input type="radio" name="beatle" value="J" /> John</label><br /> +<label><input type="radio" name="beatle" value="P" /> Paul</label><br /> +<label><input checked="checked" type="radio" name="beatle" value="G" /> George</label><br /> +<label><input type="radio" name="beatle" value="R" /> Ringo</label> + +A RadioFieldRenderer object also allows index access to individual RadioInput +objects. +>>> w = RadioSelect() +>>> r = w.get_renderer('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) +>>> print r[1] +<label><input type="radio" name="beatle" value="P" /> Paul</label> +>>> print r[0] +<label><input checked="checked" type="radio" name="beatle" value="J" /> John</label> +>>> r[0].is_checked() +True +>>> r[1].is_checked() +False +>>> r[1].name, r[1].value, r[1].choice_value, r[1].choice_label +('beatle', u'J', u'P', u'Paul') +>>> r[10] +Traceback (most recent call last): +... +IndexError: list index out of range + +# Unicode choices are correctly rendered as HTML +>>> w = RadioSelect() +>>> unicode(w.render('email', 'ŠĐĆŽćžšđ', choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')])) +u'<ul>\n<li><label><input checked="checked" type="radio" name="email" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" /> \u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</label></li>\n<li><label><input type="radio" name="email" value="\u0107\u017e\u0161\u0111" /> abc\u0107\u017e\u0161\u0111</label></li>\n</ul>' + +# Attributes provided at instantiation are passed to the constituent inputs +>>> w = RadioSelect(attrs={'id':'foo'}) +>>> print w.render('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) +<ul> +<li><label><input checked="checked" type="radio" id="foo_0" value="J" name="beatle" /> John</label></li> +<li><label><input type="radio" id="foo_1" value="P" name="beatle" /> Paul</label></li> +<li><label><input type="radio" id="foo_2" value="G" name="beatle" /> George</label></li> +<li><label><input type="radio" id="foo_3" value="R" name="beatle" /> Ringo</label></li> +</ul> + +# Attributes provided at render-time are passed to the constituent inputs +>>> w = RadioSelect() +>>> print w.render('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')), attrs={'id':'bar'}) +<ul> +<li><label><input checked="checked" type="radio" id="bar_0" value="J" name="beatle" /> John</label></li> +<li><label><input type="radio" id="bar_1" value="P" name="beatle" /> Paul</label></li> +<li><label><input type="radio" id="bar_2" value="G" name="beatle" /> George</label></li> +<li><label><input type="radio" id="bar_3" value="R" name="beatle" /> Ringo</label></li> +</ul> + +# CheckboxSelectMultiple Widget ############################################### + +>>> w = CheckboxSelectMultiple() +>>> print w.render('beatles', ['J'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) +<ul> +<li><label><input checked="checked" type="checkbox" name="beatles" value="J" /> John</label></li> +<li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li> +<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li> +<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li> +</ul> +>>> print w.render('beatles', ['J', 'P'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) +<ul> +<li><label><input checked="checked" type="checkbox" name="beatles" value="J" /> John</label></li> +<li><label><input checked="checked" type="checkbox" name="beatles" value="P" /> Paul</label></li> +<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li> +<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li> +</ul> +>>> print w.render('beatles', ['J', 'P', 'R'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) +<ul> +<li><label><input checked="checked" type="checkbox" name="beatles" value="J" /> John</label></li> +<li><label><input checked="checked" type="checkbox" name="beatles" value="P" /> Paul</label></li> +<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li> +<li><label><input checked="checked" type="checkbox" name="beatles" value="R" /> Ringo</label></li> +</ul> + +If the value is None, none of the options are selected: +>>> print w.render('beatles', None, choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) +<ul> +<li><label><input type="checkbox" name="beatles" value="J" /> John</label></li> +<li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li> +<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li> +<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li> +</ul> + +If the value corresponds to a label (but not to an option value), none of the options are selected: +>>> print w.render('beatles', ['John'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) +<ul> +<li><label><input type="checkbox" name="beatles" value="J" /> John</label></li> +<li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li> +<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li> +<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li> +</ul> + +If multiple values are given, but some of them are not valid, the valid ones are selected: +>>> print w.render('beatles', ['J', 'G', 'foo'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) +<ul> +<li><label><input checked="checked" type="checkbox" name="beatles" value="J" /> John</label></li> +<li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li> +<li><label><input checked="checked" type="checkbox" name="beatles" value="G" /> George</label></li> +<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li> +</ul> + +The value is compared to its str(): +>>> print w.render('nums', [2], choices=[('1', '1'), ('2', '2'), ('3', '3')]) +<ul> +<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> +<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> +<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> +</ul> +>>> print w.render('nums', ['2'], choices=[(1, 1), (2, 2), (3, 3)]) +<ul> +<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> +<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> +<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> +</ul> +>>> print w.render('nums', [2], choices=[(1, 1), (2, 2), (3, 3)]) +<ul> +<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> +<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> +<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> +</ul> + +The 'choices' argument can be any iterable: +>>> def get_choices(): +... for i in range(5): +... yield (i, i) +>>> print w.render('nums', [2], choices=get_choices()) +<ul> +<li><label><input type="checkbox" name="nums" value="0" /> 0</label></li> +<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> +<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> +<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> +<li><label><input type="checkbox" name="nums" value="4" /> 4</label></li> +</ul> + +You can also pass 'choices' to the constructor: +>>> w = CheckboxSelectMultiple(choices=[(1, 1), (2, 2), (3, 3)]) +>>> print w.render('nums', [2]) +<ul> +<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> +<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> +<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> +</ul> + +If 'choices' is passed to both the constructor and render(), then they'll both be in the output: +>>> print w.render('nums', [2], choices=[(4, 4), (5, 5)]) +<ul> +<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> +<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> +<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> +<li><label><input type="checkbox" name="nums" value="4" /> 4</label></li> +<li><label><input type="checkbox" name="nums" value="5" /> 5</label></li> +</ul> + +>>> w.render('nums', ['ŠĐĆŽćžšđ'], choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')]) +u'<ul>\n<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li>\n<li><label><input type="checkbox" name="nums" value="2" /> 2</label></li>\n<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li>\n<li><label><input checked="checked" type="checkbox" name="nums" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" /> \u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</label></li>\n<li><label><input type="checkbox" name="nums" value="\u0107\u017e\u0161\u0111" /> abc\u0107\u017e\u0161\u0111</label></li>\n</ul>' + +# MultiWidget ################################################################# + +>>> class MyMultiWidget(MultiWidget): +... def decompress(self, value): +... if value: +... return value.split('__') +... return ['', ''] +... def format_output(self, rendered_widgets): +... return u'<br />'.join(rendered_widgets) +>>> w = MyMultiWidget(widgets=(TextInput(attrs={'class': 'big'}), TextInput(attrs={'class': 'small'}))) +>>> w.render('name', ['john', 'lennon']) +u'<input type="text" class="big" value="john" name="name_0" /><br /><input type="text" class="small" value="lennon" name="name_1" />' +>>> w.render('name', 'john__lennon') +u'<input type="text" class="big" value="john" name="name_0" /><br /><input type="text" class="small" value="lennon" name="name_1" />' +>>> w.render('name', 'john__lennon', attrs={'id':'foo'}) +u'<input id="foo_0" type="text" class="big" value="john" name="name_0" /><br /><input id="foo_1" type="text" class="small" value="lennon" name="name_1" />' +>>> w = MyMultiWidget(widgets=(TextInput(attrs={'class': 'big'}), TextInput(attrs={'class': 'small'})), attrs={'id': 'bar'}) +>>> w.render('name', ['john', 'lennon']) +u'<input id="bar_0" type="text" class="big" value="john" name="name_0" /><br /><input id="bar_1" type="text" class="small" value="lennon" name="name_1" />' + +# SplitDateTimeWidget ######################################################### + +>>> w = SplitDateTimeWidget() +>>> w.render('date', '') +u'<input type="text" name="date_0" /><input type="text" name="date_1" />' +>>> w.render('date', None) +u'<input type="text" name="date_0" /><input type="text" name="date_1" />' +>>> w.render('date', datetime.datetime(2006, 1, 10, 7, 30)) +u'<input type="text" name="date_0" value="2006-01-10" /><input type="text" name="date_1" value="07:30:00" />' +>>> w.render('date', [datetime.date(2006, 1, 10), datetime.time(7, 30)]) +u'<input type="text" name="date_0" value="2006-01-10" /><input type="text" name="date_1" value="07:30:00" />' + +You can also pass 'attrs' to the constructor. In this case, the attrs will be +included on both widgets. +>>> w = SplitDateTimeWidget(attrs={'class': 'pretty'}) +>>> w.render('date', datetime.datetime(2006, 1, 10, 7, 30)) +u'<input type="text" class="pretty" value="2006-01-10" name="date_0" /><input type="text" class="pretty" value="07:30:00" name="date_1" />' +""" diff --git a/tests/regressiontests/max_lengths/__init__.py b/tests/regressiontests/max_lengths/__init__.py new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/tests/regressiontests/max_lengths/__init__.py @@ -0,0 +1 @@ + diff --git a/tests/regressiontests/max_lengths/models.py b/tests/regressiontests/max_lengths/models.py new file mode 100644 index 0000000000..b4c43a220d --- /dev/null +++ b/tests/regressiontests/max_lengths/models.py @@ -0,0 +1,13 @@ +from django.db import models + +class PersonWithDefaultMaxLengths(models.Model): + email = models.EmailField() + vcard = models.FileField(upload_to='/tmp') + homepage = models.URLField() + avatar = models.FilePathField() + +class PersonWithCustomMaxLengths(models.Model): + email = models.EmailField(max_length=384) + vcard = models.FileField(upload_to='/tmp', max_length=1024) + homepage = models.URLField(max_length=256) + avatar = models.FilePathField(max_length=512) diff --git a/tests/regressiontests/max_lengths/tests.py b/tests/regressiontests/max_lengths/tests.py new file mode 100644 index 0000000000..0ef407f573 --- /dev/null +++ b/tests/regressiontests/max_lengths/tests.py @@ -0,0 +1,36 @@ +from unittest import TestCase +from django.db import DatabaseError +from regressiontests.max_lengths.models import PersonWithDefaultMaxLengths, PersonWithCustomMaxLengths + +class MaxLengthArgumentsTests(TestCase): + + def verify_max_length(self, model,field,length): + self.assertEquals(model._meta.get_field(field).max_length,length) + + def test_default_max_lengths(self): + self.verify_max_length(PersonWithDefaultMaxLengths, 'email', 75) + self.verify_max_length(PersonWithDefaultMaxLengths, 'vcard', 100) + self.verify_max_length(PersonWithDefaultMaxLengths, 'homepage', 200) + self.verify_max_length(PersonWithDefaultMaxLengths, 'avatar', 100) + + def test_custom_maxlengths(self): + self.verify_max_length(PersonWithCustomMaxLengths, 'email', 384) + self.verify_max_length(PersonWithCustomMaxLengths, 'vcard', 1024) + self.verify_max_length(PersonWithCustomMaxLengths, 'homepage', 256) + self.verify_max_length(PersonWithCustomMaxLengths, 'avatar', 512) + +class MaxLengthORMTests(TestCase): + + def test_custom_max_lengths(self): + args = { + "email": "someone@example.com", + "vcard": "vcard", + "homepage": "http://example.com/", + "avatar": "me.jpg" + } + + for field in ("email", "vcard", "homepage", "avatar"): + new_args = args.copy() + new_args[field] = "X" * 250 # a value longer than any of the default fields could hold. + p = PersonWithCustomMaxLengths.objects.create(**new_args) + self.assertEqual(getattr(p, field), ("X" * 250))
\ No newline at end of file diff --git a/tests/regressiontests/model_regress/models.py b/tests/regressiontests/model_regress/models.py index 7aa9e2a7c4..00c3bc96f0 100644 --- a/tests/regressiontests/model_regress/models.py +++ b/tests/regressiontests/model_regress/models.py @@ -20,6 +20,11 @@ class Article(models.Model): def __unicode__(self): return self.headline +class Movie(models.Model): + #5218: Test models with non-default primary keys / AutoFields + movie_id = models.AutoField(primary_key=True) + name = models.CharField(max_length=60) + __test__ = {'API_TESTS': """ (NOTE: Part of the regression test here is merely parsing the model declaration. The verbose_name, in particular, did not always work.) diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py index 0f7ac2f352..0c851d5f78 100644 --- a/tests/regressiontests/templates/tests.py +++ b/tests/regressiontests/templates/tests.py @@ -306,6 +306,14 @@ class Templates(unittest.TestCase): 'cycle06': ('{% cycle a %}', {}, template.TemplateSyntaxError), 'cycle07': ('{% cycle a,b,c as foo %}{% cycle bar %}', {}, template.TemplateSyntaxError), 'cycle08': ('{% cycle a,b,c as foo %}{% cycle foo %}{{ foo }}{{ foo }}{% cycle foo %}{{ foo }}', {}, 'abbbcc'), + 'cycle09': ("{% for i in test %}{% cycle a,b %}{{ i }},{% endfor %}", {'test': range(5)}, 'a0,b1,a2,b3,a4,'), + # New format: + 'cycle10': ("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}", {}, 'ab'), + 'cycle11': ("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}{% cycle abc %}", {}, 'abc'), + 'cycle12': ("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}{% cycle abc %}{% cycle abc %}", {}, 'abca'), + 'cycle13': ("{% for i in test %}{% cycle 'a' 'b' %}{{ i }},{% endfor %}", {'test': range(5)}, 'a0,b1,a2,b3,a4,'), + 'cycle14': ("{% cycle one two as foo %}{% cycle foo %}", {'one': '1','two': '2'}, '12'), + 'cycle13': ("{% for i in test %}{% cycle aye bee %}{{ i }},{% endfor %}", {'test': range(5), 'aye': 'a', 'bee': 'b'}, 'a0,b1,a2,b3,a4,'), ### EXCEPTIONS ############################################################ @@ -763,6 +771,10 @@ class Templates(unittest.TestCase): # Check that timezone is respected 'timesince06' : ('{{ a|timesince:b }}', {'a':NOW_tz + timedelta(hours=8), 'b':NOW_tz}, '8 hours'), + # Check times in the future. + 'timesince07' : ('{{ a|timesince }}', {'a':datetime.now() + timedelta(minutes=1, seconds=10)}, '0 minutes'), + 'timesince08' : ('{{ a|timesince }}', {'a':datetime.now() + timedelta(days=1, minutes=1)}, '0 minutes'), + ### TIMEUNTIL TAG ################################################## # Default compare with datetime.now() 'timeuntil01' : ('{{ a|timeuntil }}', {'a':datetime.now() + timedelta(minutes=2, seconds = 10)}, '2 minutes'), @@ -773,6 +785,10 @@ class Templates(unittest.TestCase): 'timeuntil04' : ('{{ a|timeuntil:b }}', {'a':NOW - timedelta(days=1), 'b':NOW - timedelta(days=2)}, '1 day'), 'timeuntil05' : ('{{ a|timeuntil:b }}', {'a':NOW - timedelta(days=2), 'b':NOW - timedelta(days=2, minutes=1)}, '1 minute'), + # Check times in the past. + 'timeuntil07' : ('{{ a|timeuntil }}', {'a':datetime.now() - timedelta(minutes=1, seconds=10)}, '0 minutes'), + 'timeuntil08' : ('{{ a|timeuntil }}', {'a':datetime.now() - timedelta(days=1, minutes=1)}, '0 minutes'), + ### URL TAG ######################################################## # Successes 'url01' : ('{% url regressiontests.templates.views.client client.id %}', {'client': {'id': 1}}, '/url_tag/client/1/'), diff --git a/tests/regressiontests/test_client_regress/fixtures/testdata.json b/tests/regressiontests/test_client_regress/fixtures/testdata.json new file mode 100644 index 0000000000..5c9e415240 --- /dev/null +++ b/tests/regressiontests/test_client_regress/fixtures/testdata.json @@ -0,0 +1,20 @@ +[ + { + "pk": "1", + "model": "auth.user", + "fields": { + "username": "testclient", + "first_name": "Test", + "last_name": "Client", + "is_active": true, + "is_superuser": false, + "is_staff": false, + "last_login": "2006-12-17 07:03:31", + "groups": [], + "user_permissions": [], + "password": "sha1$6efc0$f93efe9fd7542f25a7be94871ea45aa95de57161", + "email": "testclient@example.com", + "date_joined": "2006-12-17 07:03:31" + } + } +]
\ No newline at end of file diff --git a/tests/regressiontests/test_client_regress/models.py b/tests/regressiontests/test_client_regress/models.py index e17770cd03..60fd909f43 100644 --- a/tests/regressiontests/test_client_regress/models.py +++ b/tests/regressiontests/test_client_regress/models.py @@ -75,7 +75,7 @@ class AssertTemplateUsedTests(TestCase): try: self.assertTemplateUsed(response, 'Empty POST Template') except AssertionError, e: - self.assertEquals(str(e), "Template 'Empty POST Template' was not used to render the response. Actual template was 'Empty GET Template'") + self.assertEquals(str(e), "Template 'Empty POST Template' was not a template used to render the response. Actual template(s) used: Empty GET Template") def test_multiple_context(self): "Template assertions work when there are multiple contexts" @@ -101,7 +101,7 @@ class AssertTemplateUsedTests(TestCase): try: self.assertTemplateUsed(response, "Valid POST Template") except AssertionError, e: - self.assertEquals(str(e), "Template 'Valid POST Template' was not one of the templates used to render the response. Templates used: form_view.html, base.html") + self.assertEquals(str(e), "Template 'Valid POST Template' was not a template used to render the response. Actual template(s) used: form_view.html, base.html") class AssertRedirectsTests(TestCase): def test_redirect_page(self): @@ -112,6 +112,14 @@ class AssertRedirectsTests(TestCase): self.assertRedirects(response, '/test_client/get_view/') except AssertionError, e: self.assertEquals(str(e), "Response didn't redirect as expected: Response code was 301 (expected 302)") + + def test_lost_query(self): + "An assertion is raised if the redirect location doesn't preserve GET parameters" + response = self.client.get('/test_client/redirect_view/', {'var': 'value'}) + try: + self.assertRedirects(response, '/test_client/get_view/') + except AssertionError, e: + self.assertEquals(str(e), "Response redirected to 'http://testserver/test_client/get_view/?var=value', expected '/test_client/get_view/'") def test_incorrect_target(self): "An assertion is raised if the response redirects to another target" @@ -127,7 +135,7 @@ class AssertRedirectsTests(TestCase): response = self.client.get('/test_client/double_redirect_view/') try: # The redirect target responds with a 301 code, not 200 - self.assertRedirects(response, '/test_client/permanent_redirect_view/') + self.assertRedirects(response, 'http://testserver/test_client/permanent_redirect_view/') except AssertionError, e: self.assertEquals(str(e), "Couldn't retrieve redirection page '/test_client/permanent_redirect_view/': response code was 301 (expected 200)") @@ -203,8 +211,29 @@ class AssertFormErrorTests(TestCase): self.assertFormError(response, 'form', 'email', 'Some error.') except AssertionError, e: self.assertEqual(str(e), "The field 'email' on form 'form' in context 0 does not contain the error 'Some error.' (actual errors: [u'Enter a valid e-mail address.'])") + + def test_unknown_nonfield_error(self): + """ + Checks that an assertion is raised if the form's non field errors + doesn't contain the provided error. + """ + post_data = { + 'text': 'Hello World', + 'email': 'not an email address', + 'value': 37, + 'single': 'b', + 'multi': ('b','c','e') + } + response = self.client.post('/test_client/form_view/', post_data) + self.assertEqual(response.status_code, 200) + self.assertTemplateUsed(response, "Invalid POST Template") + + try: + self.assertFormError(response, 'form', None, 'Some error.') + except AssertionError, e: + self.assertEqual(str(e), "The form 'form' in context 0 does not contain the non-field error 'Some error.' (actual errors: )") -class AssertFileUploadTests(TestCase): +class FileUploadTests(TestCase): def test_simple_upload(self): fd = open(os.path.join(os.path.dirname(__file__), "views.py")) post_data = { @@ -213,3 +242,22 @@ class AssertFileUploadTests(TestCase): } response = self.client.post('/test_client_regress/file_upload/', post_data) self.assertEqual(response.status_code, 200) + +class LoginTests(TestCase): + fixtures = ['testdata'] + + def test_login_different_client(self): + "Check that using a different test client doesn't violate authentication" + + # Create a second client, and log in. + c = Client() + login = c.login(username='testclient', password='password') + self.failUnless(login, 'Could not log in') + + # Get a redirection page with the second client. + response = c.get("/test_client_regress/login_protected_redirect_view/") + + # At this points, the self.client isn't logged in. + # Check that assertRedirects uses the original client, not the + # default client. + self.assertRedirects(response, "http://testserver/test_client_regress/get_view/") diff --git a/tests/regressiontests/test_client_regress/urls.py b/tests/regressiontests/test_client_regress/urls.py index 160f9f992d..e771707f61 100644 --- a/tests/regressiontests/test_client_regress/urls.py +++ b/tests/regressiontests/test_client_regress/urls.py @@ -4,4 +4,6 @@ import views urlpatterns = patterns('', (r'^no_template_view/$', views.no_template_view), (r'^file_upload/$', views.file_upload_view), + (r'^get_view/$', views.get_view), + (r'^login_protected_redirect_view/$', views.login_protected_redirect_view) ) diff --git a/tests/regressiontests/test_client_regress/views.py b/tests/regressiontests/test_client_regress/views.py index d3fbcf8448..75efd212e1 100644 --- a/tests/regressiontests/test_client_regress/views.py +++ b/tests/regressiontests/test_client_regress/views.py @@ -1,5 +1,6 @@ +from django.contrib.auth.decorators import login_required from django.core.mail import EmailMessage, SMTPConnection -from django.http import HttpResponse, HttpResponseServerError +from django.http import HttpResponse, HttpResponseRedirect, HttpResponseServerError from django.shortcuts import render_to_response def no_template_view(request): @@ -18,3 +19,12 @@ def file_upload_view(request): else: return HttpResponseServerError() +def get_view(request): + "A simple login protected view" + return HttpResponse("Hello world") +get_view = login_required(get_view) + +def login_protected_redirect_view(request): + "A view that redirects all requests to the GET view" + return HttpResponseRedirect('/test_client_regress/get_view/') +login_protected_redirect_view = login_required(login_protected_redirect_view)
\ No newline at end of file diff --git a/tests/regressiontests/utils/tests.py b/tests/regressiontests/utils/tests.py index 258aea697e..fe0b226adc 100644 --- a/tests/regressiontests/utils/tests.py +++ b/tests/regressiontests/utils/tests.py @@ -6,6 +6,8 @@ from unittest import TestCase from django.utils import html +from timesince import timesince_tests + class TestUtilsHtml(TestCase): def check_output(self, function, value, output=None): @@ -113,3 +115,11 @@ class TestUtilsHtml(TestCase): ) for value, output in items: self.check_output(f, value, output) + +__test__ = { + 'timesince_tests': timesince_tests, +} + +if __name__ == "__main__": + import doctest + doctest.testmod() diff --git a/tests/regressiontests/utils/timesince.py b/tests/regressiontests/utils/timesince.py new file mode 100644 index 0000000000..30200be6e9 --- /dev/null +++ b/tests/regressiontests/utils/timesince.py @@ -0,0 +1,77 @@ +timesince_tests = """ +>>> from datetime import datetime, timedelta +>>> from django.utils.timesince import timesince + +>>> t = datetime(2007, 8, 14, 13, 46, 0) + +>>> onemicrosecond = timedelta(microseconds=1) +>>> onesecond = timedelta(seconds=1) +>>> oneminute = timedelta(minutes=1) +>>> onehour = timedelta(hours=1) +>>> oneday = timedelta(days=1) +>>> oneweek = timedelta(days=7) +>>> onemonth = timedelta(days=30) +>>> oneyear = timedelta(days=365) + +# equal datetimes. +>>> timesince(t, t) +u'0 minutes' + +# Microseconds and seconds are ignored. +>>> timesince(t, t+onemicrosecond) +u'0 minutes' +>>> timesince(t, t+onesecond) +u'0 minutes' + +# Test other units. +>>> timesince(t, t+oneminute) +u'1 minute' +>>> timesince(t, t+onehour) +u'1 hour' +>>> timesince(t, t+oneday) +u'1 day' +>>> timesince(t, t+oneweek) +u'1 week' +>>> timesince(t, t+onemonth) +u'1 month' +>>> timesince(t, t+oneyear) +u'1 year' + +# Test multiple units. +>>> timesince(t, t+2*oneday+6*onehour) +u'2 days, 6 hours' +>>> timesince(t, t+2*oneweek+2*oneday) +u'2 weeks, 2 days' + +# If the two differing units aren't adjacent, only the first unit is displayed. +>>> timesince(t, t+2*oneweek+3*onehour+4*oneminute) +u'2 weeks' +>>> timesince(t, t+4*oneday+5*oneminute) +u'4 days' + +# When the second date occurs before the first, we should always get 0 minutes. +>>> timesince(t, t-onemicrosecond) +u'0 minutes' +>>> timesince(t, t-onesecond) +u'0 minutes' +>>> timesince(t, t-oneminute) +u'0 minutes' +>>> timesince(t, t-onehour) +u'0 minutes' +>>> timesince(t, t-oneday) +u'0 minutes' +>>> timesince(t, t-oneweek) +u'0 minutes' +>>> timesince(t, t-onemonth) +u'0 minutes' +>>> timesince(t, t-oneyear) +u'0 minutes' +>>> timesince(t, t-2*oneday-6*onehour) +u'0 minutes' +>>> timesince(t, t-2*oneweek-2*oneday) +u'0 minutes' +>>> timesince(t, t-2*oneweek-3*onehour-4*oneminute) +u'0 minutes' +>>> timesince(t, t-4*oneday-5*oneminute) +u'0 minutes' +""" diff --git a/tests/regressiontests/views/__init__.py b/tests/regressiontests/views/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/regressiontests/views/__init__.py diff --git a/tests/regressiontests/views/fixtures/testdata.json b/tests/regressiontests/views/fixtures/testdata.json new file mode 100644 index 0000000000..449e91913a --- /dev/null +++ b/tests/regressiontests/views/fixtures/testdata.json @@ -0,0 +1,48 @@ +[ + { + "pk": 1, + "model": "views.article", + "fields": { + "author": 1, + "title": "Old Article", + "slug": "old_article", + "date_created": "2001-01-01 21:22:23" + } + }, + { + "pk": 2, + "model": "views.article", + "fields": { + "author": 1, + "title": "Current Article", + "slug": "current_article", + "date_created": "2007-09-17 21:22:23" + } + }, + { + "pk": 3, + "model": "views.article", + "fields": { + "author": 1, + "title": "Future Article", + "slug": "future_article", + "date_created": "3000-01-01 21:22:23" + } + }, + + { + "pk": 1, + "model": "views.author", + "fields": { + "name": "Boris" + } + }, + { + "pk": 1, + "model": "sites.site", + "fields": { + "domain": "testserver", + "name": "testserver" + } + } +] diff --git a/tests/regressiontests/views/locale/en/LC_MESSAGES/djangojs.mo b/tests/regressiontests/views/locale/en/LC_MESSAGES/djangojs.mo Binary files differnew file mode 100644 index 0000000000..7593e1eb48 --- /dev/null +++ b/tests/regressiontests/views/locale/en/LC_MESSAGES/djangojs.mo diff --git a/tests/regressiontests/views/locale/en/LC_MESSAGES/djangojs.po b/tests/regressiontests/views/locale/en/LC_MESSAGES/djangojs.po new file mode 100644 index 0000000000..54ee2c4065 --- /dev/null +++ b/tests/regressiontests/views/locale/en/LC_MESSAGES/djangojs.po @@ -0,0 +1,20 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-09-15 16:45+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "this is to be translated" +msgstr "this is to be translated in english"
\ No newline at end of file diff --git a/tests/regressiontests/views/locale/es/LC_MESSAGES/djangojs.mo b/tests/regressiontests/views/locale/es/LC_MESSAGES/djangojs.mo Binary files differnew file mode 100644 index 0000000000..01c002e9e0 --- /dev/null +++ b/tests/regressiontests/views/locale/es/LC_MESSAGES/djangojs.mo diff --git a/tests/regressiontests/views/locale/es/LC_MESSAGES/djangojs.po b/tests/regressiontests/views/locale/es/LC_MESSAGES/djangojs.po new file mode 100644 index 0000000000..03c01b7656 --- /dev/null +++ b/tests/regressiontests/views/locale/es/LC_MESSAGES/djangojs.po @@ -0,0 +1,21 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-09-15 16:45+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: media/js/translate.js:1 +msgid "this is to be translated" +msgstr "esto tiene que ser traducido"
\ No newline at end of file diff --git a/tests/regressiontests/views/locale/fr/LC_MESSAGES/djangojs.mo b/tests/regressiontests/views/locale/fr/LC_MESSAGES/djangojs.mo Binary files differnew file mode 100644 index 0000000000..4feca0b44d --- /dev/null +++ b/tests/regressiontests/views/locale/fr/LC_MESSAGES/djangojs.mo diff --git a/tests/regressiontests/views/locale/fr/LC_MESSAGES/djangojs.po b/tests/regressiontests/views/locale/fr/LC_MESSAGES/djangojs.po new file mode 100644 index 0000000000..9cfaa23232 --- /dev/null +++ b/tests/regressiontests/views/locale/fr/LC_MESSAGES/djangojs.po @@ -0,0 +1,20 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-09-15 19:15+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "this is to be translated" +msgstr "il faut le traduire"
\ No newline at end of file diff --git a/tests/regressiontests/views/media/file.txt b/tests/regressiontests/views/media/file.txt new file mode 100644 index 0000000000..f1fc82c455 --- /dev/null +++ b/tests/regressiontests/views/media/file.txt @@ -0,0 +1 @@ +An example media file.
\ No newline at end of file diff --git a/tests/regressiontests/views/models.py b/tests/regressiontests/views/models.py new file mode 100644 index 0000000000..4bed1f3bde --- /dev/null +++ b/tests/regressiontests/views/models.py @@ -0,0 +1,26 @@ +""" +Regression tests for Django built-in views +""" + +from django.db import models +from django.conf import settings + +class Author(models.Model): + name = models.CharField(max_length=100) + + def __unicode__(self): + return self.name + + def get_absolute_url(self): + return '/views/authors/%s/' % self.id + + +class Article(models.Model): + title = models.CharField(max_length=100) + slug = models.SlugField() + author = models.ForeignKey(Author) + date_created = models.DateTimeField() + + def __unicode__(self): + return self.title + diff --git a/tests/regressiontests/views/tests/__init__.py b/tests/regressiontests/views/tests/__init__.py new file mode 100644 index 0000000000..2c8c5b4a92 --- /dev/null +++ b/tests/regressiontests/views/tests/__init__.py @@ -0,0 +1,4 @@ +from defaults import * +from i18n import * +from static import * +from generic.date_based import *
\ No newline at end of file diff --git a/tests/regressiontests/views/tests/defaults.py b/tests/regressiontests/views/tests/defaults.py new file mode 100644 index 0000000000..bf490d7cf0 --- /dev/null +++ b/tests/regressiontests/views/tests/defaults.py @@ -0,0 +1,39 @@ +from os import path + +from django.conf import settings +from django.test import TestCase +from django.contrib.contenttypes.models import ContentType + +from regressiontests.views.models import Author, Article + +class DefaultsTests(TestCase): + """Test django views in django/views/defaults.py""" + fixtures = ['testdata.json'] + + def test_shorcut_with_absolute_url(self): + "Can view a shortcut an Author object that has with a get_absolute_url method" + for obj in Author.objects.all(): + short_url = '/views/shortcut/%s/%s/' % (ContentType.objects.get_for_model(Author).id, obj.pk) + response = self.client.get(short_url) + self.assertRedirects(response, 'http://testserver%s' % obj.get_absolute_url(), + status_code=302, target_status_code=404) + + def test_shortcut_no_absolute_url(self): + "Shortcuts for an object that has with a get_absolute_url method raises 404" + for obj in Article.objects.all(): + short_url = '/views/shortcut/%s/%s/' % (ContentType.objects.get_for_model(Article).id, obj.pk) + response = self.client.get(short_url) + self.assertEquals(response.status_code, 404) + + def test_page_not_found(self): + "A 404 status is returned by the page_not_found view" + non_existing_urls = ['/views/non_existing_url/', # this is in urls.py + '/views/other_non_existing_url/'] # this NOT in urls.py + for url in non_existing_urls: + response = self.client.get(url) + self.assertEquals(response.status_code, 404) + + def test_server_error(self): + "The server_error view raises a 500 status" + response = self.client.get('/views/server_error/') + self.assertEquals(response.status_code, 500) diff --git a/tests/regressiontests/views/tests/generic/__init__.py b/tests/regressiontests/views/tests/generic/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/regressiontests/views/tests/generic/__init__.py diff --git a/tests/regressiontests/views/tests/generic/date_based.py b/tests/regressiontests/views/tests/generic/date_based.py new file mode 100644 index 0000000000..aca93d4579 --- /dev/null +++ b/tests/regressiontests/views/tests/generic/date_based.py @@ -0,0 +1,71 @@ +# coding: utf-8 +from django.test import TestCase +from datetime import datetime +from datetime import timedelta +from regressiontests.views.models import Article, Author + +class ObjectDetailTest(TestCase): + fixtures = ['testdata.json'] + def setUp(self): + # Correct the date for the current article + current_article = Article.objects.get(title="Current Article") + current_article.date_created = datetime.now() + current_article.save() + + def test_finds_past(self): + "date_based.object_detail can view a page in the past" + response = self.client.get('/views/date_based/object_detail/2001/01/01/old_article/') + self.assertEqual(response.status_code, 200) + self.assertEqual(response.context['object'].title, "Old Article") + + def test_object_detail_finds_today(self): + "date_based.object_detail can view a page from today" + today_url = datetime.now().strftime('%Y/%m/%d') + response = self.client.get('/views/date_based/object_detail/%s/current_article/' % today_url) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.context['object'].title, "Current Article") + + def test_object_detail_ignores_future(self): + "date_based.object_detail can view a page from the future, but only if allowed." + response = self.client.get('/views/date_based/object_detail/3000/01/01/future_article/') + self.assertEqual(response.status_code, 404) + + def test_object_detail_allowed_future_if_enabled(self): + "date_based.object_detail can view a page from the future if explicitly allowed." + response = self.client.get('/views/date_based/object_detail/3000/01/01/future_article/allow_future/') + self.assertEqual(response.status_code, 200) + self.assertEqual(response.context['object'].title, "Future Article") + +class MonthArchiveTest(TestCase): + def test_archive_month_includes_only_month(self): + "Regression for #3031: Archives around Feburary include only one month" + author = Author(name="John Smith") + author.save() + + # 2004 was a leap year, so it should be weird enough to not cheat + first_second_of_feb = datetime(2004, 2, 1, 0, 0, 0) + first_second_of_mar = datetime(2004, 3, 1, 0, 0, 0) + one_microsecond = timedelta(0, 0, 1) + article = Article(title="example", author=author) + + article.date_created = first_second_of_feb + article.save() + response = self.client.get('/views/date_based/archive_month/2004/02/') + self.assertEqual(response.status_code, 200) + + article.date_created = first_second_of_feb-one_microsecond + article.save() + response = self.client.get('/views/date_based/archive_month/2004/02/') + self.assertEqual(response.status_code, 404) + + article.date_created = first_second_of_mar-one_microsecond + article.save() + response = self.client.get('/views/date_based/archive_month/2004/02/') + self.assertEqual(response.status_code, 200) + + article.date_created = first_second_of_mar + article.save() + response = self.client.get('/views/date_based/archive_month/2004/02/') + self.assertEqual(response.status_code, 404) + +
\ No newline at end of file diff --git a/tests/regressiontests/views/tests/i18n.py b/tests/regressiontests/views/tests/i18n.py new file mode 100644 index 0000000000..ebe97ab2dc --- /dev/null +++ b/tests/regressiontests/views/tests/i18n.py @@ -0,0 +1,30 @@ +from os import path +import gettext + +from django.conf import settings +from django.test import TestCase +from django.utils.translation import activate + +from regressiontests.views.urls import locale_dir + +class I18NTests(TestCase): + """ Tests django views in django/views/i18n.py """ + + def test_setlang(self): + """The set_language view can be used to change the session language""" + for lang_code, lang_name in settings.LANGUAGES: + post_data = dict(language=lang_code, next='/views/') + response = self.client.post('/views/i18n/setlang/', data=post_data) + self.assertRedirects(response, 'http://testserver/views/') + self.assertEquals(self.client.session['django_language'], lang_code) + + def test_jsi18n(self): + """The javascript_catalog can be deployed with language settings""" + for lang_code in ['es', 'fr', 'en']: + activate(lang_code) + catalog = gettext.translation('djangojs', locale_dir, [lang_code]) + trans_txt = catalog.ugettext('this is to be translated') + response = self.client.get('/views/jsi18n/') + # in response content must to be a line like that: + # catalog['this is to be translated'] = 'same_that_trans_txt' + self.assertContains(response, trans_txt, 1) diff --git a/tests/regressiontests/views/tests/static.py b/tests/regressiontests/views/tests/static.py new file mode 100644 index 0000000000..0a67cf543e --- /dev/null +++ b/tests/regressiontests/views/tests/static.py @@ -0,0 +1,15 @@ +from os import path + +from django.test import TestCase +from regressiontests.views.urls import media_dir + +class StaticTests(TestCase): + """Tests django views in django/views/static.py""" + + def test_serve(self): + "The static view can serve static media" + media_files = ['file.txt',] + for filename in media_files: + response = self.client.get('/views/site_media/%s' % filename) + file = open(path.join(media_dir, filename)) + self.assertEquals(file.read(), response.content)
\ No newline at end of file diff --git a/tests/regressiontests/views/urls.py b/tests/regressiontests/views/urls.py new file mode 100644 index 0000000000..5ef0c5129d --- /dev/null +++ b/tests/regressiontests/views/urls.py @@ -0,0 +1,48 @@ +from os import path + +from django.conf.urls.defaults import * + +from models import * +import views + +base_dir = path.dirname(path.abspath(__file__)) +media_dir = path.join(base_dir, 'media') +locale_dir = path.join(base_dir, 'locale') + +js_info_dict = { + 'domain': 'djangojs', + 'packages': ('regressiontests.views',), +} + +date_based_info_dict = { + 'queryset': Article.objects.all(), + 'date_field': 'date_created', + 'month_format': '%m', +} + +urlpatterns = patterns('', + (r'^$', views.index_page), + + # Default views + (r'^shortcut/(\d+)/(.*)/$', 'django.views.defaults.shortcut'), + (r'^non_existing_url/', 'django.views.defaults.page_not_found'), + (r'^server_error/', 'django.views.defaults.server_error'), + + # i18n views + (r'^i18n/', include('django.conf.urls.i18n')), + (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict), + + # Static views + (r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': media_dir}), + + # Date-based generic views + (r'^date_based/object_detail/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/(?P<slug>[-\w]+)/$', + 'django.views.generic.date_based.object_detail', + dict(slug_field='slug', **date_based_info_dict)), + (r'^date_based/object_detail/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/(?P<slug>[-\w]+)/allow_future/$', + 'django.views.generic.date_based.object_detail', + dict(allow_future=True, slug_field='slug', **date_based_info_dict)), + (r'^date_based/archive_month/(?P<year>\d{4})/(?P<month>\d{1,2})/$', + 'django.views.generic.date_based.archive_month', + date_based_info_dict), +) diff --git a/tests/regressiontests/views/views.py b/tests/regressiontests/views/views.py new file mode 100644 index 0000000000..9e0bbb2d66 --- /dev/null +++ b/tests/regressiontests/views/views.py @@ -0,0 +1,7 @@ +from django.http import HttpResponse +from django.template import RequestContext + +def index_page(request): + """Dummy index page""" + return HttpResponse('<html><body>Dummy page</body></html>') + diff --git a/tests/runtests.py b/tests/runtests.py index 85aea50180..736a9a61b3 100755 --- a/tests/runtests.py +++ b/tests/runtests.py @@ -4,11 +4,17 @@ import os, sys, traceback import unittest import django.contrib as contrib + +try: + set +except NameError: + from sets import Set as set # For Python 2.3 + + CONTRIB_DIR_NAME = 'django.contrib' MODEL_TESTS_DIR_NAME = 'modeltests' REGRESSION_TESTS_DIR_NAME = 'regressiontests' -TEST_DATABASE_NAME = 'django_test_db' TEST_TEMPLATE_DIR = 'templates' CONTRIB_DIR = os.path.dirname(contrib.__file__) @@ -90,7 +96,6 @@ def django_tests(verbosity, interactive, test_labels): old_middleware_classes = settings.MIDDLEWARE_CLASSES # Redirect some settings for the duration of these tests. - settings.TEST_DATABASE_NAME = TEST_DATABASE_NAME settings.INSTALLED_APPS = ALWAYS_INSTALLED_APPS settings.ROOT_URLCONF = 'urls' settings.TEMPLATE_DIRS = (os.path.join(os.path.dirname(__file__), TEST_TEMPLATE_DIR),) @@ -143,7 +148,6 @@ def django_tests(verbosity, interactive, test_labels): # Restore the old settings. settings.INSTALLED_APPS = old_installed_apps - settings.TESTS_DATABASE_NAME = old_test_database_name settings.ROOT_URLCONF = old_root_urlconf settings.TEMPLATE_DIRS = old_template_dirs settings.USE_I18N = old_use_i18n diff --git a/tests/templates/views/article_archive_month.html b/tests/templates/views/article_archive_month.html new file mode 100644 index 0000000000..3f8ff55da6 --- /dev/null +++ b/tests/templates/views/article_archive_month.html @@ -0,0 +1 @@ +This template intentionally left blank
\ No newline at end of file diff --git a/tests/templates/views/article_detail.html b/tests/templates/views/article_detail.html new file mode 100644 index 0000000000..3f8ff55da6 --- /dev/null +++ b/tests/templates/views/article_detail.html @@ -0,0 +1 @@ +This template intentionally left blank
\ No newline at end of file diff --git a/tests/urls.py b/tests/urls.py index dd475b0ea7..d7251007c5 100644 --- a/tests/urls.py +++ b/tests/urls.py @@ -11,4 +11,7 @@ urlpatterns = patterns('', # test urlconf for {% url %} template tag (r'^url_tag/', include('regressiontests.templates.urls')), + + # django built-in views + (r'^views/', include('regressiontests.views.urls')), ) |
