diff options
| author | Honza Král <honza.kral@gmail.com> | 2009-06-03 14:03:10 +0000 |
|---|---|---|
| committer | Honza Král <honza.kral@gmail.com> | 2009-06-03 14:03:10 +0000 |
| commit | 7b14625d0d9c8dc4df87c5354c856e6f5ed3ef60 (patch) | |
| tree | 0b0e31013a52641047c5526994173db080795498 /django | |
| parent | 85e0c469aa5298b54d8d173bf1881b72b3f0c445 (diff) | |
[soc2009/model-valition] Merged to trunk at r10914
git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2009/model-validation@10916 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django')
| -rw-r--r-- | django/conf/locale/es_AR/LC_MESSAGES/django.mo | bin | 63078 -> 66901 bytes | |||
| -rw-r--r-- | django/conf/locale/es_AR/LC_MESSAGES/django.po | 774 | ||||
| -rw-r--r-- | django/contrib/gis/db/models/sql/where.py | 4 | ||||
| -rw-r--r-- | django/contrib/gis/maps/google/gmap.py | 6 | ||||
| -rw-r--r-- | django/contrib/gis/maps/google/overlays.py | 8 | ||||
| -rw-r--r-- | django/contrib/gis/tests/relatedapp/models.py | 10 | ||||
| -rw-r--r-- | django/contrib/gis/tests/relatedapp/tests.py | 34 | ||||
| -rw-r--r-- | django/contrib/gis/utils/ogrinspect.py | 56 | ||||
| -rw-r--r-- | django/db/models/fields/files.py | 133 | ||||
| -rw-r--r-- | django/db/models/query.py | 3 | ||||
| -rw-r--r-- | django/db/models/query_utils.py | 15 | ||||
| -rw-r--r-- | django/db/models/sql/query.py | 8 | ||||
| -rw-r--r-- | django/forms/models.py | 2 |
13 files changed, 689 insertions, 364 deletions
diff --git a/django/conf/locale/es_AR/LC_MESSAGES/django.mo b/django/conf/locale/es_AR/LC_MESSAGES/django.mo Binary files differindex e4474b0eb8..57349e8d9b 100644 --- a/django/conf/locale/es_AR/LC_MESSAGES/django.mo +++ b/django/conf/locale/es_AR/LC_MESSAGES/django.mo diff --git a/django/conf/locale/es_AR/LC_MESSAGES/django.po b/django/conf/locale/es_AR/LC_MESSAGES/django.po index f92735adc6..d6726ab57b 100644 --- a/django/conf/locale/es_AR/LC_MESSAGES/django.po +++ b/django/conf/locale/es_AR/LC_MESSAGES/django.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: Django\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-11-13 18:20-0200\n" -"PO-Revision-Date: 2008-11-13 18:27-0200\n" +"POT-Creation-Date: 2009-05-28 12:30-0300\n" +"PO-Revision-Date: 2009-05-05 20:35-0300\n" "Last-Translator: Ramiro Morales <rm0@gmx.net>\n" "Language-Team: Django-I18N <django-i18n@googlegroups.com>\n" "MIME-Version: 1.0\n" @@ -100,121 +100,139 @@ msgid "Hebrew" msgstr "hebreo" #: conf/global_settings.py:65 +msgid "Hindi" +msgstr "Hindi" + +#: conf/global_settings.py:66 msgid "Croatian" msgstr "croata" -#: conf/global_settings.py:66 +#: conf/global_settings.py:67 msgid "Icelandic" msgstr "islandés" -#: conf/global_settings.py:67 +#: conf/global_settings.py:68 msgid "Italian" msgstr "italiano" -#: conf/global_settings.py:68 +#: conf/global_settings.py:69 msgid "Japanese" msgstr "japonés" -#: conf/global_settings.py:69 +#: conf/global_settings.py:70 msgid "Georgian" msgstr "georgiano" -#: conf/global_settings.py:70 +#: conf/global_settings.py:71 msgid "Korean" msgstr "koreano" -#: conf/global_settings.py:71 +#: conf/global_settings.py:72 msgid "Khmer" msgstr "jémer" -#: conf/global_settings.py:72 +#: conf/global_settings.py:73 msgid "Kannada" msgstr "canarés" -#: conf/global_settings.py:73 +#: conf/global_settings.py:74 msgid "Latvian" msgstr "letón" -#: conf/global_settings.py:74 +#: conf/global_settings.py:75 msgid "Lithuanian" msgstr "lituano" -#: conf/global_settings.py:75 +#: conf/global_settings.py:76 msgid "Macedonian" msgstr "macedonio" -#: conf/global_settings.py:76 +#: conf/global_settings.py:77 msgid "Dutch" msgstr "holandés" -#: conf/global_settings.py:77 +#: conf/global_settings.py:78 msgid "Norwegian" msgstr "noruego" -#: conf/global_settings.py:78 +#: conf/global_settings.py:79 msgid "Polish" msgstr "polaco" -#: conf/global_settings.py:79 +#: conf/global_settings.py:80 msgid "Portuguese" msgstr "portugués" -#: conf/global_settings.py:80 +#: conf/global_settings.py:81 msgid "Brazilian Portuguese" msgstr "portugués de Brasil" -#: conf/global_settings.py:81 +#: conf/global_settings.py:82 msgid "Romanian" msgstr "rumano" -#: conf/global_settings.py:82 +#: conf/global_settings.py:83 msgid "Russian" msgstr "ruso" -#: conf/global_settings.py:83 +#: conf/global_settings.py:84 msgid "Slovak" msgstr "eslovaco" -#: conf/global_settings.py:84 +#: conf/global_settings.py:85 msgid "Slovenian" msgstr "esloveno" -#: conf/global_settings.py:85 +#: conf/global_settings.py:86 msgid "Serbian" msgstr "serbio" -#: conf/global_settings.py:86 +#: conf/global_settings.py:87 msgid "Swedish" msgstr "sueco" -#: conf/global_settings.py:87 +#: conf/global_settings.py:88 msgid "Tamil" msgstr "tamil" -#: conf/global_settings.py:88 +#: conf/global_settings.py:89 msgid "Telugu" msgstr "telugu" -#: conf/global_settings.py:89 +#: conf/global_settings.py:90 msgid "Thai" msgstr "tailandés" -#: conf/global_settings.py:90 +#: conf/global_settings.py:91 msgid "Turkish" msgstr "turco" -#: conf/global_settings.py:91 +#: conf/global_settings.py:92 msgid "Ukrainian" msgstr "ucraniano" -#: conf/global_settings.py:92 +#: conf/global_settings.py:93 msgid "Simplified Chinese" msgstr "chino simplificado" -#: conf/global_settings.py:93 +#: conf/global_settings.py:94 msgid "Traditional Chinese" msgstr "chino tradicional" +#: contrib/admin/actions.py:60 +#, python-format +msgid "Successfully deleted %(count)d %(items)s." +msgstr "Se eliminaron con éxito %(count)d %(items)s." + +#: contrib/admin/actions.py:67 contrib/admin/options.py:1025 +msgid "Are you sure?" +msgstr "¿Está seguro?" + +#: contrib/admin/actions.py:85 +#, python-format +msgid "Delete selected %(verbose_name_plural)s" +msgstr "Eliminar %(verbose_name_plural)s seleccionados/as" + #: contrib/admin/filterspecs.py:44 #, python-format msgid "" @@ -224,43 +242,47 @@ msgstr "" "<h3>Por %s:</h3>\n" "<ul>\n" -#: contrib/admin/filterspecs.py:74 contrib/admin/filterspecs.py:91 -#: contrib/admin/filterspecs.py:146 contrib/admin/filterspecs.py:172 +#: contrib/admin/filterspecs.py:75 contrib/admin/filterspecs.py:92 +#: contrib/admin/filterspecs.py:147 contrib/admin/filterspecs.py:173 msgid "All" msgstr "Todos/as" -#: contrib/admin/filterspecs.py:112 +#: contrib/admin/filterspecs.py:113 msgid "Any date" msgstr "Cualquier fecha" -#: contrib/admin/filterspecs.py:113 +#: contrib/admin/filterspecs.py:114 msgid "Today" msgstr "Hoy" -#: contrib/admin/filterspecs.py:116 +#: contrib/admin/filterspecs.py:117 msgid "Past 7 days" msgstr "Últimos 7 días" -#: contrib/admin/filterspecs.py:118 +#: contrib/admin/filterspecs.py:119 msgid "This month" msgstr "Este mes" -#: contrib/admin/filterspecs.py:120 +#: contrib/admin/filterspecs.py:121 msgid "This year" msgstr "Este año" -#: contrib/admin/filterspecs.py:146 forms/widgets.py:390 +#: contrib/admin/filterspecs.py:147 forms/widgets.py:434 msgid "Yes" msgstr "Sí" -#: contrib/admin/filterspecs.py:146 forms/widgets.py:390 +#: contrib/admin/filterspecs.py:147 forms/widgets.py:434 msgid "No" msgstr "No" -#: contrib/admin/filterspecs.py:153 forms/widgets.py:390 +#: contrib/admin/filterspecs.py:154 forms/widgets.py:434 msgid "Unknown" msgstr "Desconocido" +#: contrib/admin/helpers.py:14 +msgid "Action:" +msgstr "Acción:" + #: contrib/admin/models.py:19 msgid "action time" msgstr "hora de la acción" @@ -289,60 +311,61 @@ msgstr "entrada de registro" msgid "log entries" msgstr "entradas de registro" -#: contrib/admin/options.py:60 contrib/admin/options.py:121 +#: contrib/admin/options.py:133 contrib/admin/options.py:147 msgid "None" msgstr "Ninguno" -#: contrib/admin/options.py:338 +#: contrib/admin/options.py:519 #, python-format msgid "Changed %s." msgstr "Modifica %s." -#: contrib/admin/options.py:338 contrib/admin/options.py:348 -#: contrib/comments/templates/comments/preview.html:15 forms/models.py:288 +#: contrib/admin/options.py:519 contrib/admin/options.py:529 +#: contrib/comments/templates/comments/preview.html:16 forms/models.py:388 +#: forms/models.py:587 msgid "and" msgstr "y" -#: contrib/admin/options.py:343 +#: contrib/admin/options.py:524 #, python-format msgid "Added %(name)s \"%(object)s\"." msgstr "Se agregó %(name)s \"%(object)s\"." -#: contrib/admin/options.py:347 +#: contrib/admin/options.py:528 #, python-format msgid "Changed %(list)s for %(name)s \"%(object)s\"." msgstr "Se modificaron %(list)s en %(name)s \"%(object)s\"." -#: contrib/admin/options.py:352 +#: contrib/admin/options.py:533 #, python-format msgid "Deleted %(name)s \"%(object)s\"." msgstr "Se eliminó %(name)s \"%(object)s\"." -#: contrib/admin/options.py:356 +#: contrib/admin/options.py:537 msgid "No fields changed." msgstr "No ha modificado ningún campo." -#: contrib/admin/options.py:417 contrib/auth/admin.py:51 +#: contrib/admin/options.py:598 contrib/auth/admin.py:67 #, python-format msgid "The %(name)s \"%(obj)s\" was added successfully." msgstr "Se agregó con éxito %(name)s \"%(obj)s\"." -#: contrib/admin/options.py:421 contrib/admin/options.py:454 -#: contrib/auth/admin.py:59 +#: contrib/admin/options.py:602 contrib/admin/options.py:635 +#: contrib/auth/admin.py:75 msgid "You may edit it again below." msgstr "Puede modificarlo/a nuevamente abajo." -#: contrib/admin/options.py:431 contrib/admin/options.py:464 +#: contrib/admin/options.py:612 contrib/admin/options.py:645 #, python-format msgid "You may add another %s below." msgstr "Puede agregar otro/a %s abajo." -#: contrib/admin/options.py:452 +#: contrib/admin/options.py:633 #, python-format msgid "The %(name)s \"%(obj)s\" was changed successfully." msgstr "Se modificó con éxito %(name)s \"%(obj)s\"." -#: contrib/admin/options.py:460 +#: contrib/admin/options.py:641 #, python-format msgid "" "The %(name)s \"%(obj)s\" was added successfully. You may edit it again below." @@ -350,40 +373,43 @@ msgstr "" "Se agregó con éxito %(name)s \"%(obj)s\". Puede modificarlo/a nuevamente " "abajo." -#: contrib/admin/options.py:528 +#: contrib/admin/options.py:772 #, python-format msgid "Add %s" msgstr "Agregar %s" -#: contrib/admin/options.py:559 contrib/admin/options.py:673 +#: contrib/admin/options.py:803 contrib/admin/options.py:1003 #, python-format msgid "%(name)s object with primary key %(key)r does not exist." msgstr "No existe un objeto %(name)s con una clave primaria %(key)r." -#: contrib/admin/options.py:606 +#: contrib/admin/options.py:860 #, python-format msgid "Change %s" msgstr "Modificar %s" -#: contrib/admin/options.py:638 +#: contrib/admin/options.py:904 msgid "Database error" msgstr "Error de base de datos" -#: contrib/admin/options.py:688 +#: contrib/admin/options.py:940 +#, python-format +msgid "%(count)s %(name)s was changed successfully." +msgid_plural "%(count)s %(name)s were changed successfully." +msgstr[0] "Se ha modificado con éxito %(count)s %(name)s." +msgstr[1] "Se han modificado con éxito %(count)s %(name)s." + +#: contrib/admin/options.py:1018 #, python-format msgid "The %(name)s \"%(obj)s\" was deleted successfully." msgstr "Se eliminó con éxito %(name)s \"%(obj)s\"." -#: contrib/admin/options.py:695 -msgid "Are you sure?" -msgstr "¿Está seguro?" - -#: contrib/admin/options.py:724 +#: contrib/admin/options.py:1054 #, python-format msgid "Change history: %s" msgstr "Historia de modificaciones: %s" -#: contrib/admin/sites.py:16 contrib/admin/views/decorators.py:14 +#: contrib/admin/sites.py:20 contrib/admin/views/decorators.py:14 #: contrib/auth/forms.py:80 msgid "" "Please enter a correct username and password. Note that both fields are case-" @@ -392,11 +418,11 @@ msgstr "" "Por favor introduzca un nombre de usuario y una contraseña correctos. Note " "que ambos campos son sensibles a mayúsculas/minúsculas." -#: contrib/admin/sites.py:226 contrib/admin/views/decorators.py:40 +#: contrib/admin/sites.py:278 contrib/admin/views/decorators.py:40 msgid "Please log in again, because your session has expired." msgstr "Por favor, identifíquese de nuevo porque su sesión ha caducado." -#: contrib/admin/sites.py:233 contrib/admin/views/decorators.py:47 +#: contrib/admin/sites.py:285 contrib/admin/views/decorators.py:47 msgid "" "Looks like your browser isn't configured to accept cookies. Please enable " "cookies, reload this page, and try again." @@ -404,64 +430,64 @@ msgstr "" "Parece que su navegador no está configurado para aceptar cookies. Por favor " "actívelas, recargue esta página, e inténtelo de nuevo." -#: contrib/admin/sites.py:249 contrib/admin/sites.py:255 +#: contrib/admin/sites.py:301 contrib/admin/sites.py:307 #: contrib/admin/views/decorators.py:66 msgid "Usernames cannot contain the '@' character." msgstr "Los nombres de usuario no pueden contener el carácter '@'." -#: contrib/admin/sites.py:252 contrib/admin/views/decorators.py:62 +#: contrib/admin/sites.py:304 contrib/admin/views/decorators.py:62 #, python-format msgid "Your e-mail address is not your username. Try '%s' instead." msgstr "" "Su dirección de correo electrónico no es su nombre de usuario. Intente " "nuevamente usando '%s'." -#: contrib/admin/sites.py:312 +#: contrib/admin/sites.py:360 msgid "Site administration" msgstr "Administración de sitio" -#: contrib/admin/sites.py:325 contrib/admin/templates/admin/login.html:26 +#: contrib/admin/sites.py:373 contrib/admin/templates/admin/login.html:26 #: contrib/admin/templates/registration/password_reset_complete.html:14 #: contrib/admin/views/decorators.py:20 msgid "Log in" msgstr "Identificarse" -#: contrib/admin/sites.py:372 +#: contrib/admin/sites.py:417 #, python-format msgid "%s administration" msgstr "Administración de %s" -#: contrib/admin/util.py:138 +#: contrib/admin/util.py:168 #, python-format msgid "One or more %(fieldname)s in %(name)s: %(obj)s" msgstr "Uno o más %(fieldname)s en %(name)s: %(obj)s" -#: contrib/admin/util.py:143 +#: contrib/admin/util.py:173 #, python-format msgid "One or more %(fieldname)s in %(name)s:" msgstr "Uno o más %(fieldname)s en %(name)s:" -#: contrib/admin/widgets.py:70 +#: contrib/admin/widgets.py:71 msgid "Date:" msgstr "Fecha:" -#: contrib/admin/widgets.py:70 +#: contrib/admin/widgets.py:71 msgid "Time:" msgstr "Hora:" -#: contrib/admin/widgets.py:94 +#: contrib/admin/widgets.py:95 msgid "Currently:" msgstr "Actualmente" -#: contrib/admin/widgets.py:94 +#: contrib/admin/widgets.py:95 msgid "Change:" msgstr "Modificar:" -#: contrib/admin/widgets.py:123 +#: contrib/admin/widgets.py:124 msgid "Lookup" msgstr "Buscar" -#: contrib/admin/widgets.py:230 +#: contrib/admin/widgets.py:236 msgid "Add Another" msgstr "Agregar otro/a" @@ -478,8 +504,9 @@ msgstr "Lo sentimos, pero no se encuentra la página solicitada." #: contrib/admin/templates/admin/app_index.html:8 #: contrib/admin/templates/admin/base.html:31 #: contrib/admin/templates/admin/change_form.html:17 -#: contrib/admin/templates/admin/change_list.html:8 +#: contrib/admin/templates/admin/change_list.html:25 #: contrib/admin/templates/admin/delete_confirmation.html:6 +#: contrib/admin/templates/admin/delete_selected_confirmation.html:6 #: contrib/admin/templates/admin/invalid_setup.html:4 #: contrib/admin/templates/admin/object_history.html:6 #: contrib/admin/templates/admin/auth/user/change_password.html:10 @@ -515,6 +542,14 @@ msgstr "" "mediante correo electrónico y debería ser solucionado en breve. Gracias por " "su paciencia." +#: contrib/admin/templates/admin/actions.html:4 +msgid "Run the selected action" +msgstr "Ejecutar la acción seleccionada" + +#: contrib/admin/templates/admin/actions.html:4 +msgid "Go" +msgstr "Ejecutar" + #: contrib/admin/templates/admin/app_index.html:10 #: contrib/admin/templates/admin/index.html:19 #, python-format @@ -533,8 +568,8 @@ msgid "Documentation" msgstr "Documentación" #: contrib/admin/templates/admin/base.html:26 -#: contrib/admin/templates/admin/auth/user/change_password.html:13 -#: contrib/admin/templates/admin/auth/user/change_password.html:46 +#: contrib/admin/templates/admin/auth/user/change_password.html:14 +#: contrib/admin/templates/admin/auth/user/change_password.html:47 #: contrib/admin/templates/registration/password_change_done.html:3 #: contrib/admin/templates/registration/password_change_form.html:3 msgid "Change password" @@ -571,23 +606,24 @@ msgid "View on site" msgstr "Ver en el sitio" #: contrib/admin/templates/admin/change_form.html:38 -#: contrib/admin/templates/admin/auth/user/change_password.html:22 +#: contrib/admin/templates/admin/change_list.html:54 +#: contrib/admin/templates/admin/auth/user/change_password.html:23 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/change_list.html:16 +#: contrib/admin/templates/admin/change_list.html:46 #, python-format msgid "Add %(name)s" msgstr "Agregar %(name)s" -#: contrib/admin/templates/admin/change_list.html:26 +#: contrib/admin/templates/admin/change_list.html:65 msgid "Filter" msgstr "Filtrar" #: contrib/admin/templates/admin/delete_confirmation.html:10 -#: contrib/admin/templates/admin/submit_line.html:4 forms/formsets.py:246 +#: contrib/admin/templates/admin/submit_line.html:4 forms/formsets.py:275 msgid "Delete" msgstr "Eliminar" @@ -612,9 +648,34 @@ msgstr "" "\"? Se eliminarán los siguientes objetos relacionados:" #: contrib/admin/templates/admin/delete_confirmation.html:28 +#: contrib/admin/templates/admin/delete_selected_confirmation.html:33 msgid "Yes, I'm sure" msgstr "Sí, estoy seguro" +#: contrib/admin/templates/admin/delete_selected_confirmation.html:9 +msgid "Delete multiple objects" +msgstr "Eliminar múltiples objetos" + +#: contrib/admin/templates/admin/delete_selected_confirmation.html:15 +#, python-format +msgid "" +"Deleting the %(object_name)s would result in deleting related objects, but " +"your account doesn't have permission to delete the following types of " +"objects:" +msgstr "" +"El eliminar %(object_name)s provocaría la eliminación de objetos " +"relacionados, pero su cuenta no tiene permiso para eliminar los siguientes " +"tipos de objetos:" + +#: contrib/admin/templates/admin/delete_selected_confirmation.html:22 +#, python-format +msgid "" +"Are you sure you want to delete the selected %(object_name)s objects? All of " +"the following objects and it's related items will be deleted:" +msgstr "" +"¿Está seguro de que quiere eliminar los objetos %(object_name)s? Se " +"eliminarán todos los siguientes objetos relacionados:" + #: contrib/admin/templates/admin/filter.html:2 #, python-format msgid " By %(filter_title)s " @@ -645,6 +706,10 @@ msgstr "Mis acciones" msgid "None available" msgstr "Ninguna disponible" +#: contrib/admin/templates/admin/index.html:72 +msgid "Unknown content" +msgstr "COntenido desconocido" + #: contrib/admin/templates/admin/invalid_setup.html:7 msgid "" "Something's wrong with your database installation. Make sure the appropriate " @@ -677,7 +742,7 @@ msgid "Action" msgstr "Acción" #: contrib/admin/templates/admin/object_history.html:30 -#: utils/translation/trans_real.py:404 +#: utils/translation/trans_real.py:400 msgid "DATETIME_FORMAT" msgstr "j N Y P" @@ -694,7 +759,7 @@ msgid "Show all" msgstr "Mostrar todos/as" #: contrib/admin/templates/admin/search_form.html:8 -msgid "Go" +msgid "Search" msgstr "Buscar" #: contrib/admin/templates/admin/search_form.html:10 @@ -739,24 +804,24 @@ msgid "Username" msgstr "Nombre de usuario:" #: contrib/admin/templates/admin/auth/user/add_form.html:20 -#: contrib/admin/templates/admin/auth/user/change_password.html:33 -#: contrib/auth/forms.py:17 contrib/auth/forms.py:60 contrib/auth/forms.py:184 +#: contrib/admin/templates/admin/auth/user/change_password.html:34 +#: contrib/auth/forms.py:17 contrib/auth/forms.py:60 contrib/auth/forms.py:185 msgid "Password" msgstr "Contraseña:" #: contrib/admin/templates/admin/auth/user/add_form.html:26 -#: contrib/admin/templates/admin/auth/user/change_password.html:39 -#: contrib/auth/forms.py:185 +#: contrib/admin/templates/admin/auth/user/change_password.html:40 +#: contrib/auth/forms.py:186 msgid "Password (again)" msgstr "Contraseña (de nuevo)" #: contrib/admin/templates/admin/auth/user/add_form.html:27 -#: contrib/admin/templates/admin/auth/user/change_password.html:40 +#: contrib/admin/templates/admin/auth/user/change_password.html:41 msgid "Enter the same password as above, for verification." msgstr "" "Para verificación, introduzca la misma contraseña que introdujo arriba." -#: contrib/admin/templates/admin/auth/user/change_password.html:26 +#: contrib/admin/templates/admin/auth/user/change_password.html:27 #, python-format msgid "Enter a new password for the user <strong>%(username)s</strong>." msgstr "" @@ -925,166 +990,166 @@ msgstr "Dirección de correo electrónico:" msgid "Reset my password" msgstr "Recuperar mi contraseña" -#: contrib/admin/templatetags/admin_list.py:284 +#: contrib/admin/templatetags/admin_list.py:299 msgid "All dates" msgstr "Todas las fechas" -#: contrib/admin/views/main.py:69 +#: contrib/admin/views/main.py:70 #, python-format msgid "Select %s" msgstr "Seleccione %s" -#: contrib/admin/views/main.py:69 +#: contrib/admin/views/main.py:70 #, python-format msgid "Select %s to change" msgstr "Seleccione %s a modificar" -#: contrib/admin/views/template.py:36 contrib/sites/models.py:38 +#: contrib/admin/views/template.py:37 contrib/sites/models.py:38 msgid "site" msgstr "sitio" -#: contrib/admin/views/template.py:38 +#: contrib/admin/views/template.py:39 msgid "template" msgstr "plantilla" -#: contrib/admindocs/views.py:57 contrib/admindocs/views.py:59 -#: contrib/admindocs/views.py:61 +#: contrib/admindocs/views.py:58 contrib/admindocs/views.py:60 +#: contrib/admindocs/views.py:62 msgid "tag:" msgstr "etiqueta:" -#: contrib/admindocs/views.py:90 contrib/admindocs/views.py:92 -#: contrib/admindocs/views.py:94 +#: contrib/admindocs/views.py:91 contrib/admindocs/views.py:93 +#: contrib/admindocs/views.py:95 msgid "filter:" msgstr "filtrar:" -#: contrib/admindocs/views.py:154 contrib/admindocs/views.py:156 -#: contrib/admindocs/views.py:158 +#: contrib/admindocs/views.py:155 contrib/admindocs/views.py:157 +#: contrib/admindocs/views.py:159 msgid "view:" msgstr "ver:" -#: contrib/admindocs/views.py:186 +#: contrib/admindocs/views.py:187 #, python-format msgid "App %r not found" msgstr "Aplicación %r no encontrada" -#: contrib/admindocs/views.py:193 +#: contrib/admindocs/views.py:194 #, python-format msgid "Model %(model_name)r not found in app %(app_label)r" msgstr "Modelo %(model_name)r no encontrado en aplicación %(app_label)r" -#: contrib/admindocs/views.py:205 +#: contrib/admindocs/views.py:206 #, python-format msgid "the related `%(app_label)s.%(data_type)s` object" msgstr "el objeto `%(app_label)s.%(data_type)s` relacionado" -#: contrib/admindocs/views.py:205 contrib/admindocs/views.py:227 -#: contrib/admindocs/views.py:241 contrib/admindocs/views.py:246 +#: contrib/admindocs/views.py:206 contrib/admindocs/views.py:228 +#: contrib/admindocs/views.py:242 contrib/admindocs/views.py:247 msgid "model:" msgstr "modelo:" -#: contrib/admindocs/views.py:236 +#: contrib/admindocs/views.py:237 #, python-format msgid "related `%(app_label)s.%(object_name)s` objects" msgstr "objetos `%(app_label)s.%(object_name)s` relacionados" -#: contrib/admindocs/views.py:241 +#: contrib/admindocs/views.py:242 #, python-format msgid "all %s" msgstr "todos los %s" -#: contrib/admindocs/views.py:246 +#: contrib/admindocs/views.py:247 #, python-format msgid "number of %s" msgstr "número de %s" -#: contrib/admindocs/views.py:251 +#: contrib/admindocs/views.py:252 #, python-format msgid "Fields on %s objects" msgstr "Campos en objetos %s" -#: contrib/admindocs/views.py:314 contrib/admindocs/views.py:325 -#: contrib/admindocs/views.py:327 contrib/admindocs/views.py:333 -#: contrib/admindocs/views.py:334 contrib/admindocs/views.py:336 +#: contrib/admindocs/views.py:315 contrib/admindocs/views.py:326 +#: contrib/admindocs/views.py:328 contrib/admindocs/views.py:334 +#: contrib/admindocs/views.py:335 contrib/admindocs/views.py:337 msgid "Integer" msgstr "Entero" -#: contrib/admindocs/views.py:315 +#: contrib/admindocs/views.py:316 msgid "Boolean (Either True or False)" msgstr "Booleano (Verdadero o Falso)" -#: contrib/admindocs/views.py:316 contrib/admindocs/views.py:335 +#: contrib/admindocs/views.py:317 contrib/admindocs/views.py:336 #, python-format msgid "String (up to %(max_length)s)" msgstr "Cadena (máximo %(max_length)s)" -#: contrib/admindocs/views.py:317 +#: contrib/admindocs/views.py:318 msgid "Comma-separated integers" msgstr "Enteros separados por comas" -#: contrib/admindocs/views.py:318 +#: contrib/admindocs/views.py:319 msgid "Date (without time)" msgstr "Fecha (sin hora)" -#: contrib/admindocs/views.py:319 +#: contrib/admindocs/views.py:320 msgid "Date (with time)" msgstr "Fecha (con hora)" -#: contrib/admindocs/views.py:320 +#: contrib/admindocs/views.py:321 msgid "Decimal number" msgstr "Número decimal" -#: contrib/admindocs/views.py:321 +#: contrib/admindocs/views.py:322 msgid "E-mail address" msgstr "Dirección de correo electrónico" -#: contrib/admindocs/views.py:322 contrib/admindocs/views.py:323 -#: contrib/admindocs/views.py:326 +#: contrib/admindocs/views.py:323 contrib/admindocs/views.py:324 +#: contrib/admindocs/views.py:327 msgid "File path" msgstr "Ruta de archivo" -#: contrib/admindocs/views.py:324 +#: contrib/admindocs/views.py:325 msgid "Floating point number" msgstr "Número de punto flotante" -#: contrib/admindocs/views.py:328 contrib/comments/models.py:58 +#: contrib/admindocs/views.py:329 contrib/comments/models.py:60 msgid "IP address" msgstr "Dirección IP" -#: contrib/admindocs/views.py:330 +#: contrib/admindocs/views.py:331 msgid "Boolean (Either True, False or None)" msgstr "Booleano (Verdadero, Falso o Nulo)" -#: contrib/admindocs/views.py:331 +#: contrib/admindocs/views.py:332 msgid "Relation to parent model" msgstr "Relación con el modelo padre" -#: contrib/admindocs/views.py:332 +#: contrib/admindocs/views.py:333 msgid "Phone number" msgstr "Número de teléfono" -#: contrib/admindocs/views.py:337 +#: contrib/admindocs/views.py:338 msgid "Text" msgstr "Texto" -#: contrib/admindocs/views.py:338 +#: contrib/admindocs/views.py:339 msgid "Time" msgstr "Hora" -#: contrib/admindocs/views.py:339 contrib/comments/forms.py:21 +#: contrib/admindocs/views.py:340 contrib/comments/forms.py:95 #: contrib/comments/templates/comments/moderation_queue.html:37 #: contrib/flatpages/admin.py:8 contrib/flatpages/models.py:7 msgid "URL" msgstr "URL" -#: contrib/admindocs/views.py:340 +#: contrib/admindocs/views.py:341 msgid "U.S. state (two uppercase letters)" msgstr "Estado de los EE.UU. (dos letras mayúsculas)" -#: contrib/admindocs/views.py:341 +#: contrib/admindocs/views.py:342 msgid "XML text" msgstr "Texto XML" -#: contrib/admindocs/views.py:367 +#: contrib/admindocs/views.py:368 #, python-format msgid "%s does not appear to be a urlpattern object" msgstr "%s no parece ser un objeto urlpattern" @@ -1174,21 +1239,21 @@ msgstr "Fechas importantes" msgid "Groups" msgstr "Grupos" -#: contrib/auth/admin.py:64 +#: contrib/auth/admin.py:80 msgid "Add user" msgstr "Agregar usuario" -#: contrib/auth/admin.py:90 +#: contrib/auth/admin.py:106 msgid "Password changed successfully." msgstr "Cambio de contraseña exitoso" -#: contrib/auth/admin.py:96 +#: contrib/auth/admin.py:112 #, python-format msgid "Change password: %s" msgstr "Cambiar contraseña: %s" #: contrib/auth/forms.py:15 contrib/auth/forms.py:48 -#: contrib/auth/models.py:127 +#: contrib/auth/models.py:128 msgid "" "Required. 30 characters or fewer. Alphanumeric characters only (letters, " "digits and underscores)." @@ -1208,8 +1273,8 @@ msgstr "Confirmación de contraseña" msgid "A user with that username already exists." msgstr "Ya existe un usuario con ese nombre." -#: contrib/auth/forms.py:36 contrib/auth/forms.py:154 -#: contrib/auth/forms.py:196 +#: contrib/auth/forms.py:36 contrib/auth/forms.py:155 +#: contrib/auth/forms.py:197 msgid "The two password fields didn't match." msgstr "Los dos campos de contraseñas no coinciden entre si." @@ -1237,24 +1302,24 @@ msgstr "" "Esa dirección de e-mail no está asociada a ninguna cuenta de usuario. ¿Está " "seguro de que ya se ha registrado?" -#: contrib/auth/forms.py:134 +#: contrib/auth/forms.py:135 #, python-format msgid "Password reset on %s" msgstr "Reinicialización de contraseña en %s" -#: contrib/auth/forms.py:142 +#: contrib/auth/forms.py:143 msgid "New password" msgstr "Contraseña nueva" -#: contrib/auth/forms.py:143 +#: contrib/auth/forms.py:144 msgid "New password confirmation" msgstr "Confirmación de contraseña nueva" -#: contrib/auth/forms.py:168 +#: contrib/auth/forms.py:169 msgid "Old password" msgstr "Contraseña antigua" -#: contrib/auth/forms.py:176 +#: contrib/auth/forms.py:177 msgid "Your old password was entered incorrectly. Please enter it again." msgstr "" "La antigua contraseña introducida es incorrecta. Por favor introdúzcala " @@ -1280,31 +1345,31 @@ msgstr "permisos" msgid "group" msgstr "grupo" -#: contrib/auth/models.py:91 contrib/auth/models.py:137 +#: contrib/auth/models.py:91 contrib/auth/models.py:138 msgid "groups" msgstr "grupos" -#: contrib/auth/models.py:127 +#: contrib/auth/models.py:128 msgid "username" msgstr "nombre de usuario" -#: contrib/auth/models.py:128 +#: contrib/auth/models.py:129 msgid "first name" msgstr "nombre" -#: contrib/auth/models.py:129 +#: contrib/auth/models.py:130 msgid "last name" msgstr "apellido" -#: contrib/auth/models.py:130 +#: contrib/auth/models.py:131 msgid "e-mail address" msgstr "dirección de correo electrónico" -#: contrib/auth/models.py:131 +#: contrib/auth/models.py:132 msgid "password" msgstr "contraseña" -#: contrib/auth/models.py:131 +#: contrib/auth/models.py:132 msgid "" "Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change " "password form</a>." @@ -1312,19 +1377,19 @@ msgstr "" "Use '[algo]$[salt]$[hexdigest]' o use el <a href=\"password/\">formulario de " "cambio de contraseña</a>." -#: contrib/auth/models.py:132 +#: contrib/auth/models.py:133 msgid "staff status" msgstr "es staff" -#: contrib/auth/models.py:132 +#: contrib/auth/models.py:133 msgid "Designates whether the user can log into this admin site." msgstr "Indica si el usuario puede ingresar a este sitio de administración." -#: contrib/auth/models.py:133 +#: contrib/auth/models.py:134 msgid "active" msgstr "activo" -#: contrib/auth/models.py:133 +#: contrib/auth/models.py:134 msgid "" "Designates whether this user should be treated as active. Unselect this " "instead of deleting accounts." @@ -1332,11 +1397,11 @@ msgstr "" "Indica si el usuario debe ser tratado como un usuario activo. Desactive este " "campo en lugar de eliminar usuarios." -#: contrib/auth/models.py:134 +#: contrib/auth/models.py:135 msgid "superuser status" msgstr "es superusuario" -#: contrib/auth/models.py:134 +#: contrib/auth/models.py:135 msgid "" "Designates that this user has all permissions without explicitly assigning " "them." @@ -1344,15 +1409,15 @@ msgstr "" "Indica que este usuario posee todos los permisos sin que sea necesario " "asignarle los mismos en forma explícita." -#: contrib/auth/models.py:135 +#: contrib/auth/models.py:136 msgid "last login" msgstr "último ingreso" -#: contrib/auth/models.py:136 +#: contrib/auth/models.py:137 msgid "date joined" msgstr "fecha de creación" -#: contrib/auth/models.py:138 +#: contrib/auth/models.py:139 msgid "" "In addition to the permissions manually assigned, this user will also get " "all permissions granted to each group he/she is in." @@ -1360,27 +1425,28 @@ msgstr "" "Además de los permisos asignados manualmente, este usuario también poseerá " "todos los permisos de los grupos a los que pertenezca." -#: contrib/auth/models.py:139 +#: contrib/auth/models.py:140 msgid "user permissions" msgstr "permisos de usuario" -#: contrib/auth/models.py:143 +#: contrib/auth/models.py:144 contrib/comments/models.py:50 +#: contrib/comments/models.py:168 msgid "user" msgstr "usuario" -#: contrib/auth/models.py:144 +#: contrib/auth/models.py:145 msgid "users" msgstr "usuarios" -#: contrib/auth/models.py:300 +#: contrib/auth/models.py:301 msgid "message" msgstr "mensaje" -#: contrib/auth/views.py:50 +#: contrib/auth/views.py:56 msgid "Logged out" msgstr "Sesión cerrada" -#: contrib/auth/management/commands/createsuperuser.py:23 forms/fields.py:428 +#: contrib/auth/management/commands/createsuperuser.py:23 forms/fields.py:429 msgid "Enter a valid e-mail address." msgstr "Introduzca una dirección de correo electrónico válida" @@ -1392,71 +1458,86 @@ msgstr "Contenido" msgid "Metadata" msgstr "Metadatos" -#: contrib/comments/forms.py:19 +#: contrib/comments/feeds.py:13 +#, python-format +msgid "%(site_name)s comments" +msgstr "comentarios en %(site_name)s" + +#: contrib/comments/feeds.py:23 +#, python-format +msgid "Latest comments on %(site_name)s" +msgstr "Últimos comentarios en %(site_name)s." + +#: contrib/comments/forms.py:93 #: contrib/comments/templates/comments/moderation_queue.html:34 msgid "Name" msgstr "Nombre" -#: contrib/comments/forms.py:20 +#: contrib/comments/forms.py:94 msgid "Email address" msgstr "Dirección de correo electrónico" -#: contrib/comments/forms.py:22 +#: contrib/comments/forms.py:96 #: contrib/comments/templates/comments/moderation_queue.html:35 msgid "Comment" msgstr "Comentario" -#: contrib/comments/forms.py:25 -msgid "" -"If you enter anything in this field your comment will be treated as spam" -msgstr "Si introduce algo en este campo su comentario será tratado como spam" - -#: contrib/comments/forms.py:125 +#: contrib/comments/forms.py:173 #, 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] "¡Controla tu lenguaje! Aquí no admitimos la palabra %s." msgstr[1] "¡Controla tu lenguaje! Aquí no admitimos las palabras %s." -#: contrib/comments/models.py:23 +#: contrib/comments/forms.py:180 +msgid "" +"If you enter anything in this field your comment will be treated as spam" +msgstr "Si introduce algo en este campo su comentario será tratado como spam" + +#: contrib/comments/models.py:22 contrib/contenttypes/models.py:74 +msgid "content type" +msgstr "tipo de contenido" + +#: contrib/comments/models.py:24 msgid "object ID" msgstr "ID de objeto" -#: contrib/comments/models.py:50 +#: contrib/comments/models.py:52 msgid "user's name" msgstr "nombre de usuario" -#: contrib/comments/models.py:51 +#: contrib/comments/models.py:53 msgid "user's email address" msgstr "dirección de correo electrónico del usuario" -#: contrib/comments/models.py:52 +#: contrib/comments/models.py:54 msgid "user's URL" msgstr "URL del usuario" -#: contrib/comments/models.py:54 +#: contrib/comments/models.py:56 contrib/comments/models.py:76 +#: contrib/comments/models.py:169 msgid "comment" msgstr "comentario" -#: contrib/comments/models.py:57 +#: contrib/comments/models.py:59 msgid "date/time submitted" msgstr "fecha/hora de envío" -#: contrib/comments/models.py:59 +#: contrib/comments/models.py:61 msgid "is public" msgstr "es público" -#: contrib/comments/models.py:60 +#: contrib/comments/models.py:62 msgid "" "Uncheck this box to make the comment effectively disappear from the site." msgstr "" "deseleccione esta caja para lograr que el comentario desaparezca del sitio." -#: contrib/comments/models.py:62 +#: contrib/comments/models.py:64 msgid "is removed" msgstr "se ha eliminado" -#: contrib/comments/models.py:63 +#: contrib/comments/models.py:65 msgid "" "Check this box if the comment is inappropriate. A \"This comment has been " "removed\" message will be displayed instead." @@ -1464,7 +1545,11 @@ msgstr "" "Marque esta caja si el comentario es inapropiado. En su lugar se mostrará un " "mensaje \"Este comentario ha sido eliminado\"." -#: contrib/comments/models.py:115 +#: contrib/comments/models.py:77 +msgid "comments" +msgstr "comentarios" + +#: contrib/comments/models.py:119 msgid "" "This comment was posted by an authenticated user and thus the name is read-" "only." @@ -1472,7 +1557,7 @@ msgstr "" "Este comentario ha sido enviado por un usuario identificado, por lo tanto el " "nombre no puede modificarse.%(text)s" -#: contrib/comments/models.py:124 +#: contrib/comments/models.py:128 msgid "" "This comment was posted by an authenticated user and thus the email is read-" "only." @@ -1480,7 +1565,7 @@ msgstr "" "Este comentario ha sido enviado por un usuario identificado, por lo tanto la " "dirección de correo electrónico no puede modificarse.%(text)s" -#: contrib/comments/models.py:149 +#: contrib/comments/models.py:153 #, python-format msgid "" "Posted by %(user)s at %(date)s\n" @@ -1495,6 +1580,22 @@ msgstr "" "\n" "http://%(domain)s%(url)s" +#: contrib/comments/models.py:170 +msgid "flag" +msgstr "marca" + +#: contrib/comments/models.py:171 +msgid "date" +msgstr "fecha" + +#: contrib/comments/models.py:181 +msgid "comment flag" +msgstr "marca de comentario" + +#: contrib/comments/models.py:182 +msgid "comment flags" +msgstr "marcas de comentario" + #: contrib/comments/templates/comments/approve.html:4 msgid "Approve a comment" msgstr "Aprobar un comentario" @@ -1554,13 +1655,13 @@ msgstr "Marcar" msgid "Thanks for flagging" msgstr "¡Gracias por marcar!" -#: contrib/comments/templates/comments/form.html:16 -#: contrib/comments/templates/comments/preview.html:31 +#: contrib/comments/templates/comments/form.html:17 +#: contrib/comments/templates/comments/preview.html:32 msgid "Post" msgstr "Remitir" -#: contrib/comments/templates/comments/form.html:17 -#: contrib/comments/templates/comments/preview.html:32 +#: contrib/comments/templates/comments/form.html:18 +#: contrib/comments/templates/comments/preview.html:33 msgid "Preview" msgstr "Previsualización" @@ -1606,33 +1707,29 @@ msgid "Thank you for your comment" msgstr "Gracias por dejar su comentario" #: contrib/comments/templates/comments/preview.html:4 -#: contrib/comments/templates/comments/preview.html:12 +#: contrib/comments/templates/comments/preview.html:13 msgid "Preview your comment" msgstr "Ver una copia previa de su comentario" -#: contrib/comments/templates/comments/preview.html:10 +#: contrib/comments/templates/comments/preview.html:11 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/comments/templates/comments/preview.html:15 +#: contrib/comments/templates/comments/preview.html:16 msgid "Post your comment" msgstr "Enviar su comentario" -#: contrib/comments/templates/comments/preview.html:15 +#: contrib/comments/templates/comments/preview.html:16 msgid "or make changes" msgstr "o realice modificaciones" -#: contrib/contenttypes/models.py:67 +#: contrib/contenttypes/models.py:70 msgid "python model class name" msgstr "nombre de la clase python del modelo" -#: contrib/contenttypes/models.py:71 -msgid "content type" -msgstr "tipo de contenido" - -#: contrib/contenttypes/models.py:72 +#: contrib/contenttypes/models.py:75 msgid "content types" msgstr "tipos de contenido" @@ -1703,18 +1800,26 @@ msgstr "" "Lamentablemente su formulario ha caducado. Por favor continúe rellenando el " "formulario en esta página." -#: contrib/gis/forms/fields.py:14 +#: contrib/gis/forms/fields.py:17 msgid "No geometry value provided." msgstr "No se ha proporcionado un valor de geometría." -#: contrib/gis/forms/fields.py:15 +#: contrib/gis/forms/fields.py:18 msgid "Invalid geometry value." msgstr "Valor de geometría no válido." -#: contrib/gis/forms/fields.py:16 +#: contrib/gis/forms/fields.py:19 msgid "Invalid geometry type." msgstr "Tipo de geometría no válido." +#: contrib/gis/forms/fields.py:20 +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Ha ocurrido un error mientras se transformaba la geometría al SRID del campo " +"de formulario de la misma." + #: contrib/humanize/templatetags/humanize.py:19 msgid "th" msgstr "th" @@ -2037,6 +2142,83 @@ msgstr "Introduzca un RUT chileno válido. EL formato es XX.XXX.XXX-X." msgid "The Chilean RUT is not valid." msgstr "El RUT chileno no es válido." +#: contrib/localflavor/cz/cz_regions.py:8 +msgid "Prague" +msgstr "Praga" + +#: contrib/localflavor/cz/cz_regions.py:9 +msgid "Central Bohemian Region" +msgstr "región Bohemia Central" + +#: contrib/localflavor/cz/cz_regions.py:10 +msgid "South Bohemian Region" +msgstr "región Bohemian Meridional" + +#: contrib/localflavor/cz/cz_regions.py:11 +msgid "Pilsen Region" +msgstr "región Pilsen" + +#: contrib/localflavor/cz/cz_regions.py:12 +msgid "Carlsbad Region" +msgstr "región Karlovy Vary" + +#: contrib/localflavor/cz/cz_regions.py:13 +msgid "Usti Region" +msgstr "región Ústí nad Labem" + +#: contrib/localflavor/cz/cz_regions.py:14 +msgid "Liberec Region" +msgstr "región Liberec" + +#: contrib/localflavor/cz/cz_regions.py:15 +msgid "Hradec Region" +msgstr "región Hradec Králové" + +#: contrib/localflavor/cz/cz_regions.py:16 +msgid "Pardubice Region" +msgstr "región Pardubice" + +#: contrib/localflavor/cz/cz_regions.py:17 +msgid "Vysocina Region" +msgstr "región Vysočina" + +#: contrib/localflavor/cz/cz_regions.py:18 +msgid "South Moravian Region" +msgstr "región Moravia Meridional" + +#: contrib/localflavor/cz/cz_regions.py:19 +msgid "Olomouc Region" +msgstr "región Olomouc" + +#: contrib/localflavor/cz/cz_regions.py:20 +msgid "Zlin Region" +msgstr "región Zlín" + +#: contrib/localflavor/cz/cz_regions.py:21 +msgid "Moravian-Silesian Region" +msgstr "región Moravia-Silesia" + +#: contrib/localflavor/cz/forms.py:27 contrib/localflavor/sk/forms.py:30 +msgid "Enter a postal code in the format XXXXX or XXX XX." +msgstr "Introduzca un código postal en formato XXXXX o XXX XX." + +#: contrib/localflavor/cz/forms.py:47 +msgid "Enter a birth number in the format XXXXXX/XXXX or XXXXXXXXXX." +msgstr "" +"Introduzca un número de nacimiento en formato XXXXXX/XXXX o XXXXXXXXXX." + +#: contrib/localflavor/cz/forms.py:48 +msgid "Invalid optional parameter Gender, valid values are 'f' and 'm'" +msgstr "Parámetro opcional Género inválido, valores válidos son 'f' y 'm'" + +#: contrib/localflavor/cz/forms.py:49 +msgid "Enter a valid birth number." +msgstr "Introduzca un número ide nacimiento válido." + +#: contrib/localflavor/cz/forms.py:106 +msgid "Enter a valid IC number." +msgstr "Introduzca un número IC válido." + #: contrib/localflavor/de/de_states.py:5 msgid "Baden-Wuerttemberg" msgstr "Baden-Wuerttemberg" @@ -2868,19 +3050,19 @@ msgstr "" msgid "Wrong checksum for the Tax Number (NIP)." msgstr "Código de verificación de Número Impostitivo (NIP) inválido." -#: contrib/localflavor/pl/forms.py:111 -msgid "National Business Register Number (REGON) consists of 7 or 9 digits." +#: contrib/localflavor/pl/forms.py:109 +msgid "National Business Register Number (REGON) consists of 9 or 14 digits." msgstr "" -"Los Números Nacionales de Registro de Negocios (REGON) constan de 7 o 9 " +"Los Números Nacionales de Registro de Negocios (REGON) constan de 9 o 14 " "dígitos." -#: contrib/localflavor/pl/forms.py:112 +#: contrib/localflavor/pl/forms.py:110 msgid "Wrong checksum for the National Business Register Number (REGON)." msgstr "" "Código de verificación de Número Nacional de Registro de negocios (REGON) " "inválido." -#: contrib/localflavor/pl/forms.py:155 +#: contrib/localflavor/pl/forms.py:148 msgid "Enter a postal code in the format XX-XXX." msgstr "Introduzca un código postal en formato XX-XXX." @@ -2968,10 +3150,6 @@ msgstr "Los números telefónicos deben respetar el formato XXXX-XXXXXX." msgid "Enter a valid postal code in the format XXXXXX" msgstr "Introduzca un código postal válido en formato XXXXXX" -#: contrib/localflavor/sk/forms.py:30 -msgid "Enter a postal code in the format XXXXX or XXX XX." -msgstr "Introduzca un código postal en formato XXXXX o XXX XX." - #: contrib/localflavor/sk/sk_districts.py:8 msgid "Banska Bystrica" msgstr "Banska Bystrica" @@ -3290,35 +3468,35 @@ msgstr "Zilina" #: contrib/localflavor/sk/sk_regions.py:8 msgid "Banska Bystrica region" -msgstr "region Banska Bystrica" +msgstr "región Banska Bystrica" #: contrib/localflavor/sk/sk_regions.py:9 msgid "Bratislava region" -msgstr "region Bratislava" +msgstr "región Bratislava" #: contrib/localflavor/sk/sk_regions.py:10 msgid "Kosice region" -msgstr "region Kosice" +msgstr "región Kosice" #: contrib/localflavor/sk/sk_regions.py:11 msgid "Nitra region" -msgstr "region Nitra" +msgstr "región Nitra" #: contrib/localflavor/sk/sk_regions.py:12 msgid "Presov region" -msgstr "region Presov" +msgstr "región Presov" #: contrib/localflavor/sk/sk_regions.py:13 msgid "Trencin region" -msgstr "region Trencin" +msgstr "región Trencin" #: contrib/localflavor/sk/sk_regions.py:14 msgid "Trnava region" -msgstr "region Trnava" +msgstr "región Trnava" #: contrib/localflavor/sk/sk_regions.py:15 msgid "Zilina region" -msgstr "region Zilina" +msgstr "región Zilina" #: contrib/localflavor/uk/forms.py:21 msgid "Enter a valid postcode." @@ -3720,57 +3898,61 @@ msgstr "nombre para visualizar" msgid "sites" msgstr "sitios" -#: db/models/fields/__init__.py:348 db/models/fields/__init__.py:683 +#: db/models/fields/__init__.py:356 db/models/fields/__init__.py:710 msgid "This value must be an integer." msgstr "Este valor debe ser un número entero." -#: db/models/fields/__init__.py:379 +#: db/models/fields/__init__.py:388 msgid "This value must be either True or False." msgstr "Este valor debe ser True o False." -#: db/models/fields/__init__.py:412 +#: db/models/fields/__init__.py:427 msgid "This field cannot be null." msgstr "Este campo no puede ser nulo." -#: db/models/fields/__init__.py:428 +#: db/models/fields/__init__.py:443 msgid "Enter only digits separated by commas." msgstr "Introduzca sólo dígitos separados por comas." -#: db/models/fields/__init__.py:459 +#: db/models/fields/__init__.py:474 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:468 +#: db/models/fields/__init__.py:483 #, python-format msgid "Invalid date: %s" msgstr "Fecha no válida: %s" -#: db/models/fields/__init__.py:532 db/models/fields/__init__.py:550 +#: db/models/fields/__init__.py:547 db/models/fields/__init__.py:565 msgid "Enter a valid date/time in YYYY-MM-DD HH:MM[:ss[.uuuuuu]] format." msgstr "" "Introduzca un valor de fecha/hora válido en formato AAAA-MM-DD HH:MM[:ss[." "uuuuuu]]." -#: db/models/fields/__init__.py:586 +#: db/models/fields/__init__.py:601 msgid "This value must be a decimal number." msgstr "Este valor debe ser un número decimal." -#: db/models/fields/__init__.py:719 +#: db/models/fields/__init__.py:686 +msgid "This value must be a float." +msgstr "Este valor debe ser un valor en representación de punto flotante." + +#: db/models/fields/__init__.py:746 msgid "This value must be either None, True or False." msgstr "Este valor debe ser None, True o False." -#: db/models/fields/__init__.py:817 db/models/fields/__init__.py:831 +#: db/models/fields/__init__.py:849 db/models/fields/__init__.py:863 msgid "Enter a valid time in HH:MM[:ss[.uuuuuu]] format." msgstr "Introduzca un valor de hora válido en formato HH:MM[:ss[.uuuuuu]]." -#: db/models/fields/related.py:761 +#: db/models/fields/related.py:792 msgid "" "Hold down \"Control\", or \"Command\" on a Mac, to select more than one." msgstr "" "Mantenga presionada \"Control\" (\"Command\" en una Mac) para seleccionar " "más de uno." -#: db/models/fields/related.py:838 +#: db/models/fields/related.py:870 #, python-format msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid." msgid_plural "" @@ -3837,32 +4019,40 @@ msgstr "Asegúrese de que no existan mas de %s lugares decimales." msgid "Ensure that there are no more than %s digits before the decimal point." msgstr "Asegúrese de que no existan mas de %s dígitos antes del punto decimal." -#: forms/fields.py:287 forms/fields.py:849 +#: forms/fields.py:288 forms/fields.py:863 msgid "Enter a valid date." msgstr "Introduzca una fecha válida." -#: forms/fields.py:321 forms/fields.py:850 +#: forms/fields.py:322 forms/fields.py:864 msgid "Enter a valid time." msgstr "Introduzca un valor de hora válido." -#: forms/fields.py:360 +#: forms/fields.py:361 msgid "Enter a valid date/time." msgstr "Introduzca un valor de fecha/hora válido." -#: forms/fields.py:446 +#: forms/fields.py:447 msgid "No file was submitted. Check the encoding type on the form." msgstr "" "No se envió un archivo. Verifique el tipo de codificación en el formulario." -#: forms/fields.py:447 +#: forms/fields.py:448 msgid "No file was submitted." msgstr "No se envió ningún archivo." -#: forms/fields.py:448 +#: forms/fields.py:449 msgid "The submitted file is empty." msgstr "El archivo enviado está vacío." -#: forms/fields.py:477 +#: forms/fields.py:450 +#, python-format +msgid "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr "" +"Asegúrese de que este nombre de archivo tenga como máximo %(max)d caracteres " +"(tiene %(length)d)." + +#: forms/fields.py:483 msgid "" "Upload a valid image. The file you uploaded was either not an image or a " "corrupted image." @@ -3870,107 +4060,141 @@ msgstr "" "Envíe una imagen válida. El archivo que ha enviado no era una imagen o se " "trataba de una imagen corrupta." -#: forms/fields.py:538 +#: forms/fields.py:544 msgid "Enter a valid URL." msgstr "Introduzca una URL válida." -#: forms/fields.py:539 +#: forms/fields.py:545 msgid "This URL appears to be a broken link." msgstr "La URL parece ser un enlace roto." -#: forms/fields.py:618 forms/fields.py:696 +#: forms/fields.py:625 forms/fields.py:703 #, python-format msgid "Select a valid choice. %(value)s is not one of the available choices." msgstr "" "Seleccione una opción válida. %(value)s no es una de las opciones " "disponibles." -#: forms/fields.py:697 forms/fields.py:758 forms/models.py:720 +#: forms/fields.py:704 forms/fields.py:765 forms/models.py:991 msgid "Enter a list of values." msgstr "Introduzca una lista de valores." -#: forms/fields.py:878 +#: forms/fields.py:892 msgid "Enter a valid IPv4 address." msgstr "Introduzca una dirección IPv4 válida" -#: forms/fields.py:888 +#: forms/fields.py:902 msgid "" "Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens." msgstr "Introduzca un 'slug' válido consistente en letras, números o guiones." -#: forms/formsets.py:242 forms/formsets.py:244 +#: forms/formsets.py:271 forms/formsets.py:273 msgid "Order" msgstr "Ordenar" -#: forms/models.py:281 forms/models.py:290 +#: forms/models.py:367 +#, python-format +msgid "%(field_name)s must be unique for %(date_field)s %(lookup)s." +msgstr "" +"%(field_name)s debe ser único/a para un %(lookup)s %(date_field)s " +"determinado." + +#: forms/models.py:381 forms/models.py:389 #, python-format msgid "%(model_name)s with this %(field_label)s already exists." msgstr "Ya existe un/a %(model_name)s con este/a %(field_label)s." -#: forms/models.py:587 +#: forms/models.py:581 +#, fuzzy, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Por favor, corrija el siguiente error." + +#: forms/models.py:585 +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" + +#: forms/models.py:591 +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" + +#: forms/models.py:599 +#, fuzzy +msgid "Please correct the duplicate values below." +msgstr "Por favor, corrija el siguiente error." + +#: forms/models.py:855 msgid "The inline foreign key did not match the parent instance primary key." msgstr "" "La clave foránea del modelo inline no coincide con la de la instancia padre." -#: forms/models.py:650 +#: forms/models.py:918 msgid "Select a valid choice. That choice is not one of the available choices." msgstr "" "Seleccione una opción válida. Esa opción no es una de las opciones " "disponibles." -#: forms/models.py:721 +#: forms/models.py:992 #, python-format msgid "Select a valid choice. %s is not one of the available choices." msgstr "" "Seleccione una opción válida. %s no es una de las opciones disponibles." -#: template/defaultfilters.py:741 +#: forms/models.py:994 +#, python-format +msgid "\"%s\" is not a valid value for a primary key." +msgstr "\"%s\" no es un valor válido para una clave primaria." + +#: template/defaultfilters.py:767 msgid "yes,no,maybe" msgstr "si,no,talvez" -#: template/defaultfilters.py:772 +#: template/defaultfilters.py:798 #, python-format msgid "%(size)d byte" msgid_plural "%(size)d bytes" msgstr[0] "%(size)d byte" msgstr[1] "%(size)d bytes" -#: template/defaultfilters.py:774 +#: template/defaultfilters.py:800 #, python-format msgid "%.1f KB" msgstr "%.1f KB" -#: template/defaultfilters.py:776 +#: template/defaultfilters.py:802 #, python-format msgid "%.1f MB" msgstr "%.1f MB" -#: template/defaultfilters.py:777 +#: template/defaultfilters.py:803 #, python-format msgid "%.1f GB" msgstr "%.1f GB" -#: utils/dateformat.py:41 +#: utils/dateformat.py:42 msgid "p.m." msgstr "p.m." -#: utils/dateformat.py:42 +#: utils/dateformat.py:43 msgid "a.m." msgstr "a.m." -#: utils/dateformat.py:47 +#: utils/dateformat.py:48 msgid "PM" msgstr "PM" -#: utils/dateformat.py:48 +#: utils/dateformat.py:49 msgid "AM" msgstr "AM" -#: utils/dateformat.py:97 +#: utils/dateformat.py:98 msgid "midnight" msgstr "medianoche" -#: utils/dateformat.py:99 +#: utils/dateformat.py:100 msgid "noon" msgstr "mediodía" @@ -4194,33 +4418,33 @@ msgid_plural "minutes" msgstr[0] "minuto" msgstr[1] "minutos" -#: utils/timesince.py:43 +#: utils/timesince.py:45 msgid "minutes" msgstr "minutos" -#: utils/timesince.py:48 +#: utils/timesince.py:50 #, python-format msgid "%(number)d %(type)s" msgstr "%(number)d %(type)s" -#: utils/timesince.py:54 +#: utils/timesince.py:56 #, python-format msgid ", %(number)d %(type)s" msgstr ", %(number)d %(type)s" -#: utils/translation/trans_real.py:403 +#: utils/translation/trans_real.py:399 msgid "DATE_FORMAT" msgstr "j N Y" -#: utils/translation/trans_real.py:405 +#: utils/translation/trans_real.py:401 msgid "TIME_FORMAT" msgstr "P" -#: utils/translation/trans_real.py:421 +#: utils/translation/trans_real.py:417 msgid "YEAR_MONTH_FORMAT" msgstr "F Y" -#: utils/translation/trans_real.py:422 +#: utils/translation/trans_real.py:418 msgid "MONTH_DAY_FORMAT" msgstr "j \\de F" diff --git a/django/contrib/gis/db/models/sql/where.py b/django/contrib/gis/db/models/sql/where.py index 838889fbad..105cbfbec5 100644 --- a/django/contrib/gis/db/models/sql/where.py +++ b/django/contrib/gis/db/models/sql/where.py @@ -35,7 +35,7 @@ class GeoWhereNode(WhereNode): return super(WhereNode, self).add(data, connector) obj, lookup_type, value = data - alias, col, field = obj.alias, obj.col, obj.field + col, field = obj.col, obj.field if not hasattr(field, "geom_type"): # Not a geographic field, so call `WhereNode.add`. @@ -76,7 +76,7 @@ class GeoWhereNode(WhereNode): # the `get_geo_where_clause` to construct the appropriate # spatial SQL when `make_atom` is called. annotation = GeoAnnotation(field, value, where) - return super(WhereNode, self).add(((alias, col, field.db_type()), lookup_type, annotation, params), connector) + return super(WhereNode, self).add(((obj.alias, col, field.db_type()), lookup_type, annotation, params), connector) def make_atom(self, child, qn): obj, lookup_type, value_annot, params = child diff --git a/django/contrib/gis/maps/google/gmap.py b/django/contrib/gis/maps/google/gmap.py index dd4f67bc52..de8f75c5a0 100644 --- a/django/contrib/gis/maps/google/gmap.py +++ b/django/contrib/gis/maps/google/gmap.py @@ -143,7 +143,7 @@ class GoogleMap(object): @property def icons(self): "Returns a sequence of GIcon objects in this map." - return [marker.icon for marker in self.markers if marker.icon] + return set([marker.icon for marker in self.markers if marker.icon]) class GoogleMapSet(GoogleMap): @@ -221,6 +221,6 @@ class GoogleMapSet(GoogleMap): @property def icons(self): "Returns a sequence of all icons in each map of the set." - icons = [] - for map in self.maps: icons.extend(map.icons) + icons = set() + for map in self.maps: icons |= map.icons return icons diff --git a/django/contrib/gis/maps/google/overlays.py b/django/contrib/gis/maps/google/overlays.py index 4f1247d0a4..c2ebb3c992 100644 --- a/django/contrib/gis/maps/google/overlays.py +++ b/django/contrib/gis/maps/google/overlays.py @@ -231,6 +231,14 @@ class GIcon(object): self.iconanchor = iconanchor self.infowindowanchor = infowindowanchor + def __cmp__(self, other): + return cmp(self.varname, other.varname) + + def __hash__(self): + # XOR with hash of GIcon type so that hash('varname') won't + # equal hash(GIcon('varname')). + return hash(self.__class__) ^ hash(self.varname) + class GMarker(GOverlayBase): """ A Python wrapper for the Google GMarker object. For more information diff --git a/django/contrib/gis/tests/relatedapp/models.py b/django/contrib/gis/tests/relatedapp/models.py index d7dd6bbfd2..1125d7fb85 100644 --- a/django/contrib/gis/tests/relatedapp/models.py +++ b/django/contrib/gis/tests/relatedapp/models.py @@ -32,3 +32,13 @@ class Parcel(models.Model): border2 = models.PolygonField(srid=2276) objects = models.GeoManager() def __unicode__(self): return self.name + +# These use the GeoManager but do not have any geographic fields. +class Author(models.Model): + name = models.CharField(max_length=100) + objects = models.GeoManager() + +class Book(models.Model): + title = models.CharField(max_length=100) + author = models.ForeignKey(Author, related_name='books') + objects = models.GeoManager() diff --git a/django/contrib/gis/tests/relatedapp/tests.py b/django/contrib/gis/tests/relatedapp/tests.py index 77f6c73bb6..8c4f83b15a 100644 --- a/django/contrib/gis/tests/relatedapp/tests.py +++ b/django/contrib/gis/tests/relatedapp/tests.py @@ -1,10 +1,10 @@ import os, unittest from django.contrib.gis.geos import * from django.contrib.gis.db.backend import SpatialBackend -from django.contrib.gis.db.models import F, Extent, Union +from django.contrib.gis.db.models import Count, Extent, F, Union from django.contrib.gis.tests.utils import no_mysql, no_oracle, no_spatialite from django.conf import settings -from models import City, Location, DirectoryEntry, Parcel +from models import City, Location, DirectoryEntry, Parcel, Book, Author cities = (('Aurora', 'TX', -97.516111, 33.058333), ('Roswell', 'NM', -104.528056, 33.387222), @@ -196,8 +196,8 @@ class RelatedGeoModelTest(unittest.TestCase): # ID values do not match their City ID values. loc1 = Location.objects.create(point='POINT (-95.363151 29.763374)') loc2 = Location.objects.create(point='POINT (-96.801611 32.782057)') - dallas = City.objects.create(name='Dallas', location=loc2) - houston = City.objects.create(name='Houston', location=loc1) + dallas = City.objects.create(name='Dallas', state='TX', location=loc2) + houston = City.objects.create(name='Houston', state='TX', location=loc1) # The expected ID values -- notice the last two location IDs # are out of order. We want to make sure that the related @@ -231,6 +231,32 @@ class RelatedGeoModelTest(unittest.TestCase): q = pickle.loads(q_str) self.assertEqual(GeoQuery, q.__class__) + def test12_count(self): + "Testing `Count` aggregate use with the `GeoManager`. See #11087." + # Creating a new City, 'Fort Worth', that uses the same location + # as Dallas. + dallas = City.objects.get(name='Dallas') + ftworth = City.objects.create(name='Fort Worth', state='TX', location=dallas.location) + + # Count annotation should be 2 for the Dallas location now. + loc = Location.objects.annotate(num_cities=Count('city')).get(id=dallas.location.id) + self.assertEqual(2, loc.num_cities) + + # Creating some data for the Book/Author non-geo models that + # use GeoManager. See #11087. + tp = Author.objects.create(name='Trevor Paglen') + Book.objects.create(title='Torture Taxi', author=tp) + Book.objects.create(title='I Could Tell You But Then You Would Have to be Destroyed by Me', author=tp) + Book.objects.create(title='Blank Spots on the Map', author=tp) + wp = Author.objects.create(name='William Patry') + Book.objects.create(title='Patry on Copyright', author=wp) + + # Should only be one author (Trevor Paglen) returned by this query, and + # the annotation should have 3 for the number of books. + qs = Author.objects.annotate(num_books=Count('books')).filter(num_books__gt=1) + self.assertEqual(1, len(qs)) + self.assertEqual(3, qs[0].num_books) + # TODO: Related tests for KML, GML, and distance lookups. def suite(): diff --git a/django/contrib/gis/utils/ogrinspect.py b/django/contrib/gis/utils/ogrinspect.py index c0c3c40a69..145bd221bb 100644 --- a/django/contrib/gis/utils/ogrinspect.py +++ b/django/contrib/gis/utils/ogrinspect.py @@ -12,12 +12,12 @@ from django.contrib.gis.gdal.field import OFTDate, OFTDateTime, OFTInteger, OFTR def mapping(data_source, geom_name='geom', layer_key=0, multi_geom=False): """ - Given a DataSource, generates a dictionary that may be used + Given a DataSource, generates a dictionary that may be used for invoking the LayerMapping utility. Keyword Arguments: `geom_name` => The name of the geometry field to use for the model. - + `layer_key` => The key for specifying which layer in the DataSource to use; defaults to 0 (the first layer). May be an integer index or a string identifier for the layer. @@ -31,7 +31,7 @@ def mapping(data_source, geom_name='geom', layer_key=0, multi_geom=False): pass else: raise TypeError('Data source parameter must be a string or a DataSource object.') - + # Creating the dictionary. _mapping = {} @@ -52,32 +52,32 @@ def ogrinspect(*args, **kwargs): model name this function will generate a GeoDjango model. Usage: - + >>> from django.contrib.gis.utils import ogrinspect >>> ogrinspect('/path/to/shapefile.shp','NewModel') - + ...will print model definition to stout - + or put this in a python script and use to redirect the output to a new model like: - + $ python generate_model.py > myapp/models.py - - # generate_model.py + + # generate_model.py from django.contrib.gis.utils import ogrinspect shp_file = 'data/mapping_hacks/world_borders.shp' model_name = 'WorldBorders' print ogrinspect(shp_file, model_name, multi_geom=True, srid=4326, geom_name='shapes', blank=True) - + Required Arguments `datasource` => string or DataSource object to file pointer - + `model name` => string of name of new model class to create - + Optional Keyword Arguments - `geom_name` => For specifying the model name for the Geometry Field. + `geom_name` => For specifying the model name for the Geometry Field. Otherwise will default to `geom` `layer_key` => The key for specifying which layer in the DataSource to use; @@ -86,24 +86,24 @@ def ogrinspect(*args, **kwargs): `srid` => The SRID to use for the Geometry Field. If it can be determined, the SRID of the datasource is used. - + `multi_geom` => Boolean (default: False) - specify as multigeometry. - + `name_field` => String - specifies a field name to return for the `__unicode__` function (which will be generated if specified). - - `imports` => Boolean (default: True) - set to False to omit the - `from django.contrib.gis.db import models` code from the + + `imports` => Boolean (default: True) - set to False to omit the + `from django.contrib.gis.db import models` code from the autogenerated models thus avoiding duplicated imports when building more than one model by batching ogrinspect() - + `decimal` => Boolean or sequence (default: False). When set to True all generated model fields corresponding to the `OFTReal` type will be `DecimalField` instead of `FloatField`. A sequence of specific field names to generate as `DecimalField` may also be used. `blank` => Boolean or sequence (default: False). When set to True all - generated model fields will have `blank=True`. If the user wants to + generated model fields will have `blank=True`. If the user wants to give specific fields to have blank, then a list/tuple of OGR field names may be used. @@ -111,13 +111,13 @@ def ogrinspect(*args, **kwargs): model fields will have `null=True`. If the user wants to specify give specific fields to have null, then a list/tuple of OGR field names may be used. - + Note: This routine calls the _ogrinspect() helper to do the heavy lifting. """ return '\n'.join(s for s in _ogrinspect(*args, **kwargs)) def _ogrinspect(data_source, model_name, geom_name='geom', layer_key=0, srid=None, - multi_geom=False, name_field=None, imports=True, + multi_geom=False, name_field=None, imports=True, decimal=False, blank=False, null=False): """ Helper routine for `ogrinspect` that generates GeoDjango models corresponding @@ -140,7 +140,7 @@ def _ogrinspect(data_source, model_name, geom_name='geom', layer_key=0, srid=Non # keyword arguments. def process_kwarg(kwarg): if isinstance(kwarg, (list, tuple)): - return [s.lower() for s in kwarg] + return [s.lower() for s in kwarg] elif kwarg: return [s.lower() for s in ogr_fields] else: @@ -164,18 +164,18 @@ def _ogrinspect(data_source, model_name, geom_name='geom', layer_key=0, srid=Non yield '' yield 'class %s(models.Model):' % model_name - + for field_name, width, precision, field_type in izip(ogr_fields, layer.field_widths, layer.field_precisions, layer.field_types): # The model field name. mfield = field_name.lower() if mfield[-1:] == '_': mfield += 'field' - + # Getting the keyword args string. kwargs_str = get_kwargs_str(field_name) if field_type is OFTReal: # By default OFTReals are mapped to `FloatField`, however, they - # may also be mapped to `DecimalField` if specified in the + # may also be mapped to `DecimalField` if specified in the # `decimal` keyword. if field_name.lower() in decimal_fields: yield ' %s = models.DecimalField(max_digits=%d, decimal_places=%d%s)' % (mfield, width, precision, kwargs_str) @@ -192,8 +192,8 @@ def _ogrinspect(data_source, model_name, geom_name='geom', layer_key=0, srid=Non elif field_type is OFTDate: yield ' %s = models.TimeField(%s)' % (mfield, kwargs_str[2:]) else: - raise TypeError('Unknown field type %s in %s' % (fld_type, mfield)) - + raise TypeError('Unknown field type %s in %s' % (field_type, mfield)) + # TODO: Autodetection of multigeometry types (see #7218). gtype = layer.geom_type if multi_geom and gtype.num in (1, 2, 3): diff --git a/django/db/models/fields/files.py b/django/db/models/fields/files.py index 61a903e36c..aab4f3789f 100644 --- a/django/db/models/fields/files.py +++ b/django/db/models/fields/files.py @@ -142,13 +142,13 @@ class FileDescriptor(object): """ The descriptor for the file attribute on the model instance. Returns a FieldFile when accessed so you can do stuff like:: - + >>> instance.file.size - + Assigns a file object on assignment so you can do:: - + >>> instance.file = File(...) - + """ def __init__(self, field): self.field = field @@ -156,9 +156,9 @@ class FileDescriptor(object): def __get__(self, instance=None, owner=None): if instance is None: raise AttributeError( - "The '%s' attribute can only be accessed from %s instances." + "The '%s' attribute can only be accessed from %s instances." % (self.field.name, owner.__name__)) - + # This is slightly complicated, so worth an explanation. # instance.file`needs to ultimately return some instance of `File`, # probably a subclass. Additionally, this returned object needs to have @@ -168,8 +168,8 @@ class FileDescriptor(object): # peek below you can see that we're not. So depending on the current # value of the field we have to dynamically construct some sort of # "thing" to return. - - # The instance dict contains whatever was originally assigned + + # The instance dict contains whatever was originally assigned # in __set__. file = instance.__dict__[self.field.name] @@ -186,14 +186,14 @@ class FileDescriptor(object): # Other types of files may be assigned as well, but they need to have # the FieldFile interface added to the. Thus, we wrap any other type of - # File inside a FieldFile (well, the field's attr_class, which is + # File inside a FieldFile (well, the field's attr_class, which is # usually FieldFile). elif isinstance(file, File) and not isinstance(file, FieldFile): file_copy = self.field.attr_class(instance, self.field, file.name) file_copy.file = file file_copy._committed = False instance.__dict__[self.field.name] = file_copy - + # Finally, because of the (some would say boneheaded) way pickle works, # the underlying FieldFile might not actually itself have an associated # file. So we need to reset the details of the FieldFile in those cases. @@ -201,7 +201,7 @@ class FileDescriptor(object): file.instance = instance file.field = self.field file.storage = self.field.storage - + # That was fun, wasn't it? return instance.__dict__[self.field.name] @@ -212,7 +212,7 @@ class FileField(Field): # The class to wrap instance attributes in. Accessing the file object off # the instance will always return an instance of attr_class. attr_class = FieldFile - + # The descriptor to use for accessing the attribute off of the class. descriptor_class = FileDescriptor @@ -300,40 +300,20 @@ class ImageFileDescriptor(FileDescriptor): assigning the width/height to the width_field/height_field, if appropriate. """ def __set__(self, instance, value): + previous_file = instance.__dict__.get(self.field.name) super(ImageFileDescriptor, self).__set__(instance, value) - - # The rest of this method deals with width/height fields, so we can - # bail early if neither is used. - if not self.field.width_field and not self.field.height_field: - return - - # We need to call the descriptor's __get__ to coerce this assigned - # value into an instance of the right type (an ImageFieldFile, in this - # case). - value = self.__get__(instance) - - if not value: - return - - # Get the image dimensions, making sure to leave the file in the same - # state (opened or closed) that we got it in. However, we *don't* rewind - # the file pointer if the file is already open. This is in keeping with - # most Python standard library file operations that leave it up to the - # user code to reset file pointers after operations that move it. - from django.core.files.images import get_image_dimensions - close = value.closed - value.open() - try: - width, height = get_image_dimensions(value) - finally: - if close: - value.close() - - # Update the width and height fields - if self.field.width_field: - setattr(value.instance, self.field.width_field, width) - if self.field.height_field: - setattr(value.instance, self.field.height_field, height) + + # To prevent recalculating image dimensions when we are instantiating + # an object from the database (bug #11084), only update dimensions if + # the field had a value before this assignment. Since the default + # value for FileField subclasses is an instance of field.attr_class, + # previous_file will only be None when we are called from + # Model.__init__(). The ImageField.update_dimension_fields method + # hooked up to the post_init signal handles the Model.__init__() cases. + # Assignment happening outside of Model.__init__() will trigger the + # update right here. + if previous_file is not None: + self.field.update_dimension_fields(instance, force=True) class ImageFieldFile(ImageFile, FieldFile): def delete(self, save=True): @@ -350,6 +330,69 @@ class ImageField(FileField): self.width_field, self.height_field = width_field, height_field FileField.__init__(self, verbose_name, name, **kwargs) + def contribute_to_class(self, cls, name): + super(ImageField, self).contribute_to_class(cls, name) + # Attach update_dimension_fields so that dimension fields declared + # after their corresponding image field don't stay cleared by + # Model.__init__, see bug #11196. + signals.post_init.connect(self.update_dimension_fields, sender=cls) + + def update_dimension_fields(self, instance, force=False, *args, **kwargs): + """ + Updates field's width and height fields, if defined. + + This method is hooked up to model's post_init signal to update + dimensions after instantiating a model instance. However, dimensions + won't be updated if the dimensions fields are already populated. This + avoids unnecessary recalculation when loading an object from the + database. + + Dimensions can be forced to update with force=True, which is how + ImageFileDescriptor.__set__ calls this method. + """ + # Nothing to update if the field doesn't have have dimension fields. + has_dimension_fields = self.width_field or self.height_field + if not has_dimension_fields: + return + + # getattr will call the ImageFileDescriptor's __get__ method, which + # coerces the assigned value into an instance of self.attr_class + # (ImageFieldFile in this case). + file = getattr(instance, self.attname) + + # Nothing to update if we have no file and not being forced to update. + if not file and not force: + return + + dimension_fields_filled = not( + (self.width_field and not getattr(instance, self.width_field)) + or (self.height_field and not getattr(instance, self.height_field)) + ) + # When both dimension fields have values, we are most likely loading + # data from the database or updating an image field that already had + # an image stored. In the first case, we don't want to update the + # dimension fields because we are already getting their values from the + # database. In the second case, we do want to update the dimensions + # fields and will skip this return because force will be True since we + # were called from ImageFileDescriptor.__set__. + if dimension_fields_filled and not force: + return + + # file should be an instance of ImageFieldFile or should be None. + if file: + width = file.width + height = file.height + else: + # No file, so clear dimensions fields. + width = None + height = None + + # Update the width and height fields. + if self.width_field: + setattr(instance, self.width_field, width) + if self.height_field: + setattr(instance, self.height_field, height) + def formfield(self, **kwargs): defaults = {'form_class': forms.ImageField} defaults.update(kwargs) diff --git a/django/db/models/query.py b/django/db/models/query.py index 6a8d7d5e64..0d35b0ba16 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -355,10 +355,11 @@ class QuerySet(object): # Delete objects in chunks to prevent the list of related objects from # becoming too long. + seen_objs = None while 1: # Collect all the objects to be deleted in this chunk, and all the # objects that are related to the objects that are to be deleted. - seen_objs = CollectedObjects() + seen_objs = CollectedObjects(seen_objs) for object in del_query[:CHUNK_SIZE]: object._collect_sub_objects(seen_objs) diff --git a/django/db/models/query_utils.py b/django/db/models/query_utils.py index 7a5ad919a1..6a6b69013f 100644 --- a/django/db/models/query_utils.py +++ b/django/db/models/query_utils.py @@ -32,11 +32,21 @@ class CollectedObjects(object): This is used for the database object deletion routines so that we can calculate the 'leaf' objects which should be deleted first. + + previously_seen is an optional argument. It must be a CollectedObjects + instance itself; any previously_seen collected object will be blocked from + being added to this instance. """ - def __init__(self): + def __init__(self, previously_seen=None): self.data = {} self.children = {} + if previously_seen: + self.blocked = previously_seen.blocked + for cls, seen in previously_seen.data.items(): + self.blocked.setdefault(cls, SortedDict()).update(seen) + else: + self.blocked = {} def add(self, model, pk, obj, parent_model, nullable=False): """ @@ -53,6 +63,9 @@ class CollectedObjects(object): Returns True if the item already existed in the structure and False otherwise. """ + if pk in self.blocked.get(model, {}): + return True + d = self.data.setdefault(model, SortedDict()) retval = pk in d d[pk] = obj diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index 394e30ba97..d290d60e63 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -689,7 +689,7 @@ class BaseQuery(object): If 'with_aliases' is true, any column names that are duplicated (without the table names) are given unique aliases. This is needed in - some cases to avoid ambiguitity with nested queries. + some cases to avoid ambiguity with nested queries. """ qn = self.quote_name_unless_alias qn2 = self.connection.ops.quote_name @@ -1303,7 +1303,7 @@ class BaseQuery(object): opts = self.model._meta root_alias = self.tables[0] seen = {None: root_alias} - + # Skip all proxy to the root proxied model proxied_model = get_proxied_model(opts) @@ -1732,7 +1732,7 @@ class BaseQuery(object): raise MultiJoin(pos + 1) if model: # The field lives on a base class of the current model. - # Skip the chain of proxy to the concrete proxied model + # Skip the chain of proxy to the concrete proxied model proxied_model = get_proxied_model(opts) for int_model in opts.get_base_chain(model): @@ -2362,7 +2362,7 @@ class BaseQuery(object): return cursor if result_type == SINGLE: if self.ordering_aliases: - return cursor.fetchone()[:-len(results.ordering_aliases)] + return cursor.fetchone()[:-len(self.ordering_aliases)] return cursor.fetchone() # The MULTI case. diff --git a/django/forms/models.py b/django/forms/models.py index f2ce48d277..d48f33a606 100644 --- a/django/forms/models.py +++ b/django/forms/models.py @@ -451,7 +451,7 @@ class BaseModelFormSet(BaseFormSet): else: return ugettext("Please correct the duplicate data for %(field)s, " "which must be unique.") % { - "field": get_text_list(unique_check, _("and")), + "field": get_text_list(unique_check, unicode(_("and"))), } def get_date_error_message(self, date_check): |
