aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AUTHORS17
-rw-r--r--README14
-rw-r--r--docs/source/devel/migrations.rst62
-rw-r--r--docs/source/index.rst3
-rw-r--r--docs/source/pluginwriter/api.rst274
-rw-r--r--docs/source/pluginwriter/database.rst9
-rw-r--r--docs/source/pluginwriter/media_type_hooks.rst38
-rw-r--r--docs/source/pluginwriter/quickstart.rst6
-rw-r--r--docs/source/pluginwriter/tests.rst64
-rw-r--r--docs/source/siteadmin/deploying.rst44
-rw-r--r--docs/source/siteadmin/media-types.rst52
-rw-r--r--docs/source/siteadmin/production-deployments.rst64
-rw-r--r--docs/source/siteadmin/relnotes.rst78
-rw-r--r--docs/source/siteadmin/theming.rst2
-rw-r--r--mediagoblin.ini14
-rw-r--r--mediagoblin/_version.py2
-rw-r--r--mediagoblin/app.py21
-rw-r--r--mediagoblin/auth/__init__.py29
-rw-r--r--mediagoblin/auth/forms.py58
-rw-r--r--mediagoblin/auth/tools.py210
-rw-r--r--mediagoblin/auth/views.py202
-rw-r--r--mediagoblin/config_spec.ini16
-rw-r--r--mediagoblin/db/base.py12
-rw-r--r--mediagoblin/db/migration_tools.py3
-rw-r--r--mediagoblin/db/migrations.py94
-rw-r--r--mediagoblin/db/mixin.py85
-rw-r--r--mediagoblin/db/models.py119
-rw-r--r--mediagoblin/db/models_v0.py23
-rw-r--r--mediagoblin/db/open.py4
-rw-r--r--mediagoblin/db/util.py2
-rw-r--r--mediagoblin/decorators.py57
-rw-r--r--mediagoblin/edit/forms.py36
-rw-r--r--mediagoblin/edit/routing.py4
-rw-r--r--mediagoblin/edit/views.py179
-rw-r--r--mediagoblin/gmg_commands/__init__.py14
-rw-r--r--mediagoblin/gmg_commands/assetlink.py151
-rw-r--r--mediagoblin/gmg_commands/dbupdate.py30
-rw-r--r--mediagoblin/gmg_commands/import_export.py4
-rw-r--r--mediagoblin/gmg_commands/theme.py122
-rw-r--r--mediagoblin/gmg_commands/users.py18
-rw-r--r--mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.mobin24638 -> 28177 bytes
-rw-r--r--mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.po700
-rw-r--r--mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.mobin24163 -> 25199 bytes
-rw-r--r--mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.po417
-rw-r--r--mediagoblin/i18n/da/LC_MESSAGES/mediagoblin.mobin23311 -> 24330 bytes
-rw-r--r--mediagoblin/i18n/da/LC_MESSAGES/mediagoblin.po413
-rw-r--r--mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.mobin24819 -> 25811 bytes
-rw-r--r--mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.po441
-rw-r--r--mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po417
-rw-r--r--mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.mobin24144 -> 25211 bytes
-rw-r--r--mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.po421
-rw-r--r--mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.mobin24884 -> 25994 bytes
-rw-r--r--mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.po437
-rw-r--r--mediagoblin/i18n/fa/LC_MESSAGES/mediagoblin.mobin24126 -> 25146 bytes
-rw-r--r--mediagoblin/i18n/fa/LC_MESSAGES/mediagoblin.po409
-rw-r--r--mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.mobin25195 -> 26152 bytes
-rw-r--r--mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.po429
-rw-r--r--mediagoblin/i18n/he/LC_MESSAGES/mediagoblin.mobin25897 -> 27529 bytes
-rw-r--r--mediagoblin/i18n/he/LC_MESSAGES/mediagoblin.po476
-rw-r--r--mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.mobin23302 -> 24326 bytes
-rw-r--r--mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.po411
-rw-r--r--mediagoblin/i18n/is_IS/LC_MESSAGES/mediagoblin.mobin25008 -> 26342 bytes
-rw-r--r--mediagoblin/i18n/is_IS/LC_MESSAGES/mediagoblin.po468
-rw-r--r--mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.mobin24263 -> 25279 bytes
-rw-r--r--mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.po422
-rw-r--r--mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.mobin23923 -> 24944 bytes
-rw-r--r--mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.po411
-rw-r--r--mediagoblin/i18n/ko_KR/LC_MESSAGES/mediagoblin.mobin25185 -> 26202 bytes
-rw-r--r--mediagoblin/i18n/ko_KR/LC_MESSAGES/mediagoblin.po413
-rw-r--r--mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.mobin23774 -> 24753 bytes
-rw-r--r--mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.po415
-rw-r--r--mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.mobin22783 -> 23771 bytes
-rw-r--r--mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.po413
-rw-r--r--mediagoblin/i18n/pl/LC_MESSAGES/mediagoblin.mobin24051 -> 25584 bytes
-rw-r--r--mediagoblin/i18n/pl/LC_MESSAGES/mediagoblin.po506
-rw-r--r--mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.mobin24133 -> 25166 bytes
-rw-r--r--mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.po434
-rw-r--r--mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.mobin24857 -> 25911 bytes
-rw-r--r--mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.po413
-rw-r--r--mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.mobin31085 -> 32200 bytes
-rw-r--r--mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.po415
-rw-r--r--mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.mobin24563 -> 25686 bytes
-rw-r--r--mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.po427
-rw-r--r--mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.mobin23482 -> 24504 bytes
-rw-r--r--mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.po409
-rw-r--r--mediagoblin/i18n/sq/LC_MESSAGES/mediagoblin.mobin24623 -> 25789 bytes
-rw-r--r--mediagoblin/i18n/sq/LC_MESSAGES/mediagoblin.po471
-rw-r--r--mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.mobin23398 -> 24362 bytes
-rw-r--r--mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.po401
-rw-r--r--mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.mobin23628 -> 24592 bytes
-rw-r--r--mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.po409
-rw-r--r--mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.mobin23544 -> 24563 bytes
-rw-r--r--mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.po409
-rw-r--r--mediagoblin/i18n/tr_TR/LC_MESSAGES/mediagoblin.mobin0 -> 24771 bytes
-rw-r--r--mediagoblin/i18n/tr_TR/LC_MESSAGES/mediagoblin.po1252
-rw-r--r--mediagoblin/i18n/zh_CN/LC_MESSAGES/mediagoblin.mobin0 -> 23615 bytes
-rw-r--r--mediagoblin/i18n/zh_CN/LC_MESSAGES/mediagoblin.po1256
-rw-r--r--mediagoblin/i18n/zh_TW.Big5/LC_MESSAGES/mediagoblin.mobin23342 -> 24306 bytes
-rw-r--r--mediagoblin/i18n/zh_TW.Big5/LC_MESSAGES/mediagoblin.po401
-rw-r--r--mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.mobin22667 -> 23703 bytes
-rw-r--r--mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.po493
-rw-r--r--mediagoblin/init/__init__.py21
-rw-r--r--mediagoblin/init/celery/__init__.py18
-rw-r--r--mediagoblin/listings/views.py17
-rw-r--r--mediagoblin/meddleware/csrf.py2
-rw-r--r--mediagoblin/media_types/__init__.py77
-rw-r--r--mediagoblin/media_types/ascii/__init__.py24
-rw-r--r--mediagoblin/media_types/ascii/processing.py6
-rw-r--r--mediagoblin/media_types/audio/__init__.py24
-rw-r--r--mediagoblin/media_types/audio/processing.py9
-rw-r--r--mediagoblin/media_types/image/__init__.py27
-rw-r--r--mediagoblin/media_types/image/processing.py9
-rw-r--r--mediagoblin/media_types/pdf/__init__.py22
-rw-r--r--mediagoblin/media_types/pdf/processing.py13
-rw-r--r--mediagoblin/media_types/stl/__init__.py21
-rw-r--r--mediagoblin/media_types/stl/processing.py8
-rw-r--r--mediagoblin/media_types/tools.py27
-rw-r--r--mediagoblin/media_types/video/__init__.py25
-rw-r--r--mediagoblin/media_types/video/processing.py13
-rw-r--r--mediagoblin/media_types/video/transcoders.py6
-rw-r--r--mediagoblin/notifications/__init__.py141
-rw-r--r--mediagoblin/notifications/routing.py25
-rw-r--r--mediagoblin/notifications/task.py46
-rw-r--r--mediagoblin/notifications/tools.py55
-rw-r--r--mediagoblin/notifications/views.py54
-rw-r--r--mediagoblin/plugins/api/views.py6
-rw-r--r--mediagoblin/plugins/basic_auth/__init__.py88
-rw-r--r--mediagoblin/plugins/basic_auth/forms.py46
-rw-r--r--mediagoblin/plugins/basic_auth/tools.py (renamed from mediagoblin/auth/lib.py)73
-rw-r--r--mediagoblin/plugins/httpapiauth/__init__.py7
-rw-r--r--mediagoblin/plugins/openid/__init__.py123
-rw-r--r--mediagoblin/plugins/openid/forms.py41
-rw-r--r--mediagoblin/plugins/openid/models.py65
-rw-r--r--mediagoblin/plugins/openid/store.py127
-rw-r--r--mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html44
-rw-r--r--mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html43
-rw-r--r--mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html25
-rw-r--r--mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html65
-rw-r--r--mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html25
-rw-r--r--mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html27
-rw-r--r--mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/request_form.html24
-rw-r--r--mediagoblin/plugins/openid/views.py404
-rw-r--r--mediagoblin/plugins/piwigo/tools.py21
-rw-r--r--mediagoblin/plugins/piwigo/views.py102
-rw-r--r--mediagoblin/routing.py1
-rw-r--r--mediagoblin/static/css/base.css78
-rw-r--r--mediagoblin/static/css/pdf_viewer.css1448
-rw-r--r--mediagoblin/static/js/notifications.js36
-rw-r--r--mediagoblin/static/js/pdf_viewer.js3615
-rw-r--r--mediagoblin/storage/cloudfiles.py2
-rw-r--r--mediagoblin/submit/lib.py11
-rw-r--r--mediagoblin/submit/views.py23
-rw-r--r--mediagoblin/templates/mediagoblin/auth/change_fp.html3
-rw-r--r--mediagoblin/templates/mediagoblin/auth/forgot_password.html2
-rw-r--r--mediagoblin/templates/mediagoblin/auth/login.html18
-rw-r--r--mediagoblin/templates/mediagoblin/auth/register.html7
-rw-r--r--mediagoblin/templates/mediagoblin/base.html28
-rw-r--r--mediagoblin/templates/mediagoblin/bits/above_content.html (renamed from mediagoblin/templates/mediagoblin/bits/above-content.html)0
-rw-r--r--mediagoblin/templates/mediagoblin/bits/base_footer.html28
-rw-r--r--mediagoblin/templates/mediagoblin/bits/body_end.html (renamed from mediagoblin/templates/mediagoblin/bits/body-end.html)0
-rw-r--r--mediagoblin/templates/mediagoblin/bits/body_start.html (renamed from mediagoblin/templates/mediagoblin/bits/body-start.html)0
-rw-r--r--mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html41
-rw-r--r--mediagoblin/templates/mediagoblin/edit/change_pass.html52
-rw-r--r--mediagoblin/templates/mediagoblin/edit/edit_account.html20
-rw-r--r--mediagoblin/templates/mediagoblin/edit/verification.txt29
-rw-r--r--mediagoblin/templates/mediagoblin/fragments/header_notifications.html40
-rw-r--r--mediagoblin/templates/mediagoblin/media_displays/image.html17
-rw-r--r--mediagoblin/templates/mediagoblin/media_displays/pdf.html28
-rw-r--r--mediagoblin/templates/mediagoblin/media_displays/stl.html16
-rw-r--r--mediagoblin/templates/mediagoblin/root.html19
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/media.html36
-rw-r--r--mediagoblin/templates/mediagoblin/utils/comment-subscription.html34
-rw-r--r--mediagoblin/templates/mediagoblin/utils/exif.html39
-rw-r--r--mediagoblin/templates/mediagoblin/utils/wtforms.html58
-rw-r--r--mediagoblin/tests/__init__.py12
-rw-r--r--mediagoblin/tests/appconfig_context_modified.ini27
-rw-r--r--mediagoblin/tests/appconfig_static_plugin.ini27
-rw-r--r--mediagoblin/tests/auth_configs/__init__.py0
-rw-r--r--mediagoblin/tests/auth_configs/authentication_disabled_appconfig.ini25
-rw-r--r--mediagoblin/tests/auth_configs/openid_appconfig.ini41
-rw-r--r--mediagoblin/tests/conftest.py28
-rw-r--r--mediagoblin/tests/pytest.ini2
-rw-r--r--mediagoblin/tests/test_auth.py153
-rw-r--r--mediagoblin/tests/test_basic_auth.py59
-rw-r--r--mediagoblin/tests/test_celery_setup.py2
-rw-r--r--mediagoblin/tests/test_edit.py91
-rw-r--r--mediagoblin/tests/test_exif.py375
-rw-r--r--mediagoblin/tests/test_mgoblin_app.ini19
-rw-r--r--mediagoblin/tests/test_misc.py8
-rw-r--r--mediagoblin/tests/test_notifications.py151
-rw-r--r--mediagoblin/tests/test_openid.py373
-rw-r--r--mediagoblin/tests/test_paste.ini14
-rw-r--r--mediagoblin/tests/test_piwigo.py8
-rw-r--r--mediagoblin/tests/test_pluginapi.py141
-rw-r--r--mediagoblin/tests/test_submission.py14
-rw-r--r--mediagoblin/tests/testplugins/modify_context/__init__.py55
-rw-r--r--mediagoblin/tests/testplugins/modify_context/templates/contextplugin/general.html5
-rw-r--r--mediagoblin/tests/testplugins/modify_context/templates/contextplugin/specific.html6
-rw-r--r--mediagoblin/tests/testplugins/modify_context/views.py33
-rw-r--r--mediagoblin/tests/testplugins/staticstuff/__init__.py36
-rw-r--r--mediagoblin/tests/testplugins/staticstuff/static/css/bunnify.css4
-rw-r--r--mediagoblin/tests/testplugins/staticstuff/views.py28
-rw-r--r--mediagoblin/tests/tools.py106
-rw-r--r--mediagoblin/tools/exif.py2
-rw-r--r--mediagoblin/tools/mail.py22
-rw-r--r--mediagoblin/tools/response.py2
-rw-r--r--mediagoblin/tools/session.py11
-rw-r--r--mediagoblin/tools/staticdirect.py38
-rw-r--r--mediagoblin/tools/template.py20
-rw-r--r--mediagoblin/user_pages/views.py23
-rw-r--r--paste.ini6
-rw-r--r--setup.py6
212 files changed, 15878 insertions, 11315 deletions
diff --git a/AUTHORS b/AUTHORS
index b6dd1cf2..304e14a2 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -8,10 +8,12 @@ variety of different ways and this software wouldn't exist without them.
Thank you!
* Aaron Williamson
+* Aditi Mittal
* Aeva Ntsc
* Alejandro Villanueva
* Aleksandar Micovic
* Aleksej Serdjukov
+* Alon Levy
* Alex Camelio
* András Veres-Szentkirályi
* Bassam Kurdali
@@ -21,13 +23,17 @@ Thank you!
* Corey Farwell
* Chris Moylan
* Christopher Allan Webber
+* David Thompson
* Daniel Neel
* Deb Nicholson
* Derek Moore
* Duncan Paterson
* Elrond of Samba TNG
* Emily O'Leary
+* Gabi Thume
+* Gabriel Saldana
* Greg Grossmeier
+* Hans Lo
* Jakob Kramer
* Jef van Schendel
* Jessica Tallon
@@ -36,25 +42,34 @@ Thank you!
* Jorge Araya Navarro
* Karen Rustad
* Kuno Woudt
+* Laura Arjona
* Larisa Hoffenbecker
* Luke Slater
* Manuel Urbano Santos
* Mark Holmquist
+* Mats Sjöberg
* Matt Lee
* Michele Azzolari
+* Mike Linksvayer
+* Natalie Foust-Pilcher
* Nathan Yergler
* Odin Hørthe Omdal
* Osama Khalid
* Pablo J. Urbano Santos
+* Praveen Kumar
* Rasmus Larsson
+* Rodney Ewing
* Runar Petursson
* Sacha De'Angeli
* Sam Kleinman
+* Sam Tuke
* Sebastian Spaeth
* Shawn Khan
+* Simon Fondrie-Teitler
* Stefano Zacchiroli
* Tiberiu C. Turbureanu
* Tran Thanh Bao
+* Tryggvi Björgvinsson
* Shawn Khan
* Will Kahn-Greene
@@ -64,4 +79,4 @@ If you think your name should be on this list, let us know!
We also are currently borrowing an image in
mediagoblin/static/images/media_thumbs/image.png from the wonderful
people at http://tango.freedesktop.org/ which is in the public
-domain... thanks Tango folks! \ No newline at end of file
+domain... thanks Tango folks!
diff --git a/README b/README
index 07f9a094..98b8e9e9 100644
--- a/README
+++ b/README
@@ -5,21 +5,21 @@
What is GNU MediaGoblin?
========================
-* Initially, a place to store all your photos that’s as awesome as, if
- not more awesome than, existing network services (Flickr, SmugMug,
- Picasa, etc)
+* A place to store all your different media (photos, videos, audios,
+ and more!) that’s as awesome as, if not more awesome than, existing
+ network services (Flickr, YouTube, etc)
* Customizable!
* A place for people to collaborate and show off original and derived
creations. Free, as in freedom. We’re a GNU project after all.
-* Later, a place for all sorts of media, such as video, music, etc hosting.
-* Later, federated with OStatus!
+* Extensible: Plugins allow you to add new media types (3d models?
+ Presentations and documents? Yes, and more!) or extend old ones.
+* A real community, and we'd love to have you join us!
Is it ready for me to use?
==========================
-Yes! But with caveats. The software is usable and there are instances
-running, but it's still in its early stages.
+Yes!
Can I help/hang out/participate/whisper sweet nothings in your ear?
diff --git a/docs/source/devel/migrations.rst b/docs/source/devel/migrations.rst
new file mode 100644
index 00000000..16c02b04
--- /dev/null
+++ b/docs/source/devel/migrations.rst
@@ -0,0 +1,62 @@
+.. MediaGoblin Documentation
+
+ Written in 2011, 2012 by MediaGoblin contributors
+
+ To the extent possible under law, the author(s) have dedicated all
+ copyright and related and neighboring rights to this software to
+ the public domain worldwide. This software is distributed without
+ any warranty.
+
+ You should have received a copy of the CC0 Public Domain
+ Dedication along with this software. If not, see
+ <http://creativecommons.org/publicdomain/zero/1.0/>.
+
+==========
+Migrations
+==========
+
+So, about migrations. Every time we change the way the database
+structure works, we need to add a migration so that people running
+older codebases can have their databases updated to the new structure
+when they run `./bin/gmg dbupdate`.
+
+The first time `./bin/gmg dbupdate` is run by a user, it creates the
+tables at the current state that they're defined in models.py and sets
+the migration number to the current migration... after all, migrations
+only exist to get things to the current state of the db. After that,
+every migration is run with dbupdate.
+
+There's a few things you need to know:
+
+- We use `sqlalchemy-migrate
+ <http://code.google.com/p/sqlalchemy-migrate/>`_.
+ See `their docs <https://sqlalchemy-migrate.readthedocs.org/>`_.
+- `Alembic <https://bitbucket.org/zzzeek/alembic>`_ might be a better
+ choice than sqlalchemy-migrate now or in the future, but we
+ originally decided not to use it because it didn't have sqlite
+ support. It's not clear if that's changed.
+- SQLAlchemy has two parts to it, the ORM and the "core" interface.
+ We DO NOT use the ORM when running migrations. Think about it: the
+ ORM is set up with an expectation that the models already reflect a
+ certain pattern. But if a person is moving from their old patern
+ and are running tools to *get to* the current pattern, of course
+ their current database structure doesn't match the state of the ORM!
+- How to write migrations? Maybe there will be a tutorial here in the
+ future... in the meanwhile, look at existing migrations in
+ `mediagoblin/db/migrations.py` and look in
+ `mediagoblin/tests/test_sql_migrations.py` for examples.
+- Common pattern: use `inspect_table` to get the current state
+ of the table before we run alterations on it.
+- Make sure you set the RegisterMigration to be the next migration in
+ order.
+- What happens if you're adding a *totally new* table? In this case,
+ you should copy the table in entirety as it exists into
+ migrations.py then create the tables based off of that... see
+ add_collection_tables. This is easier than reproducing the SQL by
+ hand.
+- If you're writing a feature branch, you don't need to keep adding
+ migrations every time you change things around if your database
+ structure is in flux. Just alter your migrations so that they're
+ correct for the merge into master.
+
+That's it for now! Good luck!
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 7f692d57..de6c9c0d 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -73,6 +73,8 @@ This guide covers writing new GNU MediaGoblin plugins.
pluginwriter/quickstart
pluginwriter/database
pluginwriter/api
+ pluginwriter/tests
+ pluginwriter/media_type_hooks
Part 4: Developer's Zone
@@ -86,6 +88,7 @@ This chapter contains various information for developers.
devel/codebase
devel/storage
devel/originaldesigndecisions
+ devel/migrations
Indices and tables
diff --git a/docs/source/pluginwriter/api.rst b/docs/source/pluginwriter/api.rst
index df933511..29adb691 100644
--- a/docs/source/pluginwriter/api.rst
+++ b/docs/source/pluginwriter/api.rst
@@ -11,6 +11,7 @@
Dedication along with this software. If not, see
<http://creativecommons.org/publicdomain/zero/1.0/>.
+.. _plugin-api-chapter:
==========
Plugin API
@@ -23,7 +24,27 @@ Authors are encouraged to develop plugins and work with the
MediaGoblin community to keep them up to date, but this API will be a
moving target for a few releases.
-Please check the release notes for updates!
+Please check the :ref:`release-notes` for updates!
+
+
+How are hooks added? Where do I find them?
+-------------------------------------------
+
+Much of this document talks about hooks, both as in terms of regular
+hooks and template hooks. But where do they come from, and how can
+you find a list of them?
+
+For the moment, the best way to find available hooks is to check the
+source code itself. (Yes, we should start a more official hook
+listing with descriptions soon.) But many hooks you may need do not
+exist yet: what to do then?
+
+The plan at present is that we are adding hooks as people need them,
+with community discussion. If you find that you need a hook and
+MediaGoblin at present doesn't provide it at present, please
+`http://mediagoblin.org/pages/join.html <talk to us>`_! We'll
+evaluate what to do from there.
+
:mod:`pluginapi` Module
-----------------------
@@ -48,3 +69,254 @@ example might look like::
This means that when people enable your plugin in their config you'll
be able to provide defaults as well as type validation.
+You can access this via the app_config variables in mg_globals, or you
+can use a shortcut to get your plugin's config section::
+
+ >>> from mediagoblin.tools import pluginapi
+ # Replace with the path to your plugin.
+ # (If an external package, it won't be part of mediagoblin.plugins)
+ >>> floobie_config = pluginapi.get_config('mediagoblin.plugins.floobifier')
+ >>> floobie_dir = floobie_config['floobie_dir']
+ # This is the same as the above
+ >>> from mediagoblin import mg_globals
+ >>> config = mg_globals.global_config['plugins']['mediagoblin.plugins.floobifier']
+ >>> floobie_dir = floobie_config['floobie_dir']
+
+A tip: you have access to the `%(here)s` variable in your config,
+which is the directory that the user's mediagoblin config is running
+out of. So for example, your plugin may need a "floobie" directory to
+store floobs in. You could give them a reasonable default that makes
+use of the default `user_dev` location, but allow users to override
+it, like so::
+
+ [plugin_spec]
+ floobie_dir = string(default="%(here)s/user_dev/floobs/")
+
+Note, this is relative to the user's mediagoblin config directory,
+*not* your plugin directory!
+
+
+Context Hooks
+-------------
+
+View specific hooks
++++++++++++++++++++
+
+You can hook up to almost any template called by any specific view
+fairly easily. As long as the view directly or indirectly uses the
+method ``render_to_response`` you can access the context via a hook
+that has a key in the format of the tuple::
+
+ (view_symbolic_name, view_template_path)
+
+Where the "view symbolic name" is the same parameter used in
+``request.urlgen()`` to look up the view. So say we're wanting to add
+something to the context of the user's homepage. We look in
+mediagoblin/user_pages/routing.py and see::
+
+ add_route('mediagoblin.user_pages.user_home',
+ '/u/<string:user>/',
+ 'mediagoblin.user_pages.views:user_home')
+
+Aha! That means that the name is ``mediagoblin.user_pages.user_home``.
+Okay, so then we look at the view at the
+``mediagoblin.user_pages.user_home`` method::
+
+ @uses_pagination
+ def user_home(request, page):
+ # [...] whole bunch of stuff here
+ return render_to_response(
+ request,
+ 'mediagoblin/user_pages/user.html',
+ {'user': user,
+ 'user_gallery_url': user_gallery_url,
+ 'media_entries': media_entries,
+ 'pagination': pagination})
+
+Nice! So the template appears to be
+``mediagoblin/user_pages/user.html``. Cool, that means that the key
+is::
+
+ ("mediagoblin.user_pages.user_home",
+ "mediagoblin/user_pages/user.html")
+
+The context hook uses ``hook_transform()`` so that means that if we're
+hooking into it, our hook will both accept one argument, ``context``,
+and should return that modified object, like so::
+
+ def add_to_user_home_context(context):
+ context['foo'] = 'bar'
+ return context
+
+ hooks = {
+ ("mediagoblin.user_pages.user_home",
+ "mediagoblin/user_pages/user.html"): add_to_user_home_context}
+
+
+Global context hooks
+++++++++++++++++++++
+
+If you need to add something to the context of *every* view, it is not
+hard; there are two hooks hook that also uses hook_transform (like the
+above) but make available what you are providing to *every* view.
+
+Note that there is a slight, but critical, difference between the two.
+
+The most general one is the ``'template_global_context'`` hook. This
+one is run only once, and is read into the global context... all views
+will get access to what are in this dict.
+
+The slightly more expensive but more powerful one is
+``'template_context_prerender'``. This one is not added to the global
+context... it is added to the actual context of each individual
+template render right before it is run! Because of this you also can
+do some powerful and crazy things, such as checking the request object
+or other parts of the context before passing them on.
+
+
+Adding static resources
+-----------------------
+
+It's possible to add static resources for your plugin. Say your
+plugin needs some special javascript and images... how to provide
+them? Then how to access them? MediaGoblin has a way!
+
+
+Attaching to the hook
++++++++++++++++++++++
+
+First, you need to register your plugin's resources with the hook.
+This is pretty easy actually: you just need to provide a function that
+passes back a PluginStatic object.
+
+.. autoclass:: mediagoblin.tools.staticdirect.PluginStatic
+
+
+Running plugin assetlink
+++++++++++++++++++++++++
+
+In order for your plugin assets to be properly served by MediaGoblin,
+your plugin's asset directory needs to be symlinked into the directory
+that plugin assets are served from. To set this up, run::
+
+ ./bin/gmg assetlink
+
+
+Using staticdirect
+++++++++++++++++++
+
+Once you have this, you will want to be able to of course link to your
+assets! MediaGoblin has a "staticdirect" tool; you want to use this
+like so in your templates::
+
+ staticdirect("css/monkeys.css", "mystaticname")
+
+Replace "mystaticname" with the name you passed to PluginStatic. The
+staticdirect method is, for convenience, attached to the request
+object, so you can access this in your templates like:
+
+.. code-block:: html
+
+ <img alt="A funny bunny"
+ src="{{ request.staticdirect('images/funnybunny.png', 'mystaticname') }}" />
+
+
+Additional hook tips
+--------------------
+
+This section aims to explain some tips in regards to adding hooks to
+the MediaGoblin repository.
+
+WTForms hooks
++++++++++++++
+
+We haven't totally settled on a way to tranform wtforms form objects,
+but here's one way. In your view::
+
+ from mediagoblin.foo.forms import SomeForm
+
+ def some_view(request)
+ form_class = hook_transform('some_form_transform', SomeForm)
+ form = form_class(request.form)
+
+Then to hook into this form, do something in your plugin like::
+
+ import wtforms
+
+ class SomeFormAdditions(wtforms.Form):
+ new_datefield = wtforms.DateField()
+
+ def transform_some_form(orig_form):
+ class ModifiedForm(orig_form, SomeFormAdditions)
+ return ModifiedForm
+
+ hooks = {
+ 'some_form_transform': transform_some_form}
+
+
+Interfaces
+++++++++++
+
+If you want to add a pseudo-interface, it's not difficult to do so.
+Just write the interface like so::
+
+ class FrobInterface(object):
+ """
+ Interface for Frobbing.
+
+ Classes implementing this interface should provide defrob and frob.
+ They may also implement double_frob, but it is not required; if
+ not provided, we will use a general technique.
+ """
+
+ def defrob(self, frobbed_obj):
+ """
+ Take a frobbed_obj and defrob it. Returns the defrobbed object.
+ """
+ raise NotImplementedError()
+
+ def frob(self, normal_obj):
+ """
+ Take a normal object and frob it. Returns the frobbed object.
+ """
+ raise NotImplementedError()
+
+ def double_frob(self, normal_obj):
+ """
+ Frob this object and return it multiplied by two.
+ """
+ return self.frob(normal_obj) * 2
+
+
+ def some_frob_using_method():
+ # something something something
+ frobber = hook_handle(FrobInterface)
+ frobber.frob(blah)
+
+ # alternately you could have a default
+ frobber = hook_handle(FrobInterface) or DefaultFrobber
+ frobber.defrob(foo)
+
+
+It's fine to use your interface as the key instead of a string if you
+like. (Usually this is messy, but since interfaces are public and
+since you need to import them into your plugin anyway, interfaces
+might as well be keys.)
+
+Then a plugin providing your interface can be like::
+
+ from mediagoblin.foo.frobfrogs import FrobInterface
+ from frogfrobber import utils
+
+ class FrogFrobber(FrobInterface):
+ """
+ Takes a frogputer science approach to frobbing.
+ """
+ def defrob(self, frobbed_obj):
+ return utils.frog_defrob(frobbed_obj)
+
+ def frob(self, normal_obj):
+ return utils.frog_frob(normal_obj)
+
+ hooks = {
+ FrobInterface: lambda: return FrogFrobber}
diff --git a/docs/source/pluginwriter/database.rst b/docs/source/pluginwriter/database.rst
index 58edf3a0..603a19eb 100644
--- a/docs/source/pluginwriter/database.rst
+++ b/docs/source/pluginwriter/database.rst
@@ -12,9 +12,12 @@
<http://creativecommons.org/publicdomain/zero/1.0/>.
-========
-Database
-========
+.. _plugin-database-chapter:
+
+
+===========================
+Database models for plugins
+===========================
Accessing Existing Data
diff --git a/docs/source/pluginwriter/media_type_hooks.rst b/docs/source/pluginwriter/media_type_hooks.rst
new file mode 100644
index 00000000..498b0b54
--- /dev/null
+++ b/docs/source/pluginwriter/media_type_hooks.rst
@@ -0,0 +1,38 @@
+==================
+ Media Type hooks
+==================
+
+This documents the hooks that are currently available for ``media_type`` plugins.
+
+What hooks are available?
+=========================
+
+'sniff_handler'
+---------------
+
+This hook is used by ``sniff_media`` in ``mediagoblin.media_types.__init__``.
+Your media type should return its ``sniff_media`` method when this hook is
+called.
+
+.. Note::
+ Your ``sniff_media`` method should return either the ``media_type`` or
+ ``None``.
+
+'get_media_type_and_manager'
+----------------------------
+
+This hook is used by ``get_media_type_and_manager`` in
+``mediagoblin.media_types.__init__``. When this hook is called, your media type
+plugin should check if it can handle the given extension. If so, your media
+type plugin should return the media type and media manager.
+
+('media_manager', MEDIA_TYPE)
+-----------------------------
+
+If you already know the string representing the media type of a type
+of media, you can pull down the manager specifically. Note that this
+hook is not a string but a tuple of two strings, the latter being the
+name of the media type.
+
+This is used by media entries to pull down their media managers, and
+so on.
diff --git a/docs/source/pluginwriter/quickstart.rst b/docs/source/pluginwriter/quickstart.rst
index b5a63f79..6d45ea36 100644
--- a/docs/source/pluginwriter/quickstart.rst
+++ b/docs/source/pluginwriter/quickstart.rst
@@ -178,8 +178,10 @@ That's it for the quick start!
Where to go from here
=====================
-See the documentation on the plugin API for code samples and other
-things you can use when building your plugin.
+See the documentation on the :ref:`plugin-api-chapter` for code
+samples and other things you can use when building your plugin. If
+your plugin needs its own database models, see
+:ref:`plugin-database-chapter`.
See `Hitchhiker's Guide to Packaging
<http://guide.python-distribute.org/>`_ for more information on
diff --git a/docs/source/pluginwriter/tests.rst b/docs/source/pluginwriter/tests.rst
new file mode 100644
index 00000000..fe99688f
--- /dev/null
+++ b/docs/source/pluginwriter/tests.rst
@@ -0,0 +1,64 @@
+.. MediaGoblin Documentation
+
+ Written in 2013 by MediaGoblin contributors
+
+ To the extent possible under law, the author(s) have dedicated all
+ copyright and related and neighboring rights to this software to
+ the public domain worldwide. This software is distributed without
+ any warranty.
+
+ You should have received a copy of the CC0 Public Domain
+ Dedication along with this software. If not, see
+ <http://creativecommons.org/publicdomain/zero/1.0/>.
+
+==============================
+Writing unit tests for plugins
+==============================
+
+Here's a brief guide to writing unit tests for plugins. However, it
+isn't really ideal. It also hasn't been well tested... yes, there's
+some irony there :)
+
+Some notes: we're using py.test and webtest for unit testing stuff.
+Keep that in mind.
+
+My suggestion is to mime the behavior of `mediagoblin/tests/` and put
+that in your own plugin, like `myplugin/tests/`. Copy over
+`conftest.py` and `pytest.ini` to your tests directory, but possibly
+change the `test_app` fixture to match your own tests' config needs.
+For example::
+
+ import pkg_resources
+ # [...]
+
+ @pytest.fixture()
+ def test_app(request):
+ return get_app(
+ request,
+ mgoblin_config=pkg_resources.resource_filename(
+ 'myplugin.tests', 'myplugin_mediagoblin.ini'))
+
+In any test module in your tests directory you can then do::
+
+ def test_somethingorother(test_app):
+ # real code goes here
+ pass
+
+And you'll get a mediagoblin application wrapped in webtest passed in
+to your environment.
+
+If your plugin needs to define multiple configuration setups, you can
+actually set up multiple fixtures very easily for this. You can just
+set up multiple fixtures with different names that point to different
+configs and pass them in as that named argument.
+
+To run the tests, from mediagoblin's directory (make sure that your
+plugin has been added to your mediagoblin checkout's virtualenv!) do::
+
+ ./runtests.sh /path/to/myplugin/tests/
+
+replacing `/path/to/myplugin/` with the actual path to your plugin.
+
+NOTE: again, the above is untested, but it should probably work. If
+you run into trouble, `contact us
+<http://mediagoblin.org/pages/join.html>`_, preferably on IRC!
diff --git a/docs/source/siteadmin/deploying.rst b/docs/source/siteadmin/deploying.rst
index 326d2243..a892bbd4 100644
--- a/docs/source/siteadmin/deploying.rst
+++ b/docs/source/siteadmin/deploying.rst
@@ -197,13 +197,14 @@ Change to the MediaGoblin directory that you just created::
cd /srv/mediagoblin.example.org
-Clone the MediaGoblin repository::
+Clone the MediaGoblin repository and set up the git submodules::
git clone git://gitorious.org/mediagoblin/mediagoblin.git
+ cd mediagoblin
+ git submodule init && git submodule update
Set up the in-package virtualenv::
- cd mediagoblin
(virtualenv --system-site-packages . || virtualenv .) && ./bin/python setup.py develop
.. note::
@@ -234,7 +235,7 @@ This concludes the initial configuration of the development
environment. In the future, when you update your
codebase, you should also run::
- ./bin/python setup.py develop --upgrade && ./bin/gmg dbupdate
+ ./bin/python setup.py develop --upgrade && ./bin/gmg dbupdate && git submodule fetch
Note: If you are running an active site, depending on your server
configuration, you may need to stop it first or the dbupdate command
@@ -245,6 +246,23 @@ update)
Deploy MediaGoblin Services
---------------------------
+Edit site configuration
+~~~~~~~~~~~~~~~~~~~~~~~
+
+A few basic properties must be set before MediaGoblin will work. First
+make a copy of ``mediagoblin.ini`` for editing so the original config
+file isn't lost::
+
+ cp mediagoblin.ini mediagoblin_local.ini
+
+Then:
+ - Set ``email_sender_address`` to the address you wish to be used as
+ the sender for system-generated emails
+ - Edit ``direct_remote_path``, ``base_dir``, and ``base_url`` if
+ your mediagoblin directory is not the root directory of your
+ vhost.
+
+
Configure MediaGoblin to use the PostgreSQL database
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -280,11 +298,11 @@ browser to confirm that the service is operable.
.. _webserver-config:
-Connect the Webserver to MediaGoblin with FastCGI
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-This section describes how to configure MediaGoblin to work via
-FastCGI. Our configuration example will use nginx, however, you may
+FastCGI and nginx
+~~~~~~~~~~~~~~~~~
+
+This configuration example will use nginx, however, you may
use any webserver of your choice as long as it supports the FastCGI
protocol. If you do not already have a web server, consider nginx, as
the configuration files may be more clear than the
@@ -350,6 +368,11 @@ this ``nginx.conf`` file should be modeled on the following::
alias /srv/mediagoblin.example.org/mediagoblin/user_dev/theme_static/;
}
+ # Plugin static files (usually symlinked in)
+ location /plugin_static/ {
+ alias /srv/mediagoblin.example.org/mediagoblin/user_dev/plugin_static/;
+ }
+
# Mounting MediaGoblin itself via FastCGI.
location / {
fastcgi_pass 127.0.0.1:26543;
@@ -385,6 +408,13 @@ Visit the site you've set up in your browser by visiting
smaller deployments. However, for larger production deployments
with larger processing requirements, see the
":doc:`production-deployments`" documentation.
+
+
+Apache
+~~~~~~
+
+Instructions and scripts for running MediaGoblin on an Apache server
+can be found on the `MediaGoblin wiki <http://wiki.mediagoblin.org/Deployment>`_.
Security Considerations
diff --git a/docs/source/siteadmin/media-types.rst b/docs/source/siteadmin/media-types.rst
index 210094b9..3e8a94e9 100644
--- a/docs/source/siteadmin/media-types.rst
+++ b/docs/source/siteadmin/media-types.rst
@@ -18,16 +18,18 @@ Media Types
====================
In the future, there will be all sorts of media types you can enable,
-but in the meanwhile there are three additional media types: video, audio
-and ascii art.
+but in the meanwhile there are five additional media types: video, audio,
+ascii art, STL/3d models, PDF and Document.
First, you should probably read ":doc:`configuration`" to make sure
you know how to modify the mediagoblin config file.
-
Enabling Media Types
====================
+.. note::
+ Media types are now plugins
+
Media types are enabled in your mediagoblin configuration file, typically it is
created by copying ``mediagoblin.ini`` to ``mediagoblin_local.ini`` and then
applying your changes to ``mediagoblin_local.ini``. If you don't already have a
@@ -37,11 +39,13 @@ Most media types have additional dependencies that you will have to install.
You will find descriptions on how to satisfy the requirements of each media type
on this page.
-To enable a media type, edit the ``media_types`` list in your
-``mediagoblin_local.ini``. For example, if your system supported image and
-video media types, then the list would look like this::
+To enable a media type, add the the media type under the ``[plugins]`` section
+in you ``mediagoblin_local.ini``. For example, if your system supported image
+and video media types, then it would look like this::
- media_types = mediagoblin.media_types.image, mediagoblin.media_types.video
+ [plugins]
+ [[mediagoblin.media_types.image]]
+ [[mediagoblin.media_types.video]]
Note that after enabling new media types, you must run dbupdate like so::
@@ -83,8 +87,8 @@ good/bad/ugly). On Debianoid systems
gstreamer0.10-ffmpeg
-Add ``mediagoblin.media_types.video`` to the ``media_types`` list in your
-``mediagoblin_local.ini`` and restart MediaGoblin.
+Add ``[[mediagoblin.media_types.video]]`` under the ``[plugins]`` section in
+your ``mediagoblin_local.ini`` and restart MediaGoblin.
Run
@@ -133,7 +137,7 @@ Then install ``scikits.audiolab`` for the spectrograms::
./bin/pip install scikits.audiolab
-Add ``mediagoblin.media_types.audio`` to the ``media_types`` list in your
+Add ``[[mediagoblin.media_types.audio]]`` under the ``[plugins]`` section in your
``mediagoblin_local.ini`` and restart MediaGoblin.
Run
@@ -158,13 +162,8 @@ library, which is necessary for creating thumbnails of ascii art
Next, modify (and possibly copy over from ``mediagoblin.ini``) your
-``mediagoblin_local.ini``. In the ``[mediagoblin]`` section, add
-``mediagoblin.media_types.ascii`` to the ``media_types`` list.
-
-For example, if your system supported image and ascii art media types, then
-the list would look like this::
-
- media_types = mediagoblin.media_types.image, mediagoblin.media_types.ascii
+``mediagoblin_local.ini``. In the ``[plugins]`` section, add
+``[[mediagoblin.media_types.ascii]]``.
Run
@@ -184,7 +183,7 @@ your execution path. This feature has been tested with Blender 2.63.
It may work on some earlier versions, but that is not guaranteed (and
is surely not to work prior to Blender 2.5X).
-Add ``mediagoblin.media_types.stl`` to the ``media_types`` list in your
+Add ``[[mediagoblin.media_types.stl]]`` under the ``[plugins]`` section in your
``mediagoblin_local.ini`` and restart MediaGoblin.
Run
@@ -199,8 +198,16 @@ will be able to present them to your wide audience of admirers!
PDF and Document
================
-To enable the "PDF and Document" support plugin, you need pdftocairo, pdfinfo,
-unoconv with headless support. All executables must be on your execution path.
+To enable the "PDF and Document" support plugin, you need:
+
+1. pdftocairo and pdfinfo for pdf only support.
+
+2. unoconv with headless support to support converting libreoffice supported
+ documents as well, such as doc/ppt/xls/odf/odg/odp and more.
+ For the full list see mediagoblin/media_types/pdf/processing.py,
+ unoconv_supported.
+
+All executables must be on your execution path.
To install this on Fedora:
@@ -208,6 +215,9 @@ To install this on Fedora:
sudo yum install -y poppler-utils unoconv libreoffice-headless
+Note: You can leave out unoconv and libreoffice-headless if you want only pdf
+support. This will result in a much smaller list of dependencies.
+
pdf.js relies on git submodules, so be sure you have fetched them:
.. code-block:: bash
@@ -222,7 +232,7 @@ This feature has been tested on Fedora with:
It may work on some earlier versions, but that is not guaranteed.
-Add ``mediagoblin.media_types.pdf`` to the ``media_types`` list in your
+Add ``[[mediagoblin.media_types.pdf]]`` under the ``[plugins]`` section in your
``mediagoblin_local.ini`` and restart MediaGoblin.
Run
diff --git a/docs/source/siteadmin/production-deployments.rst b/docs/source/siteadmin/production-deployments.rst
index 1a32d95e..839d3ce5 100644
--- a/docs/source/siteadmin/production-deployments.rst
+++ b/docs/source/siteadmin/production-deployments.rst
@@ -22,12 +22,14 @@ MediaGoblin in actual production environments. Consider
Deploy with Paste
-----------------
-The instance configured with ``./lazyserver.sh`` is not ideal for a
-production MediaGoblin deployment. Ideally, you should be able to use
-an "init" or "control" script to launch and restart the MediaGoblin
+The MediaGoblin WSGI application instance you get with ``./lazyserver.sh`` is
+not ideal for a production MediaGoblin deployment. Ideally, you should be able
+to use an "init" or "control" script to launch and restart the MediaGoblin
process.
-Use the following command as the basis for such a script: ::
+Use the following command as the basis for such a script:
+
+.. code-block:: bash
CELERY_ALWAYS_EAGER=true \
/srv/mediagoblin.example.org/mediagoblin/bin/paster serve \
@@ -41,7 +43,9 @@ synchronously, and the user will advance to the next page only after
processing is complete. If we take Celery out of "always eager mode,"
the user will be able to immediately return to the MediaGoblin site
while processing is ongoing. In these cases, use the following command
-as the basis for your script: ::
+as the basis for your script:
+
+.. code-block:: bash
CELERY_ALWAYS_EAGER=false \
/srv/mediagoblin.example.org/mediagoblin/bin/paster serve \
@@ -52,30 +56,40 @@ as the basis for your script: ::
Separate Celery
---------------
-While the ``./lazyserver.sh`` configuration provides an efficient way to
-start using a MediaGoblin instance, it is not suitable for production
-deployments for several reasons:
+MediaGoblin uses `Celery`_ to handle heavy and long-running tasks. Celery can
+be launched in two ways:
+
+1. Embedded in the MediaGoblin WSGI application [#f-mediagoblin-wsgi-app]_.
+ This is the way ``./lazyserver.sh`` does it for you. It's simple as you
+ only have to run one process. The only bad thing with this is that the
+ heavy and long-running tasks will run *in* the webserver, keeping the user
+ waiting each time some heavy lifting is needed as in for example processing
+ a video. This could lead to problems as an aborted connection will halt any
+ processing and since most front-end web servers *will* terminate your
+ connection if it doesn't get any response from the MediaGoblin WSGI
+ application in a while.
+
+2. As a separate process communicating with the MediaGoblin WSGI application
+ via a `broker`_. This offloads the heavy lifting from the MediaGoblin WSGI
+ application and users will be able to continue to browse the site while the
+ media is being processed in the background.
+
+.. _`broker`: http://docs.celeryproject.org/en/latest/getting-started/brokers/
+.. _`celery`: http://www.celeryproject.org/
+
-In nearly every scenario, work on the Celery queue will need to
-balance with the demands of other processes, and cannot proceed
-synchronously. This is a particularly relevant problem if you use
-MediaGoblin to host video content. Processing with Celery ought to be
-operationally separate from the MediaGoblin application itself, this
-simplifies management and support better workload distribution.
+.. [#f-mediagoblin-wsgi-app] The MediaGoblin WSGI application is the part that
+ of MediaGoblin that processes HTTP requests.
-Basically, if you're doing anything beyond a trivial workload, such as
-image hosting for a small set of users, or have limited media types
-such as "ASCII art" or icon sharing, you will need to run ``celeryd``
-as a separate process.
+To launch Celery separately from the MediaGoblin WSGI application:
-Build an :ref:`init script <init-script>` around the following
-command::
+1. Make sure that the ``CELERY_ALWAYS_EAGER`` environment variable is unset or
+ set to ``false`` when launching the MediaGoblin WSGI application.
+2. Start the ``celeryd`` main process with
- CELERY_CONFIG_MODULE=mediagoblin.init.celery.from_celery ./bin/celeryd
+ .. code-block:: bash
-Modify your existing MediaGoblin and application init scripts, if
-necessary, to prevent them from starting their own ``celeryd``
-processes.
+ CELERY_CONFIG_MODULE=mediagoblin.init.celery.from_celery ./bin/celeryd
.. _sentry:
@@ -102,7 +116,7 @@ These are scripts provided by the MediaGoblin community:
Debian
* `GNU MediaGoblin init scripts
- <https://github.com/jwandborg/mediagoblin-init-scripts>`_
+ <https://github.com/joar/mediagoblin-init-scripts>`_
by `Joar Wandborg <http://wandborg.se>`_
Arch Linux
diff --git a/docs/source/siteadmin/relnotes.rst b/docs/source/siteadmin/relnotes.rst
index 04863ec6..35415b66 100644
--- a/docs/source/siteadmin/relnotes.rst
+++ b/docs/source/siteadmin/relnotes.rst
@@ -11,6 +11,8 @@
Dedication along with this software. If not, see
<http://creativecommons.org/publicdomain/zero/1.0/>.
+.. _release-notes:
+
=============
Release Notes
=============
@@ -19,6 +21,82 @@ This chapter has important information for releases in it.
If you're upgrading from a previous release, please read it
carefully, or at least skim over it.
+
+0.4.1
+=====
+
+This is a bugfix release for 0.4.0. This only implements one major
+fix in the newly released document support which prevented the
+"conversion via libreoffice" feature.
+
+If you were running 0.4.0 you can upgrade to v0.4.1 via a simple
+switch and restarting mediagoblin/celery with no other actions.
+
+Otherwise, follow 0.4.0 instructions.
+
+
+0.4.0
+=====
+
+**Do this to upgrade**
+
+1. Make sure to run
+ ``./bin/python setup.py develop --upgrade && ./bin/gmg dbupdate``
+ after upgrading.
+2. See "For Theme authors" if you have a custom theme.
+3. Note that ``./bin/gmg theme assetlink`` is now just
+ ``./bin/gmg assetlink`` and covers both plugins and assets.
+ Keep on reading to hear more about new plugin features.
+4. If you want to take advantage of new plugins that have statically
+ served assets, you are going to need to add the new "plugin_static"
+ section to your nginx config. Basically the following for nginx::
+
+ # Plugin static files (usually symlinked in)
+ location /plugin_static/ {
+ alias /srv/mediagoblin.example.org/mediagoblin/user_dev/plugin_static/;
+ }
+
+ Similarly, if you've got a modified paste config, you may want to
+ borrow the app:plugin_static section from the default paste.ini
+ file.
+5. We now use itsdangerous for sessions; if you had any references to
+ beaker in your paste config you can remove them. Again, see the
+ default paste.ini config
+6. We also now use git submodules. Please do:
+ ``git submodule init && git submodule update``
+ You will need to do this to use the new PDF support.
+
+**For theme authors**
+
+If you have your own theme or you have any "user modified templates",
+please note the following:
+
+* mediagoblin/bits/ files above-content.html, body-end.html,
+ body-start.html now are renamed... they have underscores instead of
+ dashes in the filenames now :)
+* There's a new file: ``mediagoblin/bits/frontpage_welcome.html``.
+ You can easily customize this to give a welcome page appropriate to
+ your site.
+
+
+**New features**
+* PDF media type!
+* Improved plugin system. More flexible, better documented, with a
+ new plugin authoring section of the docs.
+* itsdangerous based sessions. No more beaker!
+* New, experimental Piwigo-based API. This means you should be able
+ to use MediaGoblin with something like Shotwell. (Again, a word of
+ caution: this is *very experimental*!)
+* Human readable timestamps, and the option to display the original
+ date of an image when available (available as the
+ "original_date_visible" variable)
+* Moved unit testing system from nosetests to py.test so we can better
+ handle issues with sqlalchemy exploding with different database
+ configurations. Long story :)
+* You can now disable the ability to post comments.
+* Tags now can be up to length 255 characters by default.
+
+
0.3.3
=====
diff --git a/docs/source/siteadmin/theming.rst b/docs/source/siteadmin/theming.rst
index 98ec6de7..11ae3875 100644
--- a/docs/source/siteadmin/theming.rst
+++ b/docs/source/siteadmin/theming.rst
@@ -51,7 +51,7 @@ want to install this theme! Don't worry, it's fairly painless.
5. Link the assets so that they can be served by your web server::
- $ ./bin/gmg theme assetlink
+ $ ./bin/gmg assetlink
.. Note::
diff --git a/mediagoblin.ini b/mediagoblin.ini
index 4906546a..30dacadf 100644
--- a/mediagoblin.ini
+++ b/mediagoblin.ini
@@ -11,19 +11,15 @@ email_sender_address = "notice@mediagoblin.example.org"
## Uncomment and change to your DB's appropiate setting.
## Default is a local sqlite db "mediagoblin.db".
+## Don't forget to run `./bin/gmg dbupdate` after having changed it.
# sql_engine = postgresql:///mediagoblin
-# set to false to enable sending notices
+# Set to false to enable sending notices
email_debug_mode = true
# Set to false to disable registrations
allow_registration = true
-## Uncomment this to turn on video or enable other media types
-## You may have to install dependencies, and will have to run ./bin/dbupdate
-## See http://docs.mediagoblin.org/siteadmin/media-types.html for details.
-# media_types = mediagoblin.media_types.image, mediagoblin.media_types.video
-
## Uncomment this to put some user-overriding templates here
# local_templates = %(here)s/user_dev/templates/
@@ -43,7 +39,9 @@ base_url = /mgoblin_media/
[celery]
# Put celery stuff here
-# place plugins here---each in their own subsection of [plugins]. see
-# documentation for details.
+# Place plugins here, each in their own subsection of [plugins].
+# See http://docs.mediagoblin.org/siteadmin/plugins.html for details.
[plugins]
[[mediagoblin.plugins.geolocation]]
+[[mediagoblin.plugins.basic_auth]]
+[[mediagoblin.media_types.image]]
diff --git a/mediagoblin/_version.py b/mediagoblin/_version.py
index 8437be8b..94629775 100644
--- a/mediagoblin/_version.py
+++ b/mediagoblin/_version.py
@@ -23,4 +23,4 @@
# see http://www.python.org/dev/peps/pep-0386/
-__version__ = "0.4.0.dev"
+__version__ = "0.5.0.dev"
diff --git a/mediagoblin/app.py b/mediagoblin/app.py
index bf0e0f13..57e09e49 100644
--- a/mediagoblin/app.py
+++ b/mediagoblin/app.py
@@ -29,6 +29,7 @@ from mediagoblin.tools import common, session, translate, template
from mediagoblin.tools.response import render_http_exception
from mediagoblin.tools.theme import register_themes
from mediagoblin.tools import request as mg_request
+from mediagoblin.media_types.tools import media_type_warning
from mediagoblin.mg_globals import setup_globals
from mediagoblin.init.celery import setup_celery_from_config
from mediagoblin.init.plugins import setup_plugins
@@ -37,6 +38,8 @@ from mediagoblin.init import (get_jinja_loader, get_staticdirector,
setup_storage)
from mediagoblin.tools.pluginapi import PluginManager, hook_transform
from mediagoblin.tools.crypto import setup_crypto
+from mediagoblin.auth.tools import check_auth_enabled, no_auth_logout
+from mediagoblin import notifications
_log = logging.getLogger(__name__)
@@ -67,6 +70,8 @@ class MediaGoblinApp(object):
# Open and setup the config
global_config, app_config = setup_global_and_app_config(config_path)
+ media_type_warning()
+
setup_crypto()
##########################################
@@ -85,7 +90,7 @@ class MediaGoblinApp(object):
setup_plugins()
# Set up the database
- self.db = setup_database()
+ self.db = setup_database(app_config['run_migrations'])
# Register themes
self.theme_registry, self.current_theme = register_themes(app_config)
@@ -97,6 +102,11 @@ class MediaGoblinApp(object):
PluginManager().get_template_paths()
)
+ # Check if authentication plugin is enabled and respond accordingly.
+ self.auth = check_auth_enabled()
+ if not self.auth:
+ app_config['allow_comments'] = False
+
# Set up storage systems
self.public_store, self.queue_store = setup_storage()
@@ -186,8 +196,14 @@ class MediaGoblinApp(object):
request.urlgen = build_proxy
+ # Log user out if authentication_disabled
+ no_auth_logout(request)
+
+ request.notifications = notifications
+
mg_request.setup_user_in_request(request)
+ request.controller_name = None
try:
found_rule, url_values = map_adapter.match(return_rule=True)
request.matchdict = url_values
@@ -201,6 +217,9 @@ class MediaGoblinApp(object):
exc.get_description(environ))(environ, start_response)
controller = endpoint_to_controller(found_rule)
+ # Make a reference to the controller's symbolic name on the request...
+ # used for lazy context modification
+ request.controller_name = found_rule.endpoint
# pass the request through our meddleware classes
try:
diff --git a/mediagoblin/auth/__init__.py b/mediagoblin/auth/__init__.py
index 621845ba..be5d0eed 100644
--- a/mediagoblin/auth/__init__.py
+++ b/mediagoblin/auth/__init__.py
@@ -13,3 +13,32 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+from mediagoblin.tools.pluginapi import hook_handle, hook_runall
+
+
+def get_user(**kwargs):
+ """ Takes a kwarg such as username and returns a user object """
+ return hook_handle("auth_get_user", **kwargs)
+
+
+def create_user(register_form):
+ results = hook_runall("auth_create_user", register_form)
+ return results[0]
+
+
+def extra_validation(register_form):
+ from mediagoblin.auth.tools import basic_extra_validation
+
+ extra_validation_passes = basic_extra_validation(register_form)
+ if False in hook_runall("auth_extra_validation", register_form):
+ extra_validation_passes = False
+ return extra_validation_passes
+
+
+def gen_password_hash(raw_pass, extra_salt=None):
+ return hook_handle("auth_gen_password_hash", raw_pass, extra_salt)
+
+
+def check_password(raw_pass, stored_hash, extra_salt=None):
+ return hook_handle("auth_check_password",
+ raw_pass, stored_hash, extra_salt)
diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py
index 33e1f45c..865502e9 100644
--- a/mediagoblin/auth/forms.py
+++ b/mediagoblin/auth/forms.py
@@ -16,61 +16,8 @@
import wtforms
-from mediagoblin.tools.mail import normalize_email
from mediagoblin.tools.translate import lazy_pass_to_ugettext as _
-
-def normalize_user_or_email_field(allow_email=True, allow_user=True):
- """Check if we were passed a field that matches a username and/or email pattern
-
- This is useful for fields that can take either a username or email
- address. Use the parameters if you want to only allow a username for
- instance"""
- message = _(u'Invalid User name or email address.')
- nomail_msg = _(u"This field does not take email addresses.")
- nouser_msg = _(u"This field requires an email address.")
-
- def _normalize_field(form, field):
- email = u'@' in field.data
- if email: # normalize email address casing
- if not allow_email:
- raise wtforms.ValidationError(nomail_msg)
- wtforms.validators.Email()(form, field)
- field.data = normalize_email(field.data)
- else: # lower case user names
- if not allow_user:
- raise wtforms.ValidationError(nouser_msg)
- wtforms.validators.Length(min=3, max=30)(form, field)
- wtforms.validators.Regexp(r'^\w+$')(form, field)
- field.data = field.data.lower()
- if field.data is None: # should not happen, but be cautious anyway
- raise wtforms.ValidationError(message)
- return _normalize_field
-
-
-class RegistrationForm(wtforms.Form):
- username = wtforms.TextField(
- _('Username'),
- [wtforms.validators.Required(),
- normalize_user_or_email_field(allow_email=False)])
- password = wtforms.PasswordField(
- _('Password'),
- [wtforms.validators.Required(),
- wtforms.validators.Length(min=5, max=1024)])
- email = wtforms.TextField(
- _('Email address'),
- [wtforms.validators.Required(),
- normalize_user_or_email_field(allow_user=False)])
-
-
-class LoginForm(wtforms.Form):
- username = wtforms.TextField(
- _('Username or Email'),
- [wtforms.validators.Required(),
- normalize_user_or_email_field()])
- password = wtforms.PasswordField(
- _('Password'),
- [wtforms.validators.Required(),
- wtforms.validators.Length(min=5, max=1024)])
+from mediagoblin.auth.tools import normalize_user_or_email_field
class ForgotPassForm(wtforms.Form):
@@ -85,9 +32,6 @@ class ChangePassForm(wtforms.Form):
'Password',
[wtforms.validators.Required(),
wtforms.validators.Length(min=5, max=1024)])
- userid = wtforms.HiddenField(
- '',
- [wtforms.validators.Required()])
token = wtforms.HiddenField(
'',
[wtforms.validators.Required()])
diff --git a/mediagoblin/auth/tools.py b/mediagoblin/auth/tools.py
new file mode 100644
index 00000000..579775ff
--- /dev/null
+++ b/mediagoblin/auth/tools.py
@@ -0,0 +1,210 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import logging
+import wtforms
+
+from mediagoblin import mg_globals
+from mediagoblin.tools.crypto import get_timed_signer_url
+from mediagoblin.db.models import User
+from mediagoblin.tools.mail import (normalize_email, send_email,
+ email_debug_message)
+from mediagoblin.tools.template import render_template
+from mediagoblin.tools.translate import lazy_pass_to_ugettext as _
+from mediagoblin.tools.pluginapi import hook_handle
+from mediagoblin import auth
+
+_log = logging.getLogger(__name__)
+
+
+def normalize_user_or_email_field(allow_email=True, allow_user=True):
+ """
+ Check if we were passed a field that matches a username and/or email
+ pattern.
+
+ This is useful for fields that can take either a username or email
+ address. Use the parameters if you want to only allow a username for
+ instance"""
+ message = _(u'Invalid User name or email address.')
+ nomail_msg = _(u"This field does not take email addresses.")
+ nouser_msg = _(u"This field requires an email address.")
+
+ def _normalize_field(form, field):
+ email = u'@' in field.data
+ if email: # normalize email address casing
+ if not allow_email:
+ raise wtforms.ValidationError(nomail_msg)
+ wtforms.validators.Email()(form, field)
+ field.data = normalize_email(field.data)
+ else: # lower case user names
+ if not allow_user:
+ raise wtforms.ValidationError(nouser_msg)
+ wtforms.validators.Length(min=3, max=30)(form, field)
+ wtforms.validators.Regexp(r'^\w+$')(form, field)
+ field.data = field.data.lower()
+ if field.data is None: # should not happen, but be cautious anyway
+ raise wtforms.ValidationError(message)
+ return _normalize_field
+
+
+EMAIL_VERIFICATION_TEMPLATE = (
+ u"{uri}?"
+ u"token={verification_key}")
+
+
+def send_verification_email(user, request, email=None,
+ rendered_email=None):
+ """
+ Send the verification email to users to activate their accounts.
+
+ Args:
+ - user: a user object
+ - request: the request
+ """
+ if not email:
+ email = user.email
+
+ if not rendered_email:
+ verification_key = get_timed_signer_url('mail_verification_token') \
+ .dumps(user.id)
+ rendered_email = render_template(
+ request, 'mediagoblin/auth/verification_email.txt',
+ {'username': user.username,
+ 'verification_url': EMAIL_VERIFICATION_TEMPLATE.format(
+ uri=request.urlgen('mediagoblin.auth.verify_email',
+ qualified=True),
+ verification_key=verification_key)})
+
+ # TODO: There is no error handling in place
+ send_email(
+ mg_globals.app_config['email_sender_address'],
+ [email],
+ # TODO
+ # Due to the distributed nature of GNU MediaGoblin, we should
+ # find a way to send some additional information about the
+ # specific GNU MediaGoblin instance in the subject line. For
+ # example "GNU MediaGoblin @ Wandborg - [...]".
+ 'GNU MediaGoblin - Verify your email!',
+ rendered_email)
+
+
+EMAIL_FP_VERIFICATION_TEMPLATE = (
+ u"{uri}?"
+ u"token={fp_verification_key}")
+
+
+def send_fp_verification_email(user, request):
+ """
+ Send the verification email to users to change their password.
+
+ Args:
+ - user: a user object
+ - request: the request
+ """
+ fp_verification_key = get_timed_signer_url('mail_verification_token') \
+ .dumps(user.id)
+
+ rendered_email = render_template(
+ request, 'mediagoblin/auth/fp_verification_email.txt',
+ {'username': user.username,
+ 'verification_url': EMAIL_FP_VERIFICATION_TEMPLATE.format(
+ uri=request.urlgen('mediagoblin.auth.verify_forgot_password',
+ qualified=True),
+ fp_verification_key=fp_verification_key)})
+
+ # TODO: There is no error handling in place
+ send_email(
+ mg_globals.app_config['email_sender_address'],
+ [user.email],
+ 'GNU MediaGoblin - Change forgotten password!',
+ rendered_email)
+
+
+def basic_extra_validation(register_form, *args):
+ users_with_username = User.query.filter_by(
+ username=register_form.username.data).count()
+ users_with_email = User.query.filter_by(
+ email=register_form.email.data).count()
+
+ extra_validation_passes = True
+
+ if users_with_username:
+ register_form.username.errors.append(
+ _(u'Sorry, a user with that name already exists.'))
+ extra_validation_passes = False
+ if users_with_email:
+ register_form.email.errors.append(
+ _(u'Sorry, a user with that email address already exists.'))
+ extra_validation_passes = False
+
+ return extra_validation_passes
+
+
+def register_user(request, register_form):
+ """ Handle user registration """
+ extra_validation_passes = auth.extra_validation(register_form)
+
+ if extra_validation_passes:
+ # Create the user
+ user = auth.create_user(register_form)
+
+ # log the user in
+ request.session['user_id'] = unicode(user.id)
+ request.session.save()
+
+ # send verification email
+ email_debug_message(request)
+ send_verification_email(user, request)
+
+ return user
+
+ return None
+
+
+def check_login_simple(username, password):
+ user = auth.get_user(username=username)
+ if not user:
+ _log.info("User %r not found", username)
+ hook_handle("auth_fake_login_attempt")
+ return None
+ if not auth.check_password(password, user.pw_hash):
+ _log.warn("Wrong password for %r", username)
+ return None
+ _log.info("Logging %r in", username)
+ return user
+
+
+def check_auth_enabled():
+ if not hook_handle('authentication'):
+ _log.warning('No authentication is enabled')
+ return False
+ else:
+ return True
+
+
+def no_auth_logout(request):
+ """Log out the user if authentication_disabled, but don't delete the messages"""
+ if not mg_globals.app.auth and 'user_id' in request.session:
+ del request.session['user_id']
+ request.session.save()
+
+
+def create_basic_user(form):
+ user = User()
+ user.username = form.username.data
+ user.email = form.email.data
+ user.save()
+ return user
diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py
index dc408911..d54762b0 100644
--- a/mediagoblin/auth/views.py
+++ b/mediagoblin/auth/views.py
@@ -14,82 +14,43 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import uuid
-import datetime
+from itsdangerous import BadSignature
from mediagoblin import messages, mg_globals
from mediagoblin.db.models import User
+from mediagoblin.tools.crypto import get_timed_signer_url
+from mediagoblin.decorators import auth_enabled, allow_registration
from mediagoblin.tools.response import render_to_response, redirect, render_404
from mediagoblin.tools.translate import pass_to_ugettext as _
-from mediagoblin.auth import lib as auth_lib
+from mediagoblin.tools.mail import email_debug_message
+from mediagoblin.tools.pluginapi import hook_handle
from mediagoblin.auth import forms as auth_forms
-from mediagoblin.auth.lib import send_verification_email, \
- send_fp_verification_email
-from sqlalchemy import or_
-
-def email_debug_message(request):
- """
- If the server is running in email debug mode (which is
- the current default), give a debug message to the user
- so that they have an idea where to find their email.
- """
- if mg_globals.app_config['email_debug_mode']:
- # DEBUG message, no need to translate
- messages.add_message(request, messages.DEBUG,
- u"This instance is running in email debug mode. "
- u"The email will be on the console of the server process.")
+from mediagoblin.auth.tools import (send_verification_email, register_user,
+ send_fp_verification_email,
+ check_login_simple)
+from mediagoblin import auth
+@allow_registration
+@auth_enabled
def register(request):
"""The registration view.
Note that usernames will always be lowercased. Email domains are lowercased while
the first part remains case-sensitive.
"""
- # Redirects to indexpage if registrations are disabled
- if not mg_globals.app_config["allow_registration"]:
- messages.add_message(
- request,
- messages.WARNING,
- _('Sorry, registration is disabled on this instance.'))
- return redirect(request, "index")
+ if 'pass_auth' not in request.template_env.globals:
+ redirect_name = hook_handle('auth_no_pass_redirect')
+ return redirect(request, 'mediagoblin.plugins.{0}.register'.format(
+ redirect_name))
- register_form = auth_forms.RegistrationForm(request.form)
+ register_form = hook_handle("auth_get_registration_form", request)
if request.method == 'POST' and register_form.validate():
# TODO: Make sure the user doesn't exist already
- users_with_username = User.query.filter_by(username=register_form.data['username']).count()
- users_with_email = User.query.filter_by(email=register_form.data['email']).count()
-
- extra_validation_passes = True
-
- if users_with_username:
- register_form.username.errors.append(
- _(u'Sorry, a user with that name already exists.'))
- extra_validation_passes = False
- if users_with_email:
- register_form.email.errors.append(
- _(u'Sorry, a user with that email address already exists.'))
- extra_validation_passes = False
-
- if extra_validation_passes:
- # Create the user
- user = User()
- user.username = register_form.data['username']
- user.email = register_form.data['email']
- user.pw_hash = auth_lib.bcrypt_gen_password_hash(
- register_form.password.data)
- user.verification_key = unicode(uuid.uuid4())
- user.save()
-
- # log the user in
- request.session['user_id'] = unicode(user.id)
- request.session.save()
-
- # send verification email
- email_debug_message(request)
- send_verification_email(user, request)
+ user = register_user(request, register_form)
+ if user:
# redirect the user to their homepage... there will be a
# message waiting for them to verify their email
return redirect(
@@ -99,33 +60,36 @@ def register(request):
return render_to_response(
request,
'mediagoblin/auth/register.html',
- {'register_form': register_form})
+ {'register_form': register_form,
+ 'post_url': request.urlgen('mediagoblin.auth.register')})
+@auth_enabled
def login(request):
"""
MediaGoblin login view.
If you provide the POST with 'next', it'll redirect to that view.
"""
- login_form = auth_forms.LoginForm(request.form)
+ if 'pass_auth' not in request.template_env.globals:
+ redirect_name = hook_handle('auth_no_pass_redirect')
+ return redirect(request, 'mediagoblin.plugins.{0}.login'.format(
+ redirect_name))
+
+ login_form = hook_handle("auth_get_login_form", request)
login_failed = False
if request.method == 'POST':
-
- username = login_form.data['username']
+ username = login_form.username.data
if login_form.validate():
- user = User.query.filter(
- or_(
- User.username == username,
- User.email == username,
+ user = check_login_simple(username, login_form.password.data)
- )).first()
-
- if user and user.check_login(login_form.password.data):
+ if user:
# set up login in session
+ if login_form.stay_logged_in.data:
+ request.session['stay_logged_in'] = True
request.session['user_id'] = unicode(user.id)
request.session.save()
@@ -134,10 +98,6 @@ def login(request):
else:
return redirect(request, "index")
- # Some failure during login occured if we are here!
- # Prevent detecting who's on this system by testing login
- # attempt timings
- auth_lib.fake_login_attempt()
login_failed = True
return render_to_response(
@@ -146,6 +106,7 @@ def login(request):
{'login_form': login_form,
'next': request.GET.get('next') or request.form.get('next'),
'login_failed': login_failed,
+ 'post_url': request.urlgen('mediagoblin.auth.login'),
'allow_registration': mg_globals.app_config["allow_registration"]})
@@ -164,16 +125,28 @@ def verify_email(request):
you are lucky :)
"""
# If we don't have userid and token parameters, we can't do anything; 404
- if not 'userid' in request.GET or not 'token' in request.GET:
+ if not 'token' in request.GET:
return render_404(request)
- user = User.query.filter_by(id=request.args['userid']).first()
+ # Catch error if token is faked or expired
+ try:
+ token = get_timed_signer_url("mail_verification_token") \
+ .loads(request.GET['token'], max_age=10*24*3600)
+ except BadSignature:
+ messages.add_message(
+ request,
+ messages.ERROR,
+ _('The verification key or user id is incorrect.'))
- if user and user.verification_key == unicode(request.GET['token']):
+ return redirect(
+ request,
+ 'index')
+
+ user = User.query.filter_by(id=int(token)).first()
+
+ if user and user.email_verified is False:
user.status = u'active'
user.email_verified = True
- user.verification_key = None
-
user.save()
messages.add_message(
@@ -215,9 +188,6 @@ def resend_activation(request):
return redirect(request, "mediagoblin.user_pages.user_home", user=request.user['username'])
- request.user.verification_key = unicode(uuid.uuid4())
- request.user.save()
-
email_debug_message(request)
send_verification_email(request.user, request)
@@ -237,13 +207,16 @@ def forgot_password(request):
Sends an email with an url to renew forgotten password.
Use GET querystring parameter 'username' to pre-populate the input field
"""
+ if not 'pass_auth' in request.template_env.globals:
+ return redirect(request, 'index')
+
fp_form = auth_forms.ForgotPassForm(request.form,
username=request.args.get('username'))
if not (request.method == 'POST' and fp_form.validate()):
# Either GET request, or invalid form submitted. Display the template
return render_to_response(request,
- 'mediagoblin/auth/forgot_password.html', {'fp_form': fp_form})
+ 'mediagoblin/auth/forgot_password.html', {'fp_form': fp_form,})
# If we are here: method == POST and form is valid. username casing
# has been sanitized. Store if a user was found by email. We should
@@ -284,11 +257,6 @@ def forgot_password(request):
# SUCCESS. Send reminder and return to login page
if user:
- user.fp_verification_key = unicode(uuid.uuid4())
- user.fp_token_expire = datetime.datetime.now() + \
- datetime.timedelta(days=10)
- user.save()
-
email_debug_message(request)
send_fp_verification_email(user, request)
@@ -303,31 +271,44 @@ def verify_forgot_password(request):
"""
# get form data variables, and specifically check for presence of token
formdata = _process_for_token(request)
- if not formdata['has_userid_and_token']:
+ if not formdata['has_token']:
return render_404(request)
- formdata_token = formdata['vars']['token']
- formdata_userid = formdata['vars']['userid']
formdata_vars = formdata['vars']
+ # Catch error if token is faked or expired
+ try:
+ token = get_timed_signer_url("mail_verification_token") \
+ .loads(formdata_vars['token'], max_age=10*24*3600)
+ except BadSignature:
+ messages.add_message(
+ request,
+ messages.ERROR,
+ _('The verification key or user id is incorrect.'))
+
+ return redirect(
+ request,
+ 'index')
+
# check if it's a valid user id
- user = User.query.filter_by(id=formdata_userid).first()
+ user = User.query.filter_by(id=int(token)).first()
+
+ # no user in db
if not user:
- return render_404(request)
+ messages.add_message(
+ request, messages.ERROR,
+ _('The user id is incorrect.'))
+ return redirect(
+ request, 'index')
- # check if we have a real user and correct token
- if ((user and user.fp_verification_key and
- user.fp_verification_key == unicode(formdata_token) and
- datetime.datetime.now() < user.fp_token_expire
- and user.email_verified and user.status == 'active')):
+ # check if user active and has email verified
+ if user.email_verified and user.status == 'active':
cp_form = auth_forms.ChangePassForm(formdata_vars)
if request.method == 'POST' and cp_form.validate():
- user.pw_hash = auth_lib.bcrypt_gen_password_hash(
+ user.pw_hash = auth.gen_password_hash(
cp_form.password.data)
- user.fp_verification_key = None
- user.fp_token_expire = None
user.save()
messages.add_message(
@@ -339,12 +320,22 @@ def verify_forgot_password(request):
return render_to_response(
request,
'mediagoblin/auth/change_fp.html',
- {'cp_form': cp_form})
+ {'cp_form': cp_form,})
- # in case there is a valid id but no user with that id in the db
- # or the token expired
- else:
- return render_404(request)
+ if not user.email_verified:
+ messages.add_message(
+ request, messages.ERROR,
+ _('You need to verify your email before you can reset your'
+ ' password.'))
+
+ if not user.status == 'active':
+ messages.add_message(
+ request, messages.ERROR,
+ _('You are no longer an active user. Please contact the system'
+ ' admin to reactivate your accoutn.'))
+
+ return redirect(
+ request, 'index')
def _process_for_token(request):
@@ -362,7 +353,6 @@ def _process_for_token(request):
formdata = {
'vars': formdata_vars,
- 'has_userid_and_token':
- 'userid' in formdata_vars and 'token' in formdata_vars}
+ 'has_token': 'token' in formdata_vars}
return formdata
diff --git a/mediagoblin/config_spec.ini b/mediagoblin/config_spec.ini
index 2af4adb2..d2ada163 100644
--- a/mediagoblin/config_spec.ini
+++ b/mediagoblin/config_spec.ini
@@ -5,12 +5,13 @@ html_title = string(default="GNU MediaGoblin")
# link to source for this MediaGoblin site
source_link = string(default="https://gitorious.org/mediagoblin/mediagoblin")
-# Enabled media types
-media_types = string_list(default=list("mediagoblin.media_types.image"))
-
# database stuff
sql_engine = string(default="sqlite:///%(here)s/mediagoblin.db")
+# This flag is used during testing to allow use of in-memory SQLite
+# databases. It is not recommended to be used on a running instance.
+run_migrations = boolean(default=False)
+
# Where temporary files used in processing and etc are kept
workbench_path = string(default="%(here)s/user_dev/media/workbench")
@@ -22,9 +23,10 @@ direct_remote_path = string(default="/mgoblin_static/")
# set to false to enable sending notices
email_debug_mode = boolean(default=True)
+email_smtp_use_ssl = boolean(default=False)
email_sender_address = string(default="notice@mediagoblin.example.org")
email_smtp_host = string(default='')
-email_smtp_port = integer(default=25)
+email_smtp_port = integer(default=0)
email_smtp_user = string(default=None)
email_smtp_pass = string(default=None)
@@ -69,6 +71,10 @@ theme_web_path = string(default="/theme_static/")
theme_linked_assets_dir = string(default="%(here)s/user_dev/theme_static/")
theme = string()
+# plugin default assets directory
+plugin_web_path = string(default="/plugin_static/")
+plugin_linked_assets_dir = string(default="%(here)s/user_dev/plugin_static/")
+
[storage:publicstore]
storage_class = string(default="mediagoblin.storage.filestorage:BasicFileStorage")
@@ -130,7 +136,7 @@ spectrogram_fft_size = integer(default=4096)
thumbnail_font = string(default=None)
[media_type:mediagoblin.media_types.pdf]
-pdf_js = boolean(default=False)
+pdf_js = boolean(default=True)
[celery]
diff --git a/mediagoblin/db/base.py b/mediagoblin/db/base.py
index 699a503a..c0cefdc2 100644
--- a/mediagoblin/db/base.py
+++ b/mediagoblin/db/base.py
@@ -24,18 +24,6 @@ Session = scoped_session(sessionmaker())
class GMGTableBase(object):
query = Session.query_property()
- @classmethod
- def find(cls, query_dict):
- return cls.query.filter_by(**query_dict)
-
- @classmethod
- def find_one(cls, query_dict):
- return cls.query.filter_by(**query_dict).first()
-
- @classmethod
- def one(cls, query_dict):
- return cls.find(query_dict).one()
-
def get(self, key):
return getattr(self, key)
diff --git a/mediagoblin/db/migration_tools.py b/mediagoblin/db/migration_tools.py
index c0c7e998..aa22ef94 100644
--- a/mediagoblin/db/migration_tools.py
+++ b/mediagoblin/db/migration_tools.py
@@ -175,8 +175,7 @@ class MigrationManager(object):
if self.name == u'__main__':
return u"main mediagoblin tables"
else:
- # TODO: Use the friendlier media manager "human readable" name
- return u'media type "%s"' % self.name
+ return u'plugin "%s"' % self.name
def init_or_migrate(self):
"""
diff --git a/mediagoblin/db/migrations.py b/mediagoblin/db/migrations.py
index 2c553396..fe4ffb3e 100644
--- a/mediagoblin/db/migrations.py
+++ b/mediagoblin/db/migrations.py
@@ -26,7 +26,7 @@ from sqlalchemy.sql import and_
from migrate.changeset.constraint import UniqueConstraint
from mediagoblin.db.migration_tools import RegisterMigration, inspect_table
-from mediagoblin.db.models import MediaEntry, Collection, User
+from mediagoblin.db.models import MediaEntry, Collection, User, MediaComment
MIGRATIONS = {}
@@ -287,3 +287,95 @@ def unique_collections_slug(db):
constraint.create()
db.commit()
+
+@RegisterMigration(11, MIGRATIONS)
+def drop_token_related_User_columns(db):
+ """
+ Drop unneeded columns from the User table after switching to using
+ itsdangerous tokens for email and forgot password verification.
+ """
+ metadata = MetaData(bind=db.bind)
+ user_table = inspect_table(metadata, 'core__users')
+
+ verification_key = user_table.columns['verification_key']
+ fp_verification_key = user_table.columns['fp_verification_key']
+ fp_token_expire = user_table.columns['fp_token_expire']
+
+ verification_key.drop()
+ fp_verification_key.drop()
+ fp_token_expire.drop()
+
+ db.commit()
+
+
+class CommentSubscription_v0(declarative_base()):
+ __tablename__ = 'core__comment_subscriptions'
+ id = Column(Integer, primary_key=True)
+
+ created = Column(DateTime, nullable=False, default=datetime.datetime.now)
+
+ media_entry_id = Column(Integer, ForeignKey(MediaEntry.id), nullable=False)
+
+ user_id = Column(Integer, ForeignKey(User.id), nullable=False)
+
+ notify = Column(Boolean, nullable=False, default=True)
+ send_email = Column(Boolean, nullable=False, default=True)
+
+
+class Notification_v0(declarative_base()):
+ __tablename__ = 'core__notifications'
+ id = Column(Integer, primary_key=True)
+ type = Column(Unicode)
+
+ created = Column(DateTime, nullable=False, default=datetime.datetime.now)
+
+ user_id = Column(Integer, ForeignKey(User.id), nullable=False,
+ index=True)
+ seen = Column(Boolean, default=lambda: False, index=True)
+
+
+class CommentNotification_v0(Notification_v0):
+ __tablename__ = 'core__comment_notifications'
+ id = Column(Integer, ForeignKey(Notification_v0.id), primary_key=True)
+
+ subject_id = Column(Integer, ForeignKey(MediaComment.id))
+
+
+class ProcessingNotification_v0(Notification_v0):
+ __tablename__ = 'core__processing_notifications'
+
+ id = Column(Integer, ForeignKey(Notification_v0.id), primary_key=True)
+
+ subject_id = Column(Integer, ForeignKey(MediaEntry.id))
+
+
+@RegisterMigration(12, MIGRATIONS)
+def add_new_notification_tables(db):
+ metadata = MetaData(bind=db.bind)
+
+ user_table = inspect_table(metadata, 'core__users')
+ mediaentry_table = inspect_table(metadata, 'core__media_entries')
+ mediacomment_table = inspect_table(metadata, 'core__media_comments')
+
+ CommentSubscription_v0.__table__.create(db.bind)
+
+ Notification_v0.__table__.create(db.bind)
+ CommentNotification_v0.__table__.create(db.bind)
+ ProcessingNotification_v0.__table__.create(db.bind)
+
+
+@RegisterMigration(13, MIGRATIONS)
+def pw_hash_nullable(db):
+ """Make pw_hash column nullable"""
+ metadata = MetaData(bind=db.bind)
+ user_table = inspect_table(metadata, "core__users")
+
+ user_table.c.pw_hash.alter(nullable=True)
+
+ # sqlite+sqlalchemy seems to drop this constraint during the
+ # migration, so we add it back here for now a bit manually.
+ if db.bind.url.drivername == 'sqlite':
+ constraint = UniqueConstraint('username', table=user_table)
+ constraint.create()
+
+ db.commit()
diff --git a/mediagoblin/db/mixin.py b/mediagoblin/db/mixin.py
index 388bac89..57b27d83 100644
--- a/mediagoblin/db/mixin.py
+++ b/mediagoblin/db/mixin.py
@@ -28,25 +28,20 @@ real objects.
"""
import uuid
+import re
+from datetime import datetime
from werkzeug.utils import cached_property
from mediagoblin import mg_globals
-from mediagoblin.auth import lib as auth_lib
-from mediagoblin.media_types import get_media_managers, FileTypeNotSupported
+from mediagoblin.media_types import FileTypeNotSupported
from mediagoblin.tools import common, licenses
+from mediagoblin.tools.pluginapi import hook_handle
from mediagoblin.tools.text import cleaned_markdown_conversion
from mediagoblin.tools.url import slugify
class UserMixin(object):
- def check_login(self, password):
- """
- See if a user can login with this password
- """
- return auth_lib.bcrypt_check_password(
- password, self.pw_hash)
-
@property
def bio_html(self):
return cleaned_markdown_conversion(self.bio)
@@ -208,14 +203,14 @@ class MediaEntryMixin(GenerateSlugMixin):
Raises FileTypeNotSupported in case no such manager is enabled
"""
- # TODO, we should be able to make this a simple lookup rather
- # than iterating through all media managers.
- for media_type, manager in get_media_managers():
- if media_type == self.media_type:
- return manager(self)
+ manager = hook_handle(('media_manager', self.media_type))
+ if manager:
+ return manager(self)
+
# Not found? Then raise an error
raise FileTypeNotSupported(
- "MediaManager not in enabled types. Check media_types in config?")
+ "MediaManager not in enabled types. Check media_type plugins are"
+ " enabled in config?")
def get_fail_exception(self):
"""
@@ -229,15 +224,60 @@ class MediaEntryMixin(GenerateSlugMixin):
return licenses.get_license_by_url(self.license or "")
def exif_display_iter(self):
- from mediagoblin.tools.exif import USEFUL_TAGS
+ if not self.media_data:
+ return
+ exif_all = self.media_data.get("exif_all")
+ for key in exif_all:
+ label = re.sub('(.)([A-Z][a-z]+)', r'\1 \2', key)
+ yield label.replace('EXIF', '').replace('Image', ''), exif_all[key]
+
+ def exif_display_data_short(self):
+ """Display a very short practical version of exif info"""
if not self.media_data:
return
+
exif_all = self.media_data.get("exif_all")
- for key in USEFUL_TAGS:
- if key in exif_all:
- yield key, exif_all[key]
+ exif_short = {}
+
+ if 'Image DateTimeOriginal' in exif_all:
+ # format date taken
+ takendate = datetime.datetime.strptime(
+ exif_all['Image DateTimeOriginal']['printable'],
+ '%Y:%m:%d %H:%M:%S').date()
+ taken = takendate.strftime('%B %d %Y')
+
+ exif_short.update({'Date Taken': taken})
+
+ aperture = None
+ if 'EXIF FNumber' in exif_all:
+ fnum = str(exif_all['EXIF FNumber']['printable']).split('/')
+
+ # calculate aperture
+ if len(fnum) == 2:
+ aperture = "f/%.1f" % (float(fnum[0])/float(fnum[1]))
+ elif fnum[0] != 'None':
+ aperture = "f/%s" % (fnum[0])
+
+ if aperture:
+ exif_short.update({'Aperture': aperture})
+
+ short_keys = [
+ ('Camera', 'Image Model', None),
+ ('Exposure', 'EXIF ExposureTime', lambda x: '%s sec' % x),
+ ('ISO Speed', 'EXIF ISOSpeedRatings', None),
+ ('Focal Length', 'EXIF FocalLength', lambda x: '%s mm' % x)]
+
+ for label, key, fmt_func in short_keys:
+ try:
+ val = fmt_func(exif_all[key]['printable']) if fmt_func \
+ else exif_all[key]['printable']
+ exif_short.update({label: val})
+ except KeyError:
+ pass
+
+ return exif_short
class MediaCommentMixin(object):
@@ -249,6 +289,13 @@ class MediaCommentMixin(object):
"""
return cleaned_markdown_conversion(self.content)
+ def __repr__(self):
+ return '<{klass} #{id} {author} "{comment}">'.format(
+ klass=self.__class__.__name__,
+ id=self.id,
+ author=self.get_author,
+ comment=self.content)
+
class CollectionMixin(GenerateSlugMixin):
def check_slug_used(self, slug):
diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py
index 2412706e..826d47ba 100644
--- a/mediagoblin/db/models.py
+++ b/mediagoblin/db/models.py
@@ -24,15 +24,17 @@ import datetime
from sqlalchemy import Column, Integer, Unicode, UnicodeText, DateTime, \
Boolean, ForeignKey, UniqueConstraint, PrimaryKeyConstraint, \
SmallInteger
-from sqlalchemy.orm import relationship, backref
+from sqlalchemy.orm import relationship, backref, with_polymorphic
from sqlalchemy.orm.collections import attribute_mapped_collection
from sqlalchemy.sql.expression import desc
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.util import memoized_property
+
from mediagoblin.db.extratypes import PathTupleWithSlashes, JSONEncoded
from mediagoblin.db.base import Base, DictReadAttrProxy
-from mediagoblin.db.mixin import UserMixin, MediaEntryMixin, MediaCommentMixin, CollectionMixin, CollectionItemMixin
+from mediagoblin.db.mixin import UserMixin, MediaEntryMixin, \
+ MediaCommentMixin, CollectionMixin, CollectionItemMixin
from mediagoblin.tools.files import delete_media_files
from mediagoblin.tools.common import import_component
@@ -55,21 +57,22 @@ class User(Base, UserMixin):
id = Column(Integer, primary_key=True)
username = Column(Unicode, nullable=False, unique=True)
+ # Note: no db uniqueness constraint on email because it's not
+ # reliable (many email systems case insensitive despite against
+ # the RFC) and because it would be a mess to implement at this
+ # point.
email = Column(Unicode, nullable=False)
- created = Column(DateTime, nullable=False, default=datetime.datetime.now)
- pw_hash = Column(Unicode, nullable=False)
+ pw_hash = Column(Unicode)
email_verified = Column(Boolean, default=False)
+ created = Column(DateTime, nullable=False, default=datetime.datetime.now)
status = Column(Unicode, default=u"needs_email_verification", nullable=False)
# Intented to be nullable=False, but migrations would not work for it
# set to nullable=True implicitly.
wants_comment_notification = Column(Boolean, default=True)
license_preference = Column(Unicode)
- verification_key = Column(Unicode)
is_admin = Column(Boolean, default=False, nullable=False)
url = Column(Unicode)
bio = Column(UnicodeText) # ??
- fp_verification_key = Column(Unicode)
- fp_token_expire = Column(DateTime)
## TODO
# plugin data would be in a separate model
@@ -388,6 +391,10 @@ class MediaComment(Base, MediaCommentMixin):
backref=backref("posted_comments",
lazy="dynamic",
cascade="all, delete-orphan"))
+ get_entry = relationship(MediaEntry,
+ backref=backref("comments",
+ lazy="dynamic",
+ cascade="all, delete-orphan"))
# Cascade: Comments are somewhat owned by their MediaEntry.
# So do the full thing.
@@ -480,9 +487,103 @@ class ProcessingMetaData(Base):
return DictReadAttrProxy(self)
+class CommentSubscription(Base):
+ __tablename__ = 'core__comment_subscriptions'
+ id = Column(Integer, primary_key=True)
+
+ created = Column(DateTime, nullable=False, default=datetime.datetime.now)
+
+ media_entry_id = Column(Integer, ForeignKey(MediaEntry.id), nullable=False)
+ media_entry = relationship(MediaEntry,
+ backref=backref('comment_subscriptions',
+ cascade='all, delete-orphan'))
+
+ user_id = Column(Integer, ForeignKey(User.id), nullable=False)
+ user = relationship(User,
+ backref=backref('comment_subscriptions',
+ cascade='all, delete-orphan'))
+
+ notify = Column(Boolean, nullable=False, default=True)
+ send_email = Column(Boolean, nullable=False, default=True)
+
+ def __repr__(self):
+ return ('<{classname} #{id}: {user} {media} notify: '
+ '{notify} email: {email}>').format(
+ id=self.id,
+ classname=self.__class__.__name__,
+ user=self.user,
+ media=self.media_entry,
+ notify=self.notify,
+ email=self.send_email)
+
+
+class Notification(Base):
+ __tablename__ = 'core__notifications'
+ id = Column(Integer, primary_key=True)
+ type = Column(Unicode)
+
+ created = Column(DateTime, nullable=False, default=datetime.datetime.now)
+
+ user_id = Column(Integer, ForeignKey('core__users.id'), nullable=False,
+ index=True)
+ seen = Column(Boolean, default=lambda: False, index=True)
+ user = relationship(
+ User,
+ backref=backref('notifications', cascade='all, delete-orphan'))
+
+ __mapper_args__ = {
+ 'polymorphic_identity': 'notification',
+ 'polymorphic_on': type
+ }
+
+ def __repr__(self):
+ return '<{klass} #{id}: {user}: {subject} ({seen})>'.format(
+ id=self.id,
+ klass=self.__class__.__name__,
+ user=self.user,
+ subject=getattr(self, 'subject', None),
+ seen='unseen' if not self.seen else 'seen')
+
+
+class CommentNotification(Notification):
+ __tablename__ = 'core__comment_notifications'
+ id = Column(Integer, ForeignKey(Notification.id), primary_key=True)
+
+ subject_id = Column(Integer, ForeignKey(MediaComment.id))
+ subject = relationship(
+ MediaComment,
+ backref=backref('comment_notifications', cascade='all, delete-orphan'))
+
+ __mapper_args__ = {
+ 'polymorphic_identity': 'comment_notification'
+ }
+
+
+class ProcessingNotification(Notification):
+ __tablename__ = 'core__processing_notifications'
+
+ id = Column(Integer, ForeignKey(Notification.id), primary_key=True)
+
+ subject_id = Column(Integer, ForeignKey(MediaEntry.id))
+ subject = relationship(
+ MediaEntry,
+ backref=backref('processing_notifications',
+ cascade='all, delete-orphan'))
+
+ __mapper_args__ = {
+ 'polymorphic_identity': 'processing_notification'
+ }
+
+
+with_polymorphic(
+ Notification,
+ [ProcessingNotification, CommentNotification])
+
MODELS = [
- User, MediaEntry, Tag, MediaTag, MediaComment, Collection, CollectionItem, MediaFile, FileKeynames,
- MediaAttachmentFile, ProcessingMetaData]
+ User, MediaEntry, Tag, MediaTag, MediaComment, Collection, CollectionItem,
+ MediaFile, FileKeynames, MediaAttachmentFile, ProcessingMetaData,
+ Notification, CommentNotification, ProcessingNotification,
+ CommentSubscription]
######################################################
diff --git a/mediagoblin/db/models_v0.py b/mediagoblin/db/models_v0.py
index ec51a1f5..bdedec2e 100644
--- a/mediagoblin/db/models_v0.py
+++ b/mediagoblin/db/models_v0.py
@@ -18,6 +18,29 @@
TODO: indexes on foreignkeys, where useful.
"""
+###########################################################################
+# WHAT IS THIS FILE?
+# ------------------
+#
+# Upon occasion, someone runs into this file and wonders why we have
+# both a models.py and a models_v0.py.
+#
+# The short of it is: you can ignore this file.
+#
+# The long version is, in two parts:
+#
+# - We used to use MongoDB, then we switched to SQL and SQLAlchemy.
+# We needed to convert peoples' databases; the script we had would
+# switch them to the first version right after Mongo, convert over
+# all their tables, then run any migrations that were added after.
+#
+# - That script is now removed, but there is some discussion of
+# writing a test that would set us at the first SQL migration and
+# run everything after. If we wrote that, this file would still be
+# useful. But for now, it's legacy!
+#
+###########################################################################
+
import datetime
import sys
diff --git a/mediagoblin/db/open.py b/mediagoblin/db/open.py
index 0b1679fb..4ff0945f 100644
--- a/mediagoblin/db/open.py
+++ b/mediagoblin/db/open.py
@@ -52,10 +52,6 @@ class DatabaseMaster(object):
def load_models(app_config):
import mediagoblin.db.models
- for media_type in app_config['media_types']:
- _log.debug("Loading %s.models", media_type)
- __import__(media_type + ".models")
-
for plugin in mg_globals.global_config.get('plugins', {}).keys():
_log.debug("Loading %s.models", plugin)
try:
diff --git a/mediagoblin/db/util.py b/mediagoblin/db/util.py
index 6ffec44d..8431361a 100644
--- a/mediagoblin/db/util.py
+++ b/mediagoblin/db/util.py
@@ -24,7 +24,7 @@ from mediagoblin.db.models import MediaEntry, Tag, MediaTag, Collection
def atomic_update(table, query_dict, update_values):
- table.find(query_dict).update(update_values,
+ table.query.filter_by(**query_dict).update(update_values,
synchronize_session=False)
Session.commit()
diff --git a/mediagoblin/decorators.py b/mediagoblin/decorators.py
index f3535fcf..ca7be53c 100644
--- a/mediagoblin/decorators.py
+++ b/mediagoblin/decorators.py
@@ -18,11 +18,12 @@ from functools import wraps
from urlparse import urljoin
from werkzeug.exceptions import Forbidden, NotFound
-from werkzeug.urls import url_quote
from mediagoblin import mg_globals as mgg
+from mediagoblin import messages
from mediagoblin.db.models import MediaEntry, User
from mediagoblin.tools.response import redirect, render_404
+from mediagoblin.tools.translate import pass_to_ugettext as _
def require_active_login(controller):
@@ -86,8 +87,8 @@ def user_may_alter_collection(controller):
"""
@wraps(controller)
def wrapper(request, *args, **kwargs):
- creator_id = request.db.User.find_one(
- {'username': request.matchdict['user']}).id
+ creator_id = request.db.User.query.filter_by(
+ username=request.matchdict['user']).first().id
if not (request.user.is_admin or
request.user.id == creator_id):
raise Forbidden()
@@ -161,15 +162,15 @@ def get_user_collection(controller):
"""
@wraps(controller)
def wrapper(request, *args, **kwargs):
- user = request.db.User.find_one(
- {'username': request.matchdict['user']})
+ user = request.db.User.query.filter_by(
+ username=request.matchdict['user']).first()
if not user:
return render_404(request)
- collection = request.db.Collection.find_one(
- {'slug': request.matchdict['collection'],
- 'creator': user.id})
+ collection = request.db.Collection.query.filter_by(
+ slug=request.matchdict['collection'],
+ creator=user.id).first()
# Still no collection? Okay, 404.
if not collection:
@@ -186,14 +187,14 @@ def get_user_collection_item(controller):
"""
@wraps(controller)
def wrapper(request, *args, **kwargs):
- user = request.db.User.find_one(
- {'username': request.matchdict['user']})
+ user = request.db.User.query.filter_by(
+ username=request.matchdict['user']).first()
if not user:
return render_404(request)
- collection_item = request.db.CollectionItem.find_one(
- {'id': request.matchdict['collection_item'] })
+ collection_item = request.db.CollectionItem.query.filter_by(
+ id=request.matchdict['collection_item']).first()
# Still no collection item? Okay, 404.
if not collection_item:
@@ -235,3 +236,35 @@ def get_workbench(func):
return func(*args, workbench=workbench, **kwargs)
return new_func
+
+
+def allow_registration(controller):
+ """ Decorator for if registration is enabled"""
+ @wraps(controller)
+ def wrapper(request, *args, **kwargs):
+ if not mgg.app_config["allow_registration"]:
+ messages.add_message(
+ request,
+ messages.WARNING,
+ _('Sorry, registration is disabled on this instance.'))
+ return redirect(request, "index")
+
+ return controller(request, *args, **kwargs)
+
+ return wrapper
+
+
+def auth_enabled(controller):
+ """Decorator for if an auth plugin is enabled"""
+ @wraps(controller)
+ def wrapper(request, *args, **kwargs):
+ if not mgg.app.auth:
+ messages.add_message(
+ request,
+ messages.WARNING,
+ _('Sorry, authentication is disabled on this instance.'))
+ return redirect(request, 'index')
+
+ return controller(request, *args, **kwargs)
+
+ return wrapper
diff --git a/mediagoblin/edit/forms.py b/mediagoblin/edit/forms.py
index ef270237..85c243a0 100644
--- a/mediagoblin/edit/forms.py
+++ b/mediagoblin/edit/forms.py
@@ -16,9 +16,11 @@
import wtforms
-from mediagoblin.tools.text import tag_length_validator, TOO_LONG_TAG_WARNING
+from mediagoblin.tools.text import tag_length_validator
from mediagoblin.tools.translate import lazy_pass_to_ugettext as _
from mediagoblin.tools.licenses import licenses_as_choices
+from mediagoblin.auth.forms import normalize_user_or_email_field
+
class EditForm(wtforms.Form):
title = wtforms.TextField(
@@ -59,17 +61,12 @@ class EditProfileForm(wtforms.Form):
class EditAccountForm(wtforms.Form):
- old_password = wtforms.PasswordField(
- _('Old password'),
- description=_(
- "Enter your old password to prove you own this account."))
- new_password = wtforms.PasswordField(
- _('New password'),
- [
- wtforms.validators.Optional(),
- wtforms.validators.Length(min=6, max=30)
- ],
- id="password")
+ new_email = wtforms.TextField(
+ _('New email address'),
+ [wtforms.validators.Optional(),
+ normalize_user_or_email_field(allow_user=False)])
+ wants_comment_notification = wtforms.BooleanField(
+ description=_("Email me when others comment on my media"))
license_preference = wtforms.SelectField(
_('License preference'),
[
@@ -78,8 +75,6 @@ class EditAccountForm(wtforms.Form):
],
choices=licenses_as_choices(),
description=_('This will be your default license on upload forms.'))
- wants_comment_notification = wtforms.BooleanField(
- label=_("Email me when others comment on my media"))
class EditAttachmentsForm(wtforms.Form):
@@ -103,3 +98,16 @@ class EditCollectionForm(wtforms.Form):
description=_(
"The title part of this collection's address. "
"You usually don't need to change this."))
+
+
+class ChangePassForm(wtforms.Form):
+ old_password = wtforms.PasswordField(
+ _('Old password'),
+ [wtforms.validators.Required()],
+ description=_(
+ "Enter your old password to prove you own this account."))
+ new_password = wtforms.PasswordField(
+ _('New password'),
+ [wtforms.validators.Required(),
+ wtforms.validators.Length(min=6, max=30)],
+ id="password")
diff --git a/mediagoblin/edit/routing.py b/mediagoblin/edit/routing.py
index 035a766f..3592f708 100644
--- a/mediagoblin/edit/routing.py
+++ b/mediagoblin/edit/routing.py
@@ -24,3 +24,7 @@ add_route('mediagoblin.edit.account', '/edit/account/',
'mediagoblin.edit.views:edit_account')
add_route('mediagoblin.edit.delete_account', '/edit/account/delete/',
'mediagoblin.edit.views:delete_account')
+add_route('mediagoblin.edit.pass', '/edit/password/',
+ 'mediagoblin.edit.views:change_pass')
+add_route('mediagoblin.edit.verify_email', '/edit/verify_email/',
+ 'mediagoblin.edit.views:verify_email')
diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py
index bfcf65b5..6aa2acd9 100644
--- a/mediagoblin/edit/views.py
+++ b/mediagoblin/edit/views.py
@@ -16,25 +16,31 @@
from datetime import datetime
+from itsdangerous import BadSignature
from werkzeug.exceptions import Forbidden
from werkzeug.utils import secure_filename
from mediagoblin import messages
from mediagoblin import mg_globals
-from mediagoblin.auth import lib as auth_lib
+from mediagoblin import auth
+from mediagoblin.auth import tools as auth_tools
from mediagoblin.edit import forms
from mediagoblin.edit.lib import may_edit_media
from mediagoblin.decorators import (require_active_login, active_user_from_url,
- get_media_entry_by_id,
- user_may_alter_collection, get_user_collection)
-from mediagoblin.tools.response import render_to_response, \
- redirect, redirect_obj
+ get_media_entry_by_id, user_may_alter_collection,
+ get_user_collection)
+from mediagoblin.tools.crypto import get_timed_signer_url
+from mediagoblin.tools.mail import email_debug_message
+from mediagoblin.tools.response import (render_to_response,
+ redirect, redirect_obj, render_404)
from mediagoblin.tools.translate import pass_to_ugettext as _
+from mediagoblin.tools.template import render_template
from mediagoblin.tools.text import (
convert_to_tag_list_of_dicts, media_tags_as_string)
from mediagoblin.tools.url import slugify
from mediagoblin.db.util import check_media_slug_used, check_collection_slug_used
+from mediagoblin.db.models import User
import mimetypes
@@ -212,6 +218,10 @@ def edit_profile(request, url_user=None):
{'user': user,
'form': form})
+EMAIL_VERIFICATION_TEMPLATE = (
+ u'{uri}?'
+ u'token={verification_key}')
+
@require_active_login
def edit_account(request):
@@ -220,39 +230,22 @@ def edit_account(request):
wants_comment_notification=user.wants_comment_notification,
license_preference=user.license_preference)
- if request.method == 'POST':
- form_validated = form.validate()
-
- if form_validated and \
- form.wants_comment_notification.validate(form):
- user.wants_comment_notification = \
- form.wants_comment_notification.data
-
- if form_validated and \
- form.new_password.data or form.old_password.data:
- password_matches = auth_lib.bcrypt_check_password(
- form.old_password.data,
- user.pw_hash)
- if password_matches:
- #the entire form validates and the password matches
- user.pw_hash = auth_lib.bcrypt_gen_password_hash(
- form.new_password.data)
- else:
- form.old_password.errors.append(_('Wrong password'))
+ if request.method == 'POST' and form.validate():
+ user.wants_comment_notification = form.wants_comment_notification.data
+
+ user.license_preference = form.license_preference.data
- if form_validated and \
- form.license_preference.validate(form):
- user.license_preference = \
- form.license_preference.data
+ if form.new_email.data:
+ _update_email(request, form, user)
- if form_validated and not form.errors:
+ if not form.errors:
user.save()
messages.add_message(request,
- messages.SUCCESS,
- _("Account settings saved"))
+ messages.SUCCESS,
+ _("Account settings saved"))
return redirect(request,
- 'mediagoblin.user_pages.user_home',
- user=user.username)
+ 'mediagoblin.user_pages.user_home',
+ user=user.username)
return render_to_response(
request,
@@ -312,9 +305,9 @@ def edit_collection(request, collection):
form.slug.data, collection.id)
# Make sure there isn't already a Collection with this title
- existing_collection = request.db.Collection.find_one({
- 'creator': request.user.id,
- 'title':form.title.data})
+ existing_collection = request.db.Collection.query.filter_by(
+ creator=request.user.id,
+ title=form.title.data).first()
if existing_collection and existing_collection.id != collection.id:
messages.add_message(
@@ -345,3 +338,117 @@ def edit_collection(request, collection):
'mediagoblin/edit/edit_collection.html',
{'collection': collection,
'form': form})
+
+
+@require_active_login
+def change_pass(request):
+ # If no password authentication, no need to change your password
+ if 'pass_auth' not in request.template_env.globals:
+ return redirect(request, 'index')
+
+ form = forms.ChangePassForm(request.form)
+ user = request.user
+
+ if request.method == 'POST' and form.validate():
+
+ if not auth.check_password(
+ form.old_password.data, user.pw_hash):
+ form.old_password.errors.append(
+ _('Wrong password'))
+
+ return render_to_response(
+ request,
+ 'mediagoblin/edit/change_pass.html',
+ {'form': form,
+ 'user': user})
+
+ # Password matches
+ user.pw_hash = auth.gen_password_hash(
+ form.new_password.data)
+ user.save()
+
+ messages.add_message(
+ request, messages.SUCCESS,
+ _('Your password was changed successfully'))
+
+ return redirect(request, 'mediagoblin.edit.account')
+
+ return render_to_response(
+ request,
+ 'mediagoblin/edit/change_pass.html',
+ {'form': form,
+ 'user': user})
+
+
+def verify_email(request):
+ """
+ Email verification view for changing email address
+ """
+ # If no token, we can't do anything
+ if not 'token' in request.GET:
+ return render_404(request)
+
+ # Catch error if token is faked or expired
+ token = None
+ try:
+ token = get_timed_signer_url("mail_verification_token") \
+ .loads(request.GET['token'], max_age=10*24*3600)
+ except BadSignature:
+ messages.add_message(
+ request,
+ messages.ERROR,
+ _('The verification key or user id is incorrect.'))
+
+ return redirect(
+ request,
+ 'index')
+
+ user = User.query.filter_by(id=int(token['user'])).first()
+
+ if user:
+ user.email = token['email']
+ user.save()
+
+ messages.add_message(
+ request,
+ messages.SUCCESS,
+ _('Your email address has been verified.'))
+
+ else:
+ messages.add_message(
+ request,
+ messages.ERROR,
+ _('The verification key or user id is incorrect.'))
+
+ return redirect(
+ request, 'mediagoblin.user_pages.user_home',
+ user=user.username)
+
+
+def _update_email(request, form, user):
+ new_email = form.new_email.data
+ users_with_email = User.query.filter_by(
+ email=new_email).count()
+
+ if users_with_email:
+ form.new_email.errors.append(
+ _('Sorry, a user with that email address'
+ ' already exists.'))
+
+ elif not users_with_email:
+ verification_key = get_timed_signer_url(
+ 'mail_verification_token').dumps({
+ 'user': user.id,
+ 'email': new_email})
+
+ rendered_email = render_template(
+ request, 'mediagoblin/edit/verification.txt',
+ {'username': user.username,
+ 'verification_url': EMAIL_VERIFICATION_TEMPLATE.format(
+ uri=request.urlgen('mediagoblin.edit.verify_email',
+ qualified=True),
+ verification_key=verification_key)})
+
+ email_debug_message(request)
+ auth_tools.send_verification_email(user, request, new_email,
+ rendered_email)
diff --git a/mediagoblin/gmg_commands/__init__.py b/mediagoblin/gmg_commands/__init__.py
index 6aed4f6c..d8156126 100644
--- a/mediagoblin/gmg_commands/__init__.py
+++ b/mediagoblin/gmg_commands/__init__.py
@@ -41,11 +41,15 @@ SUBCOMMAND_MAP = {
'setup': 'mediagoblin.gmg_commands.dbupdate:dbupdate_parse_setup',
'func': 'mediagoblin.gmg_commands.dbupdate:dbupdate',
'help': 'Set up or update the SQL database'},
- 'theme': {
- 'setup': 'mediagoblin.gmg_commands.theme:theme_parser_setup',
- 'func': 'mediagoblin.gmg_commands.theme:theme',
- 'help': 'Theming commands',
- }
+ 'assetlink': {
+ 'setup': 'mediagoblin.gmg_commands.assetlink:assetlink_parser_setup',
+ 'func': 'mediagoblin.gmg_commands.assetlink:assetlink',
+ 'help': 'Link assets for themes and plugins for static serving'},
+ # 'theme': {
+ # 'setup': 'mediagoblin.gmg_commands.theme:theme_parser_setup',
+ # 'func': 'mediagoblin.gmg_commands.theme:theme',
+ # 'help': 'Theming commands',
+ # }
## These might be useful, mayyyybe, but don't really work anymore
## due to mongo change and the "versatility" of sql options.
diff --git a/mediagoblin/gmg_commands/assetlink.py b/mediagoblin/gmg_commands/assetlink.py
new file mode 100644
index 00000000..148ebe9e
--- /dev/null
+++ b/mediagoblin/gmg_commands/assetlink.py
@@ -0,0 +1,151 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+
+from mediagoblin import mg_globals
+from mediagoblin.init import setup_global_and_app_config
+from mediagoblin.gmg_commands import util as commands_util
+from mediagoblin.tools.theme import register_themes
+from mediagoblin.tools.translate import pass_to_ugettext as _
+from mediagoblin.tools.common import simple_printer
+from mediagoblin.tools import pluginapi
+
+
+def assetlink_parser_setup(subparser):
+ # theme_subparsers = subparser.add_subparsers(
+ # dest=u"subcommand",
+ # help=u'Assetlink options')
+
+ # # Install command
+ # install_parser = theme_subparsers.add_parser(
+ # u'install', help=u'Install a theme to this mediagoblin instance')
+ # install_parser.add_argument(
+ # u'themefile', help=u'The theme archive to be installed')
+
+ # theme_subparsers.add_parser(
+ # u'assetlink',
+ # help=(
+ # u"Link the currently installed theme's assets "
+ # u"to the served theme asset directory"))
+ pass
+
+
+###########
+# Utilities
+###########
+
+def link_theme_assets(theme, link_dir, printer=simple_printer):
+ """
+ Returns a list of string of text telling the user what we did
+ which should be printable.
+ """
+ link_dir = link_dir.rstrip(os.path.sep)
+ link_parent_dir = os.path.dirname(link_dir)
+
+ if theme is None:
+ printer(_("Cannot link theme... no theme set\n"))
+ return
+
+ def _maybe_unlink_link_dir():
+ """unlink link directory if it exists"""
+ if os.path.lexists(link_dir) \
+ and os.path.islink(link_dir):
+ os.unlink(link_dir)
+ return True
+
+ return
+
+ if theme.get('assets_dir') is None:
+ printer(_("No asset directory for this theme\n"))
+ if _maybe_unlink_link_dir():
+ printer(
+ _("However, old link directory symlink found; removed.\n"))
+ return
+
+ _maybe_unlink_link_dir()
+
+ # make the link directory parent dirs if necessary
+ if not os.path.lexists(link_parent_dir):
+ os.makedirs(link_parent_dir)
+
+ os.symlink(
+ theme['assets_dir'].rstrip(os.path.sep),
+ link_dir)
+ printer("Linked the theme's asset directory:\n %s\nto:\n %s\n" % (
+ theme['assets_dir'], link_dir))
+
+
+def link_plugin_assets(plugin_static, plugins_link_dir, printer=simple_printer):
+ """
+ Arguments:
+ - plugin_static: a mediagoblin.tools.staticdirect.PluginStatic instance
+ representing the static assets of this plugins' configuration
+ - plugins_link_dir: Base directory plugins are linked from
+ """
+ # link_dir is the final directory we'll link to, a combination of
+ # the plugin assetlink directory and plugin_static.name
+ link_dir = os.path.join(
+ plugins_link_dir.rstrip(os.path.sep), plugin_static.name)
+
+ # make the link directory parent dirs if necessary
+ if not os.path.lexists(plugins_link_dir):
+ os.makedirs(plugins_link_dir)
+
+ # See if the link_dir already exists.
+ if os.path.lexists(link_dir):
+ # if this isn't a symlink, there's something wrong... error out.
+ if not os.path.islink(link_dir):
+ printer(_('Could not link "%s": %s exists and is not a symlink\n') % (
+ plugin_static.name, link_dir))
+ return
+
+ # if this is a symlink and the path already exists, skip it.
+ if os.path.realpath(link_dir) == plugin_static.file_path:
+ # Is this comment helpful or not?
+ printer(_('Skipping "%s"; already set up.\n') % (
+ plugin_static.name))
+ return
+
+ # Otherwise, it's a link that went to something else... unlink it
+ printer(_('Old link found for "%s"; removing.\n') % (
+ plugin_static.name))
+ os.unlink(link_dir)
+
+ os.symlink(
+ plugin_static.file_path.rstrip(os.path.sep),
+ link_dir)
+ printer('Linked asset directory for plugin "%s":\n %s\nto:\n %s\n' % (
+ plugin_static.name,
+ plugin_static.file_path.rstrip(os.path.sep),
+ link_dir))
+
+
+def assetlink(args):
+ """
+ Link the asset directory of the currently installed theme and plugins
+ """
+ mgoblin_app = commands_util.setup_app(args)
+ app_config = mg_globals.app_config
+
+ # link theme
+ link_theme_assets(mgoblin_app.current_theme, app_config['theme_linked_assets_dir'])
+
+ # link plugin assets
+ ## ... probably for this we need the whole application initialized
+ for plugin_static in pluginapi.hook_runall("static_setup"):
+ link_plugin_assets(
+ plugin_static, app_config['plugin_linked_assets_dir'])
diff --git a/mediagoblin/gmg_commands/dbupdate.py b/mediagoblin/gmg_commands/dbupdate.py
index 32700c40..00007567 100644
--- a/mediagoblin/gmg_commands/dbupdate.py
+++ b/mediagoblin/gmg_commands/dbupdate.py
@@ -42,7 +42,7 @@ class DatabaseData(object):
self.name, self.models, self.migrations, session)
-def gather_database_data(media_types, plugins):
+def gather_database_data(plugins):
"""
Gather all database data relevant to the extensions we have
installed so we can do migrations and table initialization.
@@ -59,13 +59,6 @@ def gather_database_data(media_types, plugins):
DatabaseData(
u'__main__', MAIN_MODELS, MAIN_MIGRATIONS))
- # Then get all registered media managers (eventually, plugins)
- for media_type in media_types:
- models = import_component('%s.models:MODELS' % media_type)
- migrations = import_component('%s.migrations:MIGRATIONS' % media_type)
- managed_dbdata.append(
- DatabaseData(media_type, models, migrations))
-
for plugin in plugins:
try:
models = import_component('{0}.models:MODELS'.format(plugin))
@@ -78,6 +71,7 @@ def gather_database_data(media_types, plugins):
except AttributeError as exc:
_log.warning('Could not find MODELS in {0}.models, have you \
forgotten to add it? ({1})'.format(plugin, exc))
+ models = []
try:
migrations = import_component('{0}.migrations:MIGRATIONS'.format(
@@ -91,6 +85,7 @@ forgotten to add it? ({1})'.format(plugin, exc))
except AttributeError as exc:
_log.debug('Cloud not find MIGRATIONS in {0}.migrations, have you \
forgotten to add it? ({1})'.format(plugin, exc))
+ migrations = {}
if models:
managed_dbdata.append(
@@ -108,14 +103,25 @@ def run_dbupdate(app_config, global_config):
in the future, plugins)
"""
+ # Set up the database
+ db = setup_connection_and_db_from_config(app_config, migrations=True)
+ #Run the migrations
+ run_all_migrations(db, app_config, global_config)
+
+
+def run_all_migrations(db, app_config, global_config):
+ """
+ Initializes or migrates a database that already has a
+ connection setup and also initializes or migrates all
+ extensions based on the config files.
+
+ It can be used to initialize an in-memory database for
+ testing.
+ """
# Gather information from all media managers / projects
dbdatas = gather_database_data(
- app_config['media_types'],
global_config.get('plugins', {}).keys())
- # Set up the database
- db = setup_connection_and_db_from_config(app_config, migrations=True)
-
Session = sessionmaker(bind=db.engine)
# Setup media managers for all dbdata, run init/migrate and print info
diff --git a/mediagoblin/gmg_commands/import_export.py b/mediagoblin/gmg_commands/import_export.py
index d51a1e3e..98ec617d 100644
--- a/mediagoblin/gmg_commands/import_export.py
+++ b/mediagoblin/gmg_commands/import_export.py
@@ -63,7 +63,7 @@ def _import_media(db, args):
# TODO: Add import of queue files
queue_cache = BasicFileStorage(args._cache_path['queue'])
- for entry in db.MediaEntry.find():
+ for entry in db.MediaEntry.query.filter_by():
for name, path in entry.media_files.items():
_log.info('Importing: {0} - {1}'.format(
entry.title.encode('ascii', 'replace'),
@@ -204,7 +204,7 @@ def _export_media(db, args):
# TODO: Add export of queue files
queue_cache = BasicFileStorage(args._cache_path['queue'])
- for entry in db.MediaEntry.find():
+ for entry in db.MediaEntry.query.filter_by():
for name, path in entry.media_files.items():
_log.info(u'Exporting {0} - {1}'.format(
entry.title,
diff --git a/mediagoblin/gmg_commands/theme.py b/mediagoblin/gmg_commands/theme.py
deleted file mode 100644
index 71abb982..00000000
--- a/mediagoblin/gmg_commands/theme.py
+++ /dev/null
@@ -1,122 +0,0 @@
-# GNU MediaGoblin -- federated, autonomous media hosting
-# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-import os
-
-from mediagoblin.init import setup_global_and_app_config
-from mediagoblin.tools.theme import register_themes
-from mediagoblin.tools.translate import pass_to_ugettext as _
-from mediagoblin.tools.common import simple_printer
-
-
-def theme_parser_setup(subparser):
- theme_subparsers = subparser.add_subparsers(
- dest=u"subcommand",
- help=u'Theme sub-commands')
-
- # Install command
- install_parser = theme_subparsers.add_parser(
- u'install', help=u'Install a theme to this mediagoblin instance')
- install_parser.add_argument(
- u'themefile', help=u'The theme archive to be installed')
-
- theme_subparsers.add_parser(
- u'assetlink',
- help=(
- u"Link the currently installed theme's assets "
- u"to the served theme asset directory"))
-
-
-###########
-# Utilities
-###########
-
-def link_assets(theme, link_dir, printer=simple_printer):
- """
- Returns a list of string of text telling the user what we did
- which should be printable.
- """
- link_dir = link_dir.rstrip(os.path.sep)
- link_parent_dir = os.path.dirname(link_dir)
-
- results = []
-
- if theme is None:
- printer(_("Cannot link theme... no theme set\n"))
- return results
-
- def _maybe_unlink_link_dir():
- """unlink link directory if it exists"""
- if os.path.lexists(link_dir) \
- and os.path.islink(link_dir):
- os.unlink(link_dir)
- return True
-
- return results
-
- if theme.get('assets_dir') is None:
- printer(_("No asset directory for this theme\n"))
- if _maybe_unlink_link_dir():
- printer(
- _("However, old link directory symlink found; removed.\n"))
- return results
-
- _maybe_unlink_link_dir()
-
- # make the link directory parent dirs if necessary
- if not os.path.lexists(link_parent_dir):
- os.makedirs(link_parent_dir)
-
- os.symlink(
- theme['assets_dir'].rstrip(os.path.sep),
- link_dir)
- printer("Linked the theme's asset directory:\n %s\nto:\n %s\n" % (
- theme['assets_dir'], link_dir))
-
-
-def install_theme(install_dir, themefile):
- pass # TODO ;)
-
-
-#############
-# Subcommands
-#############
-
-def assetlink_command(args):
- """
- Link the asset directory of the currently installed theme
- """
- global_config, app_config = setup_global_and_app_config(args.conf_file)
- theme_registry, current_theme = register_themes(app_config)
- link_assets(current_theme, app_config['theme_linked_assets_dir'])
-
-
-def install_command(args):
- """
- Handle the 'install this theme' subcommand
- """
- global_config, app_config = setup_global_and_app_config(args.conf_file)
- install_dir = app_config['theme_install_dir']
- install_theme(install_dir, args.themefile)
-
-
-SUBCOMMANDS = {
- 'assetlink': assetlink_command,
- 'install': install_command}
-
-
-def theme(args):
- SUBCOMMANDS[args.subcommand](args)
diff --git a/mediagoblin/gmg_commands/users.py b/mediagoblin/gmg_commands/users.py
index 024c8498..e44b0aa9 100644
--- a/mediagoblin/gmg_commands/users.py
+++ b/mediagoblin/gmg_commands/users.py
@@ -15,7 +15,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from mediagoblin.gmg_commands import util as commands_util
-from mediagoblin.auth import lib as auth_lib
+from mediagoblin import auth
from mediagoblin import mg_globals
def adduser_parser_setup(subparser):
@@ -40,9 +40,9 @@ def adduser(args):
db = mg_globals.database
users_with_username = \
- db.User.find({
- 'username': args.username.lower(),
- }).count()
+ db.User.query.filter_by(
+ username=args.username.lower()
+ ).count()
if users_with_username:
print u'Sorry, a user with that name already exists.'
@@ -52,7 +52,7 @@ def adduser(args):
entry = db.User()
entry.username = unicode(args.username.lower())
entry.email = unicode(args.email)
- entry.pw_hash = auth_lib.bcrypt_gen_password_hash(args.password)
+ entry.pw_hash = auth.gen_password_hash(args.password)
entry.status = u'active'
entry.email_verified = True
entry.save()
@@ -71,7 +71,8 @@ def makeadmin(args):
db = mg_globals.database
- user = db.User.one({'username': unicode(args.username.lower())})
+ user = db.User.query.filter_by(
+ username=unicode(args.username.lower())).one()
if user:
user.is_admin = True
user.save()
@@ -94,9 +95,10 @@ def changepw(args):
db = mg_globals.database
- user = db.User.one({'username': unicode(args.username.lower())})
+ user = db.User.query.filter_by(
+ username=unicode(args.username.lower())).one()
if user:
- user.pw_hash = auth_lib.bcrypt_gen_password_hash(args.password)
+ user.pw_hash = auth.gen_password_hash(args.password)
user.save()
print 'Password successfully changed'
else:
diff --git a/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.mo
index 5e69858e..543830c8 100644
--- a/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.po
index 51c71c3a..1f086613 100644
--- a/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.po
@@ -3,18 +3,19 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
-# Majid Al-Dharrab <majid@aldharrab.com>, 2011.
-# Mena Rezk Eid <minaeid90@gmail.com>, 2013.
-# <Omar.w.kh@gmail.com>, 2011.
-# <osamak@gnu.org>, 2011.
+# Jiyda <jiydam@gmail.com>, 2013
+# Majid Al-Dharrab <majid@aldharrab.com>, 2011
+# minaeid90 <minaeid90@gmail.com>, 2013
+# OmarKH <Omar.w.kh@gmail.com>, 2011
+# OsamaK <osamak@gnu.org>, 2011
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-05 00:04+0000\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-05-27 18:54+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language-Team: Arabic (http://www.transifex.com/projects/p/mediagoblin/language/ar/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -22,34 +23,39 @@ msgstr ""
"Language: ar\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
+#: mediagoblin/auth/forms.py:26
msgid "Username"
msgstr "اسم المستخدم"
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
msgid "Password"
msgstr "كلمة السر"
-#: mediagoblin/auth/forms.py:60
+#: mediagoblin/auth/forms.py:34
msgid "Email address"
msgstr "عنوان البريد الإلكتروني"
-#: mediagoblin/auth/forms.py:78
-msgid "Username or email"
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
msgstr ""
+#: mediagoblin/auth/forms.py:52
+msgid "Username or email"
+msgstr "اسم المستخدم او الايميل"
+
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr "اسم مستخدم او ايميل غير صحيح."
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr "هذا الحقل لا يأخذ ايميل."
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr "هذا الحقل يحتاج ايميل."
+
#: mediagoblin/auth/views.py:54
msgid "Sorry, registration is disabled on this instance."
msgstr "عÙوًا، التسجيل غير متاح هنا."
@@ -60,56 +66,56 @@ msgstr "عذرًا، لقد اختار مستخدم آخر هذا الاسم."
#: mediagoblin/auth/views.py:72
msgid "Sorry, a user with that email address already exists."
-msgstr ""
+msgstr "عذرًا، لقد اختار مستخدم آخر هذا الايميل."
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr "تم التحقق من بريدك الإلكتروني. يمكنك الآن الولوج، وتحرير ملÙÙƒ الشخصي، ونشر الصور!"
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr "Ù…ÙØªØ§Ø­ التحقق أو معر٠المستخدم خاطئ"
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr "يجب عليك تسجيل الدخول لإرسال بريد الكترونى لك!"
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr "لقد قمت Ø¨Ø§Ù„ÙØ¹Ù„ بالتحقق من عنوان البريد الإلكتروني الخاص بك!"
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr "أعدنا إرسال رسالة التحقق."
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
-msgstr ""
+msgstr "إذا كان هذا الايميل(حساس للحرو٠الكبيرة والصغيرة!) Ù…ÙØ³Ø¬Ù„, Ùقد تم إرسال ايميل به تعليمات عن كيÙية تغيير رقمك السري."
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
-msgstr ""
+msgstr "لم نتمكن من العثور على أحد له أسم المستخدم هذا."
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
-msgstr ""
+msgstr "لقد تم إرسال ايميل به تعليمات عن كيÙية تغيير رقمك السري."
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr "تعذر إرسال رسالة استعادة كلمة السر لأن اسم المستخدم معطل أو لأننا لم نتحقق من بريدك الإلكتروني."
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
-msgstr ""
+msgstr "تستطيع الآن الدخول باستخدام رقمك السري الجديد."
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -120,13 +126,13 @@ msgid "Description of this work"
msgstr "وص٠هذا العمل."
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n"
" Markdown</a> for formatting."
-msgstr ""
+msgstr "بامكانك استخدام âŽ\n<a href=\"http://daringfireball.net/projects/markdown/basics\">âŽ\nMarkdown</a> للإدراج."
#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36
msgid "Tags"
@@ -134,13 +140,13 @@ msgstr "الوسوم"
#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38
msgid "Separate tags by commas."
-msgstr ""
+msgstr "قم Ø¨ÙØµÙ„ المحددات Ø¨ÙØµÙ„Ø©."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "المسار"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "لا يمكن ترك المسار ÙØ§Ø±ØºÙ‹Ø§"
@@ -148,12 +154,12 @@ msgstr "لا يمكن ترك المسار ÙØ§Ø±ØºÙ‹Ø§"
msgid ""
"The title part of this media's address. You usually don't need to change "
"this."
-msgstr ""
+msgstr "مقدمة عنوان هذه الميديا, غالبا لن تحتاج لتغيره."
#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41
#: mediagoblin/templates/mediagoblin/utils/license.html:20
msgid "License"
-msgstr ""
+msgstr "ترخيص"
#: mediagoblin/edit/forms.py:50
msgid "Bio"
@@ -165,48 +171,48 @@ msgstr "الموقع الإلكتروني"
#: mediagoblin/edit/forms.py:58
msgid "This address contains errors"
-msgstr ""
+msgstr "العنوان يحتوي على اخطاء"
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr ""
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr ""
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr ""
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
-msgstr ""
+msgstr "ØªÙØ¶ÙŠÙ„ رخصة"
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
-msgstr ""
+msgstr "سو٠تكون هذه رخصتك المبدئية ÙÙŠ نماذج التحميل."
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
-msgstr ""
+msgstr "ارسل لي رسالة عندما يقوم الاخرون بالتعليق على الميديا خاصتي"
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
-msgstr ""
+msgstr "لا يمكن ترك العنوان ÙØ§Ø±ØºÙ‹Ø§"
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
-msgstr ""
+msgstr "وص٠هذه المجموعة"
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
-msgstr ""
+msgstr "مقدمة عنوان هذه المجموعة, غالبا لن تحتاج لتغيره."
+
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr " كلمة السر القديمة"
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr "قم بإدخال رقمك السري القديم حتى تثبت انك صاحب هذا الحساب."
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr "رقم سري جديد"
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr "يوجد مل٠آخر بهذا المسار لدى هذى المستخدم."
@@ -217,11 +223,11 @@ msgstr "أنت تحرّر وسائط مستخدم آخر. كن حذرًا أثن
#: mediagoblin/edit/views.py:155
#, python-format
msgid "You added the attachment %s!"
-msgstr ""
+msgstr "لقد قمت Ø¨Ø¥Ø¶Ø§ÙØ© مرÙقة %s!"
#: mediagoblin/edit/views.py:182
msgid "You can only edit your own profile."
-msgstr ""
+msgstr "يمكنك Ùقط تعديل حسابك الخاص"
#: mediagoblin/edit/views.py:188
msgid "You are editing a user's profile. Proceed with caution."
@@ -229,44 +235,63 @@ msgstr "أنت تحرّر مل٠مستخدم آخر. كن حذرًا أثناء
#: mediagoblin/edit/views.py:204
msgid "Profile changes saved"
-msgstr ""
+msgstr "تم Ø­ÙØ¸ تغيرات حسابك"
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr "كلمة سر خاطئة"
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
-msgstr ""
+msgstr "تم Ø­ÙØ¸ خصائص حسابك"
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
-msgstr ""
+msgstr "يجب عليك تأكيد إلغاء حسابك."
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
-msgstr ""
+msgstr "أنت لديك مجموعة تدعى \"%s\"!"
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
-msgstr ""
+msgstr "توجد مجموعة اخرى بهذا المسار لهذا المستخدم."
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
+msgstr "أنت تعدل مجموعة مستخدم آخر. كن حذرًا أثناء العملية."
+
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr "كلمة سر خاطئة"
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
-msgstr ""
+msgstr "لم يتم ربط الثيم... لاتوجد مجموعة ثيمات\n"
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
-msgstr ""
+msgstr "لا يوجد مسار جيد لهذا الثيم\n"
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
+msgstr "ولكن, الرابط القديم للمسار الذي تم ايجاده; Ø­ÙØ°Ù.\n"
+
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
msgstr ""
#: mediagoblin/meddleware/csrf.py:134
@@ -274,55 +299,59 @@ msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
"or somesuch.<br/>Make sure to permit the settings of cookies for this "
"domain."
-msgstr ""
+msgstr "CSRF كوكيز غير موجودة, وهذا من الممكن ان يكون نتيجة لمانع الكوكيز او شئ من هذا القبيل.<br/>تأكد من أنك قمت بالسماح لخصائص الكوكيز لهذا الميدان."
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
+msgstr "عذرا, انا لا ادعم هذا النوع من Ø§Ù„Ù…Ù„ÙØ§Øª :("
+
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
msgstr ""
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
-msgstr ""
+msgstr "ÙØ´Ù„ ÙÙŠ تحويل الÙيديو"
#: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24
msgid "Location"
-msgstr ""
+msgstr "المكان"
#: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:52
#, python-format
msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
-msgstr ""
+msgstr "عرض ÙÙŠ <a href=\"%(osm_url)s\">OpenStreetMap</a>"
#: mediagoblin/plugins/oauth/forms.py:29
msgid "Allow"
-msgstr ""
+msgstr "سماح"
#: mediagoblin/plugins/oauth/forms.py:30
msgid "Deny"
-msgstr ""
+msgstr "Ø±ÙØ¶"
#: mediagoblin/plugins/oauth/forms.py:34
msgid "Name"
-msgstr ""
+msgstr "الاسم"
#: mediagoblin/plugins/oauth/forms.py:35
msgid "The name of the OAuth client"
-msgstr ""
+msgstr "اسم العميل Ø§Ù„Ù…Ù†Ø´ÙØ¦"
#: mediagoblin/plugins/oauth/forms.py:36
msgid "Description"
-msgstr ""
+msgstr "الوصÙ"
#: mediagoblin/plugins/oauth/forms.py:38
msgid ""
"This will be visible to users allowing your\n"
" application to authenticate as them."
-msgstr ""
+msgstr "سو٠يكون هذا مرئي بالنسبة للمستخدمين حتى يتاح\nللبرنامج خاصتك بالتصديق عليهم."
#: mediagoblin/plugins/oauth/forms.py:40
msgid "Type"
-msgstr ""
+msgstr "النوع"
#: mediagoblin/plugins/oauth/forms.py:45
msgid ""
@@ -332,88 +361,88 @@ msgid ""
" <strong>Public</strong> - The client can't make confidential\n"
" requests to the GNU MediaGoblin instance (e.g. client-side\n"
" JavaScript client)."
-msgstr ""
+msgstr "<strong>سري</strong> - يستطيع العميل\nان يقوم بطلب نسخة من GNU MediaGoblin والتي من الممكن ان \nيعترضه وكيل المستخدم (مثلا الخادم من جانب العميل).<br />\n<strong>عام</strong> - لا يستطيع العميل ارسال طلبات سرية\nلنسخة من GNU MediaGoblin (مثلا \nخادم Ø§Ù„Ø¬Ø§ÙØ§ سكريبت من جانب العميل)."
#: mediagoblin/plugins/oauth/forms.py:52
msgid "Redirect URI"
-msgstr ""
+msgstr "تحويل لينك"
#: mediagoblin/plugins/oauth/forms.py:54
msgid ""
"The redirect URI for the applications, this field\n"
" is <strong>required</strong> for public clients."
-msgstr ""
+msgstr "الرابط الموجه للبرنامج, هذا الحقل\n<strong>مطلوب</strong> لجمهور العملاء."
#: mediagoblin/plugins/oauth/forms.py:66
msgid "This field is required for public clients"
-msgstr ""
+msgstr "هذا الحقل مطلوب لجمهور العملاء"
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
-msgstr ""
+msgstr "العميل {0} تم تسجيله!"
#: mediagoblin/plugins/oauth/templates/oauth/client/connections.html:22
msgid "OAuth client connections"
-msgstr ""
+msgstr "ارتباطات العميل المنشئ"
#: mediagoblin/plugins/oauth/templates/oauth/client/list.html:22
msgid "Your OAuth clients"
-msgstr ""
+msgstr "عميلك المنشئ"
#: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
#: mediagoblin/templates/mediagoblin/submit/start.html:34
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68
msgid "Add"
-msgstr ""
+msgstr "اضÙ"
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
-msgstr ""
+msgstr "المل٠المعطى لهذا النوع من الميديا غير صحيح."
#: mediagoblin/submit/forms.py:26
msgid "File"
msgstr "الملÙ"
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr "يجب أن تضع ملÙًا."
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr "يا سلام! Ù†ÙØ´Ø±ÙŽØª!"
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
-msgstr ""
+msgstr "تم Ø¥Ø¶Ø§ÙØ© المجموعة \"%s\"!"
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr "تأكد من بريدك الإلكترونى!"
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
-msgstr ""
+msgstr "تسجيل خروج"
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr "تسجيل دخول"
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
-msgstr ""
+msgstr "<a href=\"%(user_url)s\">%(user_name)s</a>'s حساب"
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
-msgstr ""
+msgstr "تغيير خصائص الحساب"
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -421,79 +450,32 @@ msgstr ""
msgid "Media processing panel"
msgstr "لوحة معالجة الوسائط"
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
-msgstr ""
+msgstr "تسجيل خروج"
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr "أض٠وسائط"
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr ""
+msgstr "إنشاء مجموعة جديدة"
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr "استكشÙ"
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr ""
+msgstr "صورة قزم مرتبك"
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr "أحدث الوسائط"
#: mediagoblin/templates/mediagoblin/admin/panel.html:29
msgid ""
"Here you can track the state of media being processed on this instance."
-msgstr ""
+msgstr "يمكنك متابعة عملية معالجة وسائط معرضك من هنا."
#: mediagoblin/templates/mediagoblin/admin/panel.html:32
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32
@@ -513,34 +495,34 @@ msgstr "ÙØ´Ù„ت معالجة هذه Ø§Ù„Ù…Ù„ÙØ§Øª:"
#: mediagoblin/templates/mediagoblin/admin/panel.html:90
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86
msgid "No failed entries!"
-msgstr ""
+msgstr "لا توجد مداخل ÙØ§Ø´Ù„Ø©!"
#: mediagoblin/templates/mediagoblin/admin/panel.html:92
msgid "Last 10 successful uploads"
-msgstr ""
+msgstr "آخر 10 تحويلات ناجحة"
#: mediagoblin/templates/mediagoblin/admin/panel.html:112
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107
msgid "No processed entries, yet!"
-msgstr ""
+msgstr "لا يوجد مداخل Ù…ÙØ¹Ø§Ù„جة بعد! "
#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28
#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36
msgid "Set your new password"
-msgstr ""
+msgstr "قم بضبط رقمك السري الجديد"
#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39
msgid "Set password"
-msgstr ""
+msgstr "قم بضبط رقم سري"
#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23
#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31
msgid "Recover password"
-msgstr ""
+msgstr "استعادة كلمة السر"
#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34
msgid "Send instructions"
-msgstr ""
+msgstr "ارسل تعليمات"
#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19
#, python-format
@@ -592,6 +574,53 @@ msgid ""
"%(verification_url)s"
msgstr "أهلًا يا %(username)sØŒ\n\nØ§ÙØªØ­ الرابط التالي\nÙÙŠ Ù…ØªØµÙØ­Ùƒ Ù„ØªÙØ¹ÙŠÙ„ حسابك ÙÙŠ غنو ميدياغوبلن:\n\n%(verification_url)s"
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr "برعاية <a href=\"http://mediagoblin.org/\" title='Version %(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> مشروع."
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr "تم النشر ÙˆÙقا Ù„ <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Source code</a> متاح."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr "استكشÙ"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "اهلا, مرحبا بك ÙÙŠ موقع MediaGoblin."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr "هذا الموقع يقوم بتشغيل <a href=\"http://mediagoblin.org\">MediaGoblin</a>, وهو برنامج Ø§Ø³ØªØ¶Ø§ÙØ© ميديا ÙØ§Ø¦Ù‚ الروعة."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr "لكي تضي٠الميديا خاصتك, تضع التعليقات, والمزيد, يجب عليك الدخول بحساب MediaGoblin الخاص بك."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr "ليس لديك واحد حتى الآن؟ انه سهل!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -601,18 +630,18 @@ msgstr "شعار ميدياغوبلن"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:35
#, python-format
msgid "Editing attachments for %(media_title)s"
-msgstr ""
+msgstr "تعديل المرÙقات Ù„ %(media_title)s"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
-msgstr ""
+msgstr "مرÙقات"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
-msgstr ""
+msgstr "أض٠مرÙقة"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:61
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:42
@@ -627,26 +656,36 @@ msgstr "ألغÙ"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr "Ø§Ø­ÙØ¸ التغييرات"
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
-msgstr ""
+msgstr "هل تريد ÙØ¹Ù„ا إلغاء المستخدم '%(user_name)s' وكل الميديا/التعليقات المتعلقة به؟"
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:35
msgid "Yes, really delete my account"
-msgstr ""
+msgstr "نعم, قم بإلغاء حسابي"
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
-msgstr ""
+msgstr "احذ٠نهائيًا"
#: mediagoblin/templates/mediagoblin/edit/edit.html:23
#: mediagoblin/templates/mediagoblin/edit/edit.html:35
@@ -658,11 +697,15 @@ msgstr "تحرير %(media_title)s"
#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
#, python-format
msgid "Changing %(username)s's account settings"
+msgstr "نغيير %(username)s خصائص الحساب"
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
-msgstr ""
+msgstr "إلغ٠حسابي"
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29
#, python-format
@@ -681,42 +724,45 @@ msgstr "تحرير مل٠%(username)s الشخصي"
#: mediagoblin/templates/mediagoblin/listings/tag.html:35
#, python-format
msgid "Media tagged with: %(tag_name)s"
-msgstr ""
+msgstr "يتم تحديد الميديا ب: %(tag_name)s"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
-msgstr ""
+msgstr "تحميل"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
msgid "Original"
-msgstr ""
+msgstr "أصلي"
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:44
msgid ""
"Sorry, this audio will not work because \n"
"\tyour web browser does not support HTML5 \n"
"\taudio."
-msgstr ""
+msgstr "عذرا, لن يتم تشغيل الصوت لأن âŽ\nÂ»Ù…ØªØµÙØ­Ùƒ لا يدعم HTML5 âŽ\n»صوتيا."
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:47
msgid ""
"You can get a modern web browser that \n"
"\tcan play the audio at <a href=\"http://getfirefox.com\">\n"
"\t http://getfirefox.com</a>!"
-msgstr ""
+msgstr "تستطيع الحصول على Ù…ØªØµÙØ­ حديث âŽ\n»يمكنه تشغيل الصوت ÙÙŠ <a href=\"http://getfirefox.com\">âŽ\n» http://getfirefox.com</a>!"
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
-msgstr ""
+msgstr "مل٠أصلي"
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:63
msgid "WebM file (Vorbis codec)"
-msgstr ""
+msgstr "مل٠WebM (Vorbic كوديك)"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -725,65 +771,69 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media.html:65
#, python-format
msgid "Image for %(media_title)s"
+msgstr "صورة ل%(media_title)s"
+
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
-msgstr ""
+msgstr "تبديل التدوير"
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113
msgid "Perspective"
-msgstr ""
+msgstr "منظور"
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117
msgid "Front"
-msgstr ""
+msgstr "مقدمة"
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121
msgid "Top"
-msgstr ""
+msgstr "أعلى"
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125
msgid "Side"
-msgstr ""
+msgstr "جانب"
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131
msgid "WebGL"
-msgstr ""
+msgstr "WebGL"
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138
msgid "Download model"
-msgstr ""
+msgstr "تحميل نموذج"
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146
msgid "File Format"
-msgstr ""
+msgstr "بنية الملÙ"
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148
msgid "Object Height"
-msgstr ""
+msgstr "طول الكائن"
#: mediagoblin/templates/mediagoblin/media_displays/video.html:44
msgid ""
"Sorry, this video will not work because\n"
" your web browser does not support HTML5 \n"
" video."
-msgstr ""
+msgstr "عذرا, لن يتم تشغيل هذا الÙيديو لأن âŽ\nÂ»Ù…ØªØµÙØ­Ùƒ لا يدعم HTML5 âŽ\n»Ùيديو."
#: mediagoblin/templates/mediagoblin/media_displays/video.html:47
msgid ""
"You can get a modern web browser that \n"
" can play this video at <a href=\"http://getfirefox.com\">\n"
" http://getfirefox.com</a>!"
-msgstr ""
+msgstr "تستطيع الحصول على Ù…ØªØµÙØ­ حديث âŽ\n»يمكنه تشغيل هذا الÙيديو ÙÙŠ <a href=\"http://getfirefox.com\">âŽ\n» http://getfirefox.com</a>!"
#: mediagoblin/templates/mediagoblin/media_displays/video.html:69
msgid "WebM file (640p; VP8/Vorbis)"
-msgstr ""
+msgstr "WebM مل٠(640p; VP8/Vorbis)"
#: mediagoblin/templates/mediagoblin/submit/collection.html:26
msgid "Add a collection"
@@ -792,27 +842,27 @@ msgstr "Ø¥Ø¶Ø§ÙØ© مجموعة"
#: mediagoblin/templates/mediagoblin/submit/start.html:23
#: mediagoblin/templates/mediagoblin/submit/start.html:30
msgid "Add your media"
-msgstr ""
+msgstr "اض٠الميديا الخاصة بك"
#: mediagoblin/templates/mediagoblin/user_pages/collection.html:30
#, python-format
msgid "%(collection_title)s (%(username)s's collection)"
-msgstr ""
+msgstr "%(collection_title)s (%(username)s's مجموعة)"
#: mediagoblin/templates/mediagoblin/user_pages/collection.html:39
#, python-format
msgid "%(collection_title)s by <a href=\"%(user_url)s\">%(username)s</a>"
-msgstr ""
+msgstr "%(collection_title)s بواسطة <a href=\"%(user_url)s\">%(username)s</a>"
#: mediagoblin/templates/mediagoblin/user_pages/collection.html:52
#: mediagoblin/templates/mediagoblin/user_pages/media.html:79
msgid "Edit"
-msgstr ""
+msgstr "تعديل"
#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56
#: mediagoblin/templates/mediagoblin/user_pages/media.html:83
msgid "Delete"
-msgstr ""
+msgstr "إلغاء"
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
@@ -823,40 +873,40 @@ msgstr "أتود حقًا حذ٠%(title)s?"
#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:31
#, python-format
msgid "Really remove %(media_title)s from %(collection_title)s?"
-msgstr ""
+msgstr "هل تريد ÙØ¹Ù„ا إلغاء %(media_title)s من %(collection_title)s?"
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
-msgstr ""
+msgstr "إلغاء"
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:21
#, python-format
msgid "%(username)s's collections"
-msgstr ""
+msgstr "%(username)s's مجموعات"
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:28
#, python-format
msgid "<a href=\"%(user_url)s\">%(username)s</a>'s collections"
-msgstr ""
+msgstr "<a href=\"%(user_url)s\">%(username)s</a>'s مجموعات"
#: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19
#, python-format
msgid ""
"Hi %(username)s,\n"
"%(comment_author)s commented on your post (%(comment_url)s) at %(instance_name)s\n"
-msgstr ""
+msgstr "اهلا, %(username)s,\n%(comment_author)s قام بالتعليق على مشاركتك (%(comment_url)s) ÙÙŠ %(instance_name)s\n"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30
#, python-format
msgid "%(username)s's media"
-msgstr ""
+msgstr "%(username)s ميديا"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:38
#, python-format
msgid ""
"<a href=\"%(user_url)s\">%(username)s</a>'s media with tag <a "
"href=\"%(tag_url)s\">%(tag)s</a>"
-msgstr ""
+msgstr "<a href=\"%(user_url)s\">\n%(username)s\n</a>\n's ميديا بالمحدد\n<a href=\"%(tag_url)s\">\n%(tag)s\n</a>"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48
#, python-format
@@ -866,40 +916,44 @@ msgstr "وسائط <a href=\"%(user_url)s\">%(username)s</a>"
#: mediagoblin/templates/mediagoblin/user_pages/media.html:38
#, python-format
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
-msgstr ""
+msgstr "■اختيار الميديا بواسطة <a href=\"%(user_url)s\">%(username)s</a>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
-msgstr ""
+msgstr "أض٠تعليق"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
+msgstr "اض٠هذا التعليق"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
+#, python-format
+msgid "%(formatted_time)s ago"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
-#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40
#, python-format
msgid "Add “%(media_title)s†to a collection"
-msgstr ""
+msgstr "Ø¥Ø¶Ø§ÙØ© “%(media_title)s†لمجموعة"
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:54
msgid "+"
-msgstr ""
+msgstr "+"
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:58
msgid "Add a new collection"
-msgstr ""
+msgstr "Ø¥Ø¶Ø§ÙØ© مجموعة جديدة"
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:29
msgid ""
@@ -908,7 +962,7 @@ msgstr "يمكنك متابعة عملية معالجة وسائط معرضك م
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:89
msgid "Your last 10 successful uploads"
-msgstr ""
+msgstr "آخر 10 تحميلات ناجحة خاصة بك"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:31
#: mediagoblin/templates/mediagoblin/user_pages/user.html:89
@@ -970,7 +1024,7 @@ msgstr "لم يعبئ هذا العضو بيانات ملÙÙ‡ بعد."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:124
msgid "Browse collections"
-msgstr ""
+msgstr "تحديد مجموعة"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:137
#, python-format
@@ -991,59 +1045,59 @@ msgstr "لا يبدو أنه توجد أي وسائط هنا حتى الآن..."
#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
msgid "(remove)"
-msgstr ""
+msgstr "(إلغاء)"
#: mediagoblin/templates/mediagoblin/utils/collections.html:21
msgid "Collected in"
-msgstr ""
+msgstr "تم تجميعه ÙÙŠ"
#: mediagoblin/templates/mediagoblin/utils/collections.html:40
msgid "Add to a collection"
-msgstr ""
+msgstr "Ø¥Ø¶Ø§ÙØ© مجموعة"
#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
#: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:21
msgid "feed icon"
-msgstr ""
+msgstr "ايقونة تغذية"
#: mediagoblin/templates/mediagoblin/utils/feed_link.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:23
msgid "Atom feed"
-msgstr ""
+msgstr "تغذية ذرية"
#: mediagoblin/templates/mediagoblin/utils/license.html:25
msgid "All rights reserved"
-msgstr ""
+msgstr "جميع الحقوق محÙوظة"
#: mediagoblin/templates/mediagoblin/utils/pagination.html:39
msgid "↠Newer"
-msgstr ""
+msgstr "اجددâ†"
#: mediagoblin/templates/mediagoblin/utils/pagination.html:45
msgid "Older →"
-msgstr ""
+msgstr "→اقدم"
#: mediagoblin/templates/mediagoblin/utils/pagination.html:48
msgid "Go to page:"
-msgstr ""
+msgstr "اذهب إلى ØµÙØ­Ø©:"
#: mediagoblin/templates/mediagoblin/utils/prev_next.html:28
#: mediagoblin/templates/mediagoblin/utils/prev_next.html:33
msgid "newer"
-msgstr ""
+msgstr "اجدد"
#: mediagoblin/templates/mediagoblin/utils/prev_next.html:39
#: mediagoblin/templates/mediagoblin/utils/prev_next.html:44
msgid "older"
-msgstr ""
+msgstr "اقدم"
#: mediagoblin/templates/mediagoblin/utils/tags.html:20
msgid "Tagged with"
-msgstr ""
+msgstr "تحدد ب"
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
-msgstr ""
+msgstr "لم نستطيع قراءة هذه الصورة."
#: mediagoblin/tools/response.py:35
msgid "Oops!"
@@ -1051,36 +1105,60 @@ msgstr "ويحي!"
#: mediagoblin/tools/response.py:36
msgid "An error occured"
-msgstr ""
+msgstr "حدث خطأ"
#: mediagoblin/tools/response.py:51
msgid "Operation not allowed"
-msgstr ""
+msgstr "غير مسموح بهذه العملية"
#: mediagoblin/tools/response.py:52
msgid ""
"Sorry Dave, I can't let you do that!</p><p>You have tried to perform a "
"function that you are not allowed to. Have you been trying to delete all "
"user accounts again?"
-msgstr ""
+msgstr "عذرا ديÙ, لا استطيع ترك ØªÙØ¹Ù„ هذا!</p><p>لقد حاولت تشغيل خاصية ليست مسموحة لك. هل كنت تحاول إلغاء جميع حسابات المستخدمين مجددا؟"
#: mediagoblin/tools/response.py:60
msgid ""
"There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure"
" the address is correct, maybe the page you're looking for has been moved or"
" deleted."
+msgstr "يبدو أنه لا توجد ØµÙØ­Ø© بهذا العنوان, عذرا</p><p>إذا كنت متأكد من صحة العنوان, من الممكن أن تكون Ø§Ù„ØµÙØ­Ø© التي تبحث عنها قد تم نقلها أو إلغاءها."
+
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
msgstr ""
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
-msgstr ""
+msgstr "تعليق"
#: mediagoblin/user_pages/forms.py:25
msgid ""
"You can use <a "
"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for"
" formatting."
-msgstr ""
+msgstr "بامكانك استخدام <a href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> للإدراج."
#: mediagoblin/user_pages/forms.py:31
msgid "I am sure I want to delete this"
@@ -1088,87 +1166,91 @@ msgstr "أنا متأكد من رغبتي بحذ٠هذا العمل"
#: mediagoblin/user_pages/forms.py:35
msgid "I am sure I want to remove this item from the collection"
-msgstr ""
+msgstr "أنا متأكد من أنني أريد إلغاء هذه المادة من المجموعة"
#: mediagoblin/user_pages/forms.py:39
msgid "Collection"
-msgstr ""
+msgstr "مجموعة"
#: mediagoblin/user_pages/forms.py:40
msgid "-- Select --"
-msgstr ""
+msgstr "-- إختار --"
#: mediagoblin/user_pages/forms.py:42
msgid "Include a note"
-msgstr ""
+msgstr "إدراج ملاحظة"
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
+msgstr "قام بالتعليق على مشاركتك"
+
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
msgstr ""
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
-msgstr ""
+msgstr "عذرا, لقد قمت بادخال تعليق ÙØ§Ø±Øº."
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
-msgstr ""
+msgstr "لقد تم إرسال تعليقك!"
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
-msgstr ""
+msgstr "من ÙØ¶Ù„Ùƒ قم Ø¨ÙØ­Øµ المداخل وقم بالمحاولة مرة أخرى."
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
-msgstr ""
+msgstr "يجب عليك إختيار أو Ø¥Ø¶Ø§ÙØ© مجموعة"
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
-msgstr ""
+msgstr "\"%s\" توجد Ø¨Ø§Ù„ÙØ¹Ù„ ÙÙŠ المجموعة \"%s\""
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
-msgstr ""
+msgstr "\"%s\" Ø£ÙØ¶ÙŠÙت للمجموعة \"%s\""
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
-msgstr ""
+msgstr "لقد قمت بإلغاء الميديا."
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
-msgstr ""
+msgstr "لم يتم إلغاء الميديا لأنك لم تقم بإختيار انك متأكد من ذلك."
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr "أنت على وشك حذ٠وسائط مستخدم آخر. كن حذرًا أثناء العملية."
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
-msgstr ""
+msgstr "لقد قمت بإلغاء المادة من المجموعة."
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
-msgstr ""
+msgstr "لم يتم إلغاء المادة لأنك لم تقم بإختيار انك متأكد من ذلك."
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
-msgstr ""
+msgstr "أنت على وشك حذ٠مادة من مجموعة مستخدم آخر. كن حذرا."
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
-msgstr ""
+msgstr "لقد قمت بإلغاء المجموعة \"%s\""
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
-msgstr ""
+msgstr "لم يتم إلغاء المجموعة لأنك لم تقم بإختيار انك متأكد من ذلك."
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
-msgstr ""
+msgstr "أنت على وشك حذ٠مجموعة مستخدم آخر. كن حذرا."
diff --git a/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.mo
index 495ef726..ec01d7f7 100644
--- a/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.po
index 28bdca82..9ebbdf18 100644
--- a/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.po
@@ -3,17 +3,17 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
-# Al fred <devaleitzer@aim.com>, 2011.
-# <devaleitzer@aim.com>, 2011.
-# <skarbat@gmail.com>, 2012.
+# Al fred <devaleitzer@aim.com>, 2011
+# Al fred <devaleitzer@aim.com>, 2011
+# skarbat <skarbat@gmail.com>, 2012
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-05 00:04+0000\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-05-27 18:54+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language-Team: Catalan (http://www.transifex.com/projects/p/mediagoblin/language/ca/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -21,34 +21,39 @@ msgstr ""
"Language: ca\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
+#: mediagoblin/auth/forms.py:26
msgid "Username"
msgstr "Nom d'usuari"
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
msgid "Password"
msgstr "Contrasenya"
-#: mediagoblin/auth/forms.py:60
+#: mediagoblin/auth/forms.py:34
msgid "Email address"
msgstr "Adreça electrònica"
-#: mediagoblin/auth/forms.py:78
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
+msgstr ""
+
+#: mediagoblin/auth/forms.py:52
msgid "Username or email"
msgstr "Nom d'usuari o correu"
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr ""
+
#: mediagoblin/auth/views.py:54
msgid "Sorry, registration is disabled on this instance."
msgstr "Ho sentim, el registre està desactivat en aquest cas."
@@ -61,54 +66,54 @@ msgstr "Lamentablement aquest usuari ja existeix."
msgid "Sorry, a user with that email address already exists."
msgstr "Perdó, ja existeix un usuari amb aquesta adreça de correu."
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr "Ja s'ha verificat la vostra adreça electrònica. Ara podeu entrar, editar el vostre perfil i penjar imatge!"
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr "La clau de verificació o la identificació de l'usuari no són correctes."
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr "Has d'estar conectat per saber a qui hem d'enviar el correu!"
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr "Ja has verificat la teva adreça de correu!"
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr "Torna'm a enviar el correu de verificació"
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
msgstr ""
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
msgstr ""
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
msgstr "S'ha enviat un correu amb instruccions de com cambiar la teva contrasenya"
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr "No hem pogut enviar el correu de recuperació de contrasenya perquè el teu nom d'usuari és inactiu o bé l'adreça electrònica del teu compte no ha sigut verificada."
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
msgstr "Ara et pots conectar amb la teva nova contrasenya."
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -119,7 +124,7 @@ msgid "Description of this work"
msgstr "Descripció d'aquest treball."
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -135,11 +140,11 @@ msgstr "Etiquetes"
msgid "Separate tags by commas."
msgstr "Separa els tags amb comes."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "Llimac"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "El llimac no pot ésser buit"
@@ -167,45 +172,45 @@ msgid "This address contains errors"
msgstr "Aquesta adreça conté errors"
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr "Contrasenya antiga"
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr "Introdueix la teva contrasenya antiga per comprovar que aquest compte és teu."
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr "Nova contrasenya"
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
msgstr ""
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
msgstr ""
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr "Envia'm correu quan d'altres comentin al meu mitjà"
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr "El títol no pot ser buit"
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr "Descripció d'aquesta col.lecció"
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr "La part del títol de l'adreça d'aquesta col.lecció. Normalment no cal que canviis això."
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr "Contrasenya antiga"
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr "Introdueix la teva contrasenya antiga per comprovar que aquest compte és teu."
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr "Nova contrasenya"
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr "Ja existeix una entrada amb aquest llimac per aquest usuari"
@@ -230,44 +235,63 @@ msgstr "Esteu editant el perfil d'un usuari. Aneu amb compte"
msgid "Profile changes saved"
msgstr "Els canvis al perfil s'han guardat"
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr "Contrasenya errònia"
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr "Els detalls del compte s'han guardat"
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
msgstr ""
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr "Ja tens una col.lecció anomenada \"%s\"!"
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr "Estas editant la col.lecció d'un altre usuari. Prossegueix amb cautela."
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr "Contrasenya errònia"
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr "No es pot enllaçar el tema... no hi ha tema establert\n"
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr "Tot i així, l'enllaç antic al directori s'ha trobat; eliminat.\n"
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr ""
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
@@ -275,12 +299,16 @@ msgid ""
"domain."
msgstr ""
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr "Ho sento, no puc manegar aquest tipus d'arxiu :("
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr ""
+
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr "La transformació del vídeo ha fallat"
@@ -347,7 +375,7 @@ msgstr "La URI de redirecció per les aplicacions, aquest camp\n és
msgid "This field is required for public clients"
msgstr "Aquest camp és requeriment per a clients públics"
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
msgstr "El client {0} ha sigut enregistrat!"
@@ -366,7 +394,7 @@ msgstr ""
msgid "Add"
msgstr "Afegir"
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr "Aquest tipus de fitxer no és vàlid."
@@ -374,45 +402,45 @@ msgstr "Aquest tipus de fitxer no és vàlid."
msgid "File"
msgstr "Fitxer"
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr "Heu d'escollir un fitxer."
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr "Visca! S'ha enviat!"
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr "S'ha afegit la col.leccio \"%s\"!"
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr "Verifica el teu correu electrònic"
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr "Entra"
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr "Modificar els ajustaments del compte"
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -420,72 +448,25 @@ msgstr "Modificar els ajustaments del compte"
msgid "Media processing panel"
msgstr "Quadre de processament de fitxers"
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr "Tots els fitxers"
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr "Alliberat segons la <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Codi font</a> disponible."
-
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr "Explorar"
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr "Hola, una benvinguda al MediaGoblin!"
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr "El lloc esta usant <a href=\"http://mediagoblin.org\">MediaGoblin</a>, una gran i extraordinària peça de software per allotjar mitjans."
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr "Per afegir el teu propi mitjà, col.locar comentaris, i més, pots conectar-te amb el teu compte MediaGoblin."
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr "No en tens una encara? Es fàcil!"
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">Crear un compte a aquest lloc</a> \no\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Preparar MediaGoblin al teu propi servidor</a>"
-
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr "Mitjans més recents"
@@ -591,6 +572,53 @@ msgid ""
"%(verification_url)s"
msgstr "Hi %(username)s,\n\nto activate your GNU MediaGoblin account, open the following URL in\nyour web browser:\n\n%(verification_url)s"
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr "Alliberat segons la <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Codi font</a> disponible."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr "Explorar"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "Hola, una benvinguda al MediaGoblin!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr "El lloc esta usant <a href=\"http://mediagoblin.org\">MediaGoblin</a>, una gran i extraordinària peça de software per allotjar mitjans."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr "Per afegir el teu propi mitjà, col.locar comentaris, i més, pots conectar-te amb el teu compte MediaGoblin."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr "No en tens una encara? Es fàcil!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -603,13 +631,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr "Editant afegits per a %(media_title)s"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
msgstr ""
@@ -626,12 +654,22 @@ msgstr "Cancel·la"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr "Desa els canvis"
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
@@ -642,7 +680,7 @@ msgid "Yes, really delete my account"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "Esborrar permanentment"
@@ -659,7 +697,11 @@ msgstr "Edició %(media_title)s "
msgid "Changing %(username)s's account settings"
msgstr "Modificant els detalls del compte de %(username)s"
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
msgstr ""
@@ -684,6 +726,7 @@ msgstr "Mitjà marcat amb: %(tag_name)s"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -708,6 +751,7 @@ msgid ""
msgstr "Pots obtenir un navegador web modern que \n »podrà reproduir l'àudio, a <a href=\"http://getfirefox.com\">\n » http://getfirefox.com</a>!"
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr "Arxiu original"
@@ -716,6 +760,7 @@ msgstr "Arxiu original"
msgid "WebM file (Vorbis codec)"
msgstr "Arxiu WebM (Vorbis codec)"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -726,6 +771,10 @@ msgstr "Arxiu WebM (Vorbis codec)"
msgid "Image for %(media_title)s"
msgstr "Imatge per %(media_title)s"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
msgstr ""
@@ -824,7 +873,7 @@ msgstr "Realment vols esborrar %(title)s?"
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr "Relment eliminar %(media_title)s de %(collection_title)s?"
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr "Eliminar"
@@ -867,24 +916,28 @@ msgstr "<a href=\"%(user_url)s\">%(username)s</a>'s media"
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr "■Navegant mitjà per a <a href=\"%(user_url)s\">%(username)s</a>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
msgstr "Afegeix un comentari"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
msgstr "Afegir aquest comentari"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
-msgstr "a"
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
-msgstr "<h3>Afegit el</h3>\n <p>%(date)s</p>"
+msgid "%(formatted_time)s ago"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
+msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40
@@ -1040,7 +1093,7 @@ msgstr "més antic"
msgid "Tagged with"
msgstr ""
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr "No s'ha pogut llegir l'arxiu d'imatge"
@@ -1070,6 +1123,30 @@ msgid ""
" deleted."
msgstr ""
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr ""
+
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
msgstr ""
@@ -1101,73 +1178,77 @@ msgstr "-- Sel.leccionar --"
msgid "Include a note"
msgstr "Incluir una nota"
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
msgstr "comentat al teu post"
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr "Uups, el teu comentari era buit."
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr "El teu comentari s'ha publicat!"
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
msgstr "Si et plau, comprova les teves entrades i intenta-ho de nou."
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr "Has de sel.leccionar o afegir una col.lecció"
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr "\"%s\" ja és a la col.lecció \"%s\""
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr "\"%s\" afegir a la col.lecció \"%s\""
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr "Has esborrat el mitjà"
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr "El mitjà no s'ha esborrat perque no has marcat que n'estiguessis segur."
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr "Ets a punt d'esborrar el mitjà d'un altre usuari. Prossegueix amb cautela."
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr "Has esborrat l'element de la col.lecció"
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr "L'element no s'ha eliminat perque no has marcat que n'estiguessis segur."
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr "Ets a punt d'esborrar un element de la col.lecció d'un altre usuari. Prossegueix amb cautela."
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr "Has esborrat la col.lecció \"%s\""
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr "La col.lecció no s'ha esborrat perquè no has marcat que n'estiguessis segur."
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr "Ets a punt d'esborrar la col.lecció d'un altre usuari. Prossegueix amb cautela."
diff --git a/mediagoblin/i18n/da/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/da/LC_MESSAGES/mediagoblin.mo
index 6b6827f0..53e3fedf 100644
--- a/mediagoblin/i18n/da/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/da/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/da/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/da/LC_MESSAGES/mediagoblin.po
index 8494aa60..c78c08ac 100644
--- a/mediagoblin/i18n/da/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/da/LC_MESSAGES/mediagoblin.po
@@ -3,17 +3,17 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
-# Morten Juhl-Johansen Zölde-Fejér <morten@writtenandread.net>, 2012.
-# Olle Jonsson <olle.jonsson@gmail.com>, 2012.
-# Tanja Trudslev <tanja.trudslev@gmail.com>, 2012.
+# Morten Juhl-Johansen Zölde-Fejér <morten@writtenandread.net>, 2012
+# Olle Jonsson <olle.jonsson@gmail.com>, 2012
+# ttrudslev <tanja.trudslev@gmail.com>, 2012
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-05 00:04+0000\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-05-27 18:54+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language-Team: Danish (http://www.transifex.com/projects/p/mediagoblin/language/da/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -21,34 +21,39 @@ msgstr ""
"Language: da\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
+#: mediagoblin/auth/forms.py:26
msgid "Username"
msgstr "Brugernavn"
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
msgid "Password"
msgstr "Kodeord"
-#: mediagoblin/auth/forms.py:60
+#: mediagoblin/auth/forms.py:34
msgid "Email address"
msgstr "Email adresse"
-#: mediagoblin/auth/forms.py:78
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
+msgstr ""
+
+#: mediagoblin/auth/forms.py:52
msgid "Username or email"
msgstr "Brugernavn eller email"
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr ""
+
#: mediagoblin/auth/views.py:54
msgid "Sorry, registration is disabled on this instance."
msgstr "Desværre, registrering er ikke muligt på denne instans"
@@ -61,54 +66,54 @@ msgstr "Desværre, det brugernavn er allerede brugt"
msgid "Sorry, a user with that email address already exists."
msgstr "Desværre, en bruger er allerede oprettet for den email"
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr "Din email adresse er blevet bekræftet. Du kan nu logge på, ændre din profil, og indsende billeder!"
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr "Bekræftelsesnøglen eller brugerid er forkert"
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr "Du er nødt til at være logget ind, så vi ved hvem vi skal emaile!"
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr "Du har allerede bekræftet din email adresse!"
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr "Email til godkendelse sendt igen."
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
msgstr ""
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
msgstr ""
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
msgstr "En email er blevet sendt med instruktioner til at ændre dit kodeord."
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr "Vi kunne ikke sende en kodeords nulstillings email da dit brugernavn er inaktivt, eller din konto's email adresse er ikke blevet godkendt."
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
msgstr "Du kan nu logge ind med dit nye kodeord."
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -119,7 +124,7 @@ msgid "Description of this work"
msgstr "Beskrivelse af arbejdet"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -135,11 +140,11 @@ msgstr "Tags"
msgid "Separate tags by commas."
msgstr "Separer tags med kommaer."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr ""
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr ""
@@ -167,45 +172,45 @@ msgid "This address contains errors"
msgstr "Denne adresse indeholder fejl"
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr "Gammelt kodeord"
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr "Skriv dit gamle kodeord for at bevise det er din konto."
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr "Ny kodeord"
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
msgstr ""
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
msgstr ""
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr "Email mig når andre kommenterer på mine medier"
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr "Titlen kan ikke være tom"
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr "Beskrivelse af denne samling"
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr "Titeldelen af denne samlings's adresse. Du behøver normalt ikke ændre dette."
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr "Gammelt kodeord"
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr "Skriv dit gamle kodeord for at bevise det er din konto."
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr "Ny kodeord"
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr ""
@@ -230,44 +235,63 @@ msgstr "Du er ved at ændre en bruger's profil. Pas på."
msgid "Profile changes saved"
msgstr "Profilændringer gemt"
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr "Forkert kodeord"
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr "Kontoindstillinger gemt"
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
msgstr ""
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr "Du har allerede en samling ved navn \"%s\"!"
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr "Du er ved at ændre en anden bruger's samling. Pas på."
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr "Forkert kodeord"
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr "Kan ikke linke til tema... intet tema sat\n"
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr ""
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr ""
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
@@ -275,12 +299,16 @@ msgid ""
"domain."
msgstr ""
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr "Desværre, jeg understøtter ikke den filtype :("
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr ""
+
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr ""
@@ -347,7 +375,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr "Dette felt er nødvendigt for offentlige klienter"
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
msgstr "Klienten {0} er blevet registreret!"
@@ -366,7 +394,7 @@ msgstr ""
msgid "Add"
msgstr ""
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr "Forkert fil for medietypen."
@@ -374,45 +402,45 @@ msgstr "Forkert fil for medietypen."
msgid "File"
msgstr "Fil"
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr "Du må give mig en fil"
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr "Juhuu! Delt!"
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr "Bekræft din email!"
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr "Log ind"
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -420,72 +448,25 @@ msgstr ""
msgid "Media processing panel"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr "Udforsk"
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr "Hey, velkommen til denne MediaGoblin side!"
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr "For at tilføje dine egne medier, skrive kommentarer, og mere, du kan logge ind med din MediaGoblin konto."
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr "Har du ikke en endnu? Det er let!"
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr ""
@@ -591,6 +572,53 @@ msgid ""
"%(verification_url)s"
msgstr ""
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr "Udforsk"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "Hey, velkommen til denne MediaGoblin side!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr "For at tilføje dine egne medier, skrive kommentarer, og mere, du kan logge ind med din MediaGoblin konto."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr "Har du ikke en endnu? Det er let!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -603,13 +631,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
msgstr ""
@@ -626,12 +654,22 @@ msgstr "Afbryd"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr "Gem ændringer"
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
@@ -642,7 +680,7 @@ msgid "Yes, really delete my account"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr ""
@@ -659,7 +697,11 @@ msgstr ""
msgid "Changing %(username)s's account settings"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
msgstr ""
@@ -684,6 +726,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -708,6 +751,7 @@ msgid ""
msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr ""
@@ -716,6 +760,7 @@ msgstr ""
msgid "WebM file (Vorbis codec)"
msgstr ""
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -726,6 +771,10 @@ msgstr ""
msgid "Image for %(media_title)s"
msgstr ""
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
msgstr ""
@@ -824,7 +873,7 @@ msgstr ""
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr ""
@@ -867,23 +916,27 @@ msgstr ""
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
+#, python-format
+msgid "%(formatted_time)s ago"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
-#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
@@ -1040,7 +1093,7 @@ msgstr ""
msgid "Tagged with"
msgstr ""
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr ""
@@ -1070,6 +1123,30 @@ msgid ""
" deleted."
msgstr ""
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr ""
+
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
msgstr ""
@@ -1101,73 +1178,77 @@ msgstr ""
msgid "Include a note"
msgstr ""
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
msgstr ""
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr ""
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr ""
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr ""
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr ""
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr ""
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr ""
diff --git a/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.mo
index 5ae794fa..e2fcf85d 100644
--- a/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.po
index b3d82ee9..e2147070 100644
--- a/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.po
@@ -3,26 +3,26 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
-# <benjamin@lebsanft.org>, 2011.
-# <cwebber@dustycloud.org>, 2011.
-# Elrond <elrond+mediagoblin.org@samba-tng.org>, 2011-2012.
-# Elrond <elrond+mediagoblin.org@samba-tng.org>, 2013.
-# <jakob.kramer@gmx.de>, 2011, 2012.
-# Jakob Kramer <jakob.kramer@gmx.de>, 2012-2013.
-# Jan-Christoph Borchardt <JanCBorchardt@fsfe.org>, 2011.
-# Jan-Christoph Borchardt <jan@unhosted.org>, 2011, 2012.
-# <kyoo@kyoo.ch>, 2011.
-# <mediagoblin.org@samba-tng.org>, 2011.
-# Rafael Maguiña <rafael.maguina@gmail.com>, 2011.
-# <sebastian@sspaeth.de>, 2012.
-# Vinzenz Vietzke <vietzke@b1-systems.de>, 2012.
-# Vinzenz Vietzke <vinz@fedoraproject.org>, 2011.
+# piratenpanda <benjamin@lebsanft.org>, 2011
+# cwebber <cwebber@dustycloud.org>, 2011
+# Elrond <elrond+mediagoblin.org@samba-tng.org>, 2011-2012
+# Elrond <elrond+mediagoblin.org@samba-tng.org>, 2013
+# Jakob Kramer <jakob.kramer@gmx.de>, 2011, 2012
+# Jakob Kramer <jakob.kramer@gmx.de>, 2012-2013
+# Jan-Christoph Borchardt <hey@jancborchardt.net>, 2011
+# Jan-Christoph Borchardt <hey@jancborchardt.net>, 2011, 2012
+# Keyzo <kyoo@kyoo.ch>, 2011
+# Elrond <elrond+mediagoblin.org@samba-tng.org>, 2011
+# Art O. Pal <artopal@fastmail.fm>, 2011
+# spaetz <sebastian@sspaeth.de>, 2012
+# Vinzenz Vietzke <vinz@vinzv.de>, 2012
+# Vinzenz Vietzke <vinz@vinzv.de>, 2011
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-07 13:16+0000\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-05-28 10:43+0000\n"
"Last-Translator: Elrond <elrond+mediagoblin.org@samba-tng.org>\n"
"Language-Team: German (http://www.transifex.com/projects/p/mediagoblin/language/de/)\n"
"MIME-Version: 1.0\n"
@@ -32,34 +32,39 @@ msgstr ""
"Language: de\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
-msgstr "Ungültiger Benutzername oder E-Mail-Adresse."
-
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
-msgstr "Dieses Feld akzeptiert keine E-Mail-Adressen."
-
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
-msgstr "Dieses Feld benötigt eine E-Mail-Adresse."
-
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
+#: mediagoblin/auth/forms.py:26
msgid "Username"
msgstr "Benutzername"
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
msgid "Password"
msgstr "Passwort"
-#: mediagoblin/auth/forms.py:60
+#: mediagoblin/auth/forms.py:34
msgid "Email address"
msgstr "E-Mail-Adresse"
-#: mediagoblin/auth/forms.py:78
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
+msgstr "Benutzername oder E-Mail-Adresse"
+
+#: mediagoblin/auth/forms.py:52
msgid "Username or email"
msgstr "Benutzername oder E-Mail-Adresse"
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr "Ungültiger Benutzername oder E-Mail-Adresse."
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr "Dieses Feld akzeptiert keine E-Mail-Adressen."
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr "Dieses Feld benötigt eine E-Mail-Adresse."
+
#: mediagoblin/auth/views.py:54
msgid "Sorry, registration is disabled on this instance."
msgstr "Benutzerregistrierung ist auf diesem Server leider deaktiviert."
@@ -72,54 +77,54 @@ msgstr "Leider gibt es bereits einen Benutzer mit diesem Namen."
msgid "Sorry, a user with that email address already exists."
msgstr "Leider gibt es bereits einen Benutzer mit dieser E-Mail-Adresse."
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr "Dein GNU MediaGoblin Konto wurde hiermit aktiviert. Du kannst dich jetzt anmelden, dein Profil bearbeiten und Medien hochladen."
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr "Der Aktivierungsschlüssel oder die Nutzerkennung ist falsch."
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr "Du musst angemeldet sein, damit wir wissen, wer die Email bekommt."
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr "Deine E-Mail-Adresse wurde bereits aktiviert."
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr "Aktivierungsmail wurde erneut versandt."
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
msgstr "Falls jemand mit dieser E-Mail-Adresse (Groß- und Kleinschreibung wird unterschieden!) registriert ist, wurde eine E-Mail mit Anleitungen verschickt, wie Du Dein Passwort ändern kannst."
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
msgstr "Es konnte niemand mit diesem Benutzernamen gefunden werden."
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
msgstr "Es wurde eine E-Mail mit der Anleitung zur Änderung des Passwortes an Dich gesendet."
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr "Die E-Mail zur Wiederherstellung des Passworts konnte nicht verschickt werden, weil dein Benutzername inaktiv oder deine E-Mail-Adresse noch nicht aktiviert wurde."
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
msgstr "Du kannst dich jetzt mit deinem neuen Passwort anmelden."
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -130,7 +135,7 @@ msgid "Description of this work"
msgstr "Beschreibung des Werkes"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -146,11 +151,11 @@ msgstr "Schlagwörter"
msgid "Separate tags by commas."
msgstr "Kommaseparierte Schlagwörter"
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "Kurztitel"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "Bitte gib einen Kurztitel ein"
@@ -178,45 +183,45 @@ msgid "This address contains errors"
msgstr "Diese Adresse ist fehlerhaft"
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr "Altes Passwort"
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr "Gib dein altes Passwort ein, um zu bestätigen, dass du dieses Konto besitzt."
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr "Neues Passwort"
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
msgstr "Bevorzugte Lizenz"
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
msgstr "Dies wird Deine Standardlizenz in den Upload-Forumularen sein."
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr "Mir eine E-Mail schicken, wenn andere meine Medien kommentieren"
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr "Der Titel kann nicht leer sein"
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr "Beschreibung dieser Sammlung"
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr "Der Titelteil dieser Sammlungsadresse. Du musst ihn normalerweise nicht ändern."
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr "Altes Passwort"
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr "Gib dein altes Passwort ein, um zu bestätigen, dass du dieses Konto besitzt."
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr "Neues Passwort"
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr "Diesen Kurztitel hast du bereits vergeben."
@@ -241,44 +246,63 @@ msgstr "Du bearbeitest das Profil eines anderen Nutzers. Sei bitte vorsichtig."
msgid "Profile changes saved"
msgstr "Das Profil wurde aktualisiert"
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr "Falsches Passwort"
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr "Kontoeinstellungen gespeichert"
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
msgstr "Du musst die Löschung deines Kontos bestätigen."
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr "Du hast bereits eine Sammlung mit Namen »%s«!"
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr "Eine Sammlung mit diesem Kurztitel existiert bereits für diesen Benutzer."
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr "Du bearbeitest die Sammlung eines anderen Benutzers. Sei vorsichtig."
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr "Falsches Passwort"
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr "Theme kann nicht verknüpft werden … Kein Theme gesetzt\n"
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr "Für dieses Theme gibt es kein asset-Verzeichnis\n"
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr "Trotzdem wurde eine alte Verknüpfung gefunden; sie wurde entfernt\n"
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr ""
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
@@ -286,12 +310,16 @@ msgid ""
"domain."
msgstr "Das CSRF cookie ist nicht vorhanden. Das liegt vermutlich an einem Cookie-Blocker oder ähnlichem.<br/>Bitte stelle sicher, dass Cookies von dieser Domäne erlaubt sind."
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr "Entschuldigung, dieser Dateityp wird nicht unterstützt."
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr ""
+
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr "Videokonvertierung fehlgeschlagen"
@@ -358,17 +386,17 @@ msgstr "Die Weiterleitungs-URI für die Anwendung, dieses Feld\n ist
msgid "This field is required for public clients"
msgstr "Dieses Feld ist Pflicht für öffentliche Clients"
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
msgstr "Client {0} wurde registriert!"
#: mediagoblin/plugins/oauth/templates/oauth/client/connections.html:22
msgid "OAuth client connections"
-msgstr ""
+msgstr "OAuth-Client-Verbindungen"
#: mediagoblin/plugins/oauth/templates/oauth/client/list.html:22
msgid "Your OAuth clients"
-msgstr ""
+msgstr "Deine OAuth-Clients"
#: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
@@ -377,7 +405,7 @@ msgstr ""
msgid "Add"
msgstr "Hinzufügen"
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr "Die Datei stimmt nicht mit dem gewählten Medientyp überein."
@@ -385,45 +413,45 @@ msgstr "Die Datei stimmt nicht mit dem gewählten Medientyp überein."
msgid "File"
msgstr "Datei"
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr "Du musst eine Datei angeben."
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr "JAAA! Geschafft!"
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr "Sammlung »%s« hinzugefügt!"
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr "Bitte bestätige Deine E-Mail-Adresse!"
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
msgstr "abmelden"
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr "Anmelden"
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr "<a href=\"%(user_url)s\">%(user_name)s</a>s Konto"
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr "Kontoeinstellungen ändern"
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -431,72 +459,25 @@ msgstr "Kontoeinstellungen ändern"
msgid "Media processing panel"
msgstr "Medienverarbeitung"
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
msgstr "Abmelden"
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr "Medien hinzufügen"
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
msgstr "Neues Album erstellen"
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr "Läuft mit <a href=\"http://mediagoblin.org/\" title='Version %(version)s'>MediaGoblin</a>, einem <a href=\"http://gnu.org/\">GNU</a>-Projekt."
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr "Veröffentlicht unter der <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a> (<a href=\"%(source_link)s\">Quellcode</a>)."
-
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
msgstr "Bild eines gestressten Goblins"
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr "Entdecken"
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr "Hallo du, willkommen auf dieser MediaGoblin-Seite!"
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr "Diese Webseite setzt <a href=\"http://mediagoblin.org\">MediaGoblin</a> ein, eine großartige Software für Medienhosting."
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr "Melde Dich mit Deinem MediaGoblin-Konto an, um eigene Medien hinzuzufügen, andere zu kommentieren und vieles mehr."
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr "Hast du noch keinen? Das geht ganz einfach!"
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">Registriere dich auf dieser Seite</a> oder <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Installiere MediaGoblin auf deinem eigenen Server</a>"
-
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr "Neuste Medien"
@@ -602,6 +583,53 @@ msgid ""
"%(verification_url)s"
msgstr "Hallo %(username)s,\n\num deinNutzerkonto bei GNU MediaGoblin zu aktivieren, musst du folgende Adresse in deinem Webbrowser öffnen:\n\n%(verification_url)s"
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr "Läuft mit <a href=\"http://mediagoblin.org/\" title='Version %(version)s'>MediaGoblin</a>, einem <a href=\"http://gnu.org/\">GNU</a>-Projekt."
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr "Veröffentlicht unter der <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a> (<a href=\"%(source_link)s\">Quellcode</a>)."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr "Entdecken"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "Hallo du, willkommen auf dieser MediaGoblin-Seite!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr "Diese Webseite setzt <a href=\"http://mediagoblin.org\">MediaGoblin</a> ein, eine großartige Software für Medienhosting."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr "Melde Dich mit Deinem MediaGoblin-Konto an, um eigene Medien hinzuzufügen, andere zu kommentieren und vieles mehr."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr "Hast du noch keinen? Das geht ganz einfach!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">Registriere dich auf dieser Seite</a> oder <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Installiere MediaGoblin auf deinem eigenen Server</a>"
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -614,13 +642,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr "Bearbeite Anhänge von %(media_title)s"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
msgstr "Anhänge"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
msgstr "Anhang hinzufügen"
@@ -637,12 +665,22 @@ msgstr "Abbrechen"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr "Änderungen speichern"
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
@@ -653,7 +691,7 @@ msgid "Yes, really delete my account"
msgstr "Ja, ich möchte mein Konto wirklich löschen"
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "Dauerhaft löschen"
@@ -670,7 +708,11 @@ msgstr "%(media_title)s bearbeiten"
msgid "Changing %(username)s's account settings"
msgstr "%(username)ss Kontoeinstellungen ändern"
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
msgstr "Mein Konto löschen"
@@ -695,6 +737,7 @@ msgstr "Medien mit Schlagwort: %(tag_name)s"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -719,6 +762,7 @@ msgid ""
msgstr "Hol dir auf <a href=\"http://getfirefox.com\">http://getfirefox.com</a> einen modernen Webbrowser, der dieses Audiostück abspielen kann!"
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr "Originaldatei"
@@ -727,6 +771,7 @@ msgstr "Originaldatei"
msgid "WebM file (Vorbis codec)"
msgstr "WebM-Datei (Vorbis-Codec)"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -737,6 +782,10 @@ msgstr "WebM-Datei (Vorbis-Codec)"
msgid "Image for %(media_title)s"
msgstr "Bild für %(media_title)s"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr "PDF-Datei"
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
msgstr ""
@@ -835,7 +884,7 @@ msgstr "Möchtest du %(title)s wirklich löschen?"
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr "Wirklich »%(media_title)s« aus »%(collection_title)s« entfernen?"
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr "Entfernen"
@@ -878,24 +927,28 @@ msgstr "<a href=\"%(user_url)s\">%(username)s</a>s Medien"
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr "â– Medien von <a href=\"%(user_url)s\">%(username)s</a>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
msgstr "Einen Kommentar schreiben"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
msgstr "Kommentar absenden"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
-msgstr "um"
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
-msgstr "<h3>Veröffentlicht am</h3>\n <p>%(date)s</p>"
+msgid "%(formatted_time)s ago"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr "Hinzugefügt"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
+msgstr "Originaldatum"
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40
@@ -1051,7 +1104,7 @@ msgstr "älter"
msgid "Tagged with"
msgstr "Schlagwörter"
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr "Die Bilddatei konnte nicht gelesen werden."
@@ -1081,6 +1134,30 @@ msgid ""
" deleted."
msgstr "Tut uns Leid, aber unter der angegebenen Adresse gibt es keine Seite!</p><p>Wenn du sicher bist, dass die Adresse stimmt, wurde die Seite eventuell verschoben oder gelöscht."
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr "Jahr"
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr "Monat"
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr "Woche"
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr "Tag"
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr "Stunde"
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr "Minute"
+
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
msgstr "Kommentar"
@@ -1112,73 +1189,77 @@ msgstr "-- Auswählen --"
msgid "Include a note"
msgstr "Notiz anfügen"
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
msgstr "hat dein Medium kommentiert"
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr "Hoppla, der Kommentartext fehlte."
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr "Dein Kommentar wurde angenommen!"
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
msgstr "Bitte prüfe deinen Einträge und versuche erneut."
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr "Du musst eine Sammlung auswählen oder hinzufügen"
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr "»%s« ist bereits in der Sammlung »%s«"
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr "»%s« zur Sammlung »%s« hinzugefügt"
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr "Du hast das Medium gelöscht."
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr "Das Medium wurde nicht gelöscht, da nicht angekreuzt hast, dass du es wirklich löschen möchtest."
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr "Du versuchst Medien eines anderen Nutzers zu löschen. Sei bitte vorsichtig."
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr "Du hast das Objekt aus der Sammlung gelöscht."
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr "Das Objekt wurde nicht aus der Sammlung entfernt, weil du nicht bestätigt hast, dass du dir sicher bist."
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr "Du bist dabei ein Objekt aus der Sammlung eines anderen Nutzers zu entfernen. Sei vorsichtig."
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr "Du hast die Sammlung »%s« gelöscht"
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr "Die Sammlung wurde nicht gelöscht, weil du nicht bestätigt hast, dass du dir sicher bist."
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr "Du bist dabei eine Sammlung eines anderen Nutzers zu entfernen. Sei vorsichtig."
diff --git a/mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po
index 6950f515..1b22b786 100644
--- a/mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2013-03-11 17:21-0500\n"
+"POT-Creation-Date: 2013-06-16 20:06-0500\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"
@@ -17,93 +17,98 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 0.9.6\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
+#: mediagoblin/auth/forms.py:25
+msgid "Username"
msgstr ""
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
+#: mediagoblin/auth/forms.py:29 mediagoblin/auth/forms.py:44
+#: mediagoblin/tests/test_util.py:110
+msgid "Password"
msgstr ""
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
+#: mediagoblin/auth/forms.py:33
+msgid "Email address"
msgstr ""
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
-msgid "Username"
+#: mediagoblin/auth/forms.py:40
+msgid "Username or Email"
msgstr ""
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
-msgid "Password"
+#: mediagoblin/auth/forms.py:51
+msgid "Username or email"
msgstr ""
-#: mediagoblin/auth/forms.py:60
-msgid "Email address"
+#: mediagoblin/auth/tools.py:42
+msgid "Invalid User name or email address."
msgstr ""
-#: mediagoblin/auth/forms.py:78
-msgid "Username or email"
+#: mediagoblin/auth/tools.py:43
+msgid "This field does not take email addresses."
msgstr ""
-#: mediagoblin/auth/views.py:54
-msgid "Sorry, registration is disabled on this instance."
+#: mediagoblin/auth/tools.py:44
+msgid "This field requires an email address."
msgstr ""
-#: mediagoblin/auth/views.py:68
+#: mediagoblin/auth/tools.py:109
msgid "Sorry, a user with that name already exists."
msgstr ""
-#: mediagoblin/auth/views.py:72
+#: mediagoblin/auth/tools.py:113
msgid "Sorry, a user with that email address already exists."
msgstr ""
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:43
+msgid "Sorry, registration is disabled on this instance."
+msgstr ""
+
+#: mediagoblin/auth/views.py:133
msgid ""
"Your email address has been verified. You may now login, edit your "
"profile, and submit images!"
msgstr ""
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:139
msgid "The verification key or user id is incorrect"
msgstr ""
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:157
msgid "You must be logged in so we know who to send the email to!"
msgstr ""
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:165
msgid "You've already verified your email address!"
msgstr ""
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:178
msgid "Resent your verification email."
msgstr ""
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:209
msgid ""
"If that email address (case sensitive!) is registered an email has been "
"sent with instructions on how to change your password."
msgstr ""
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:220
msgid "Couldn't find someone with that username."
msgstr ""
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:223
msgid "An email has been sent with instructions on how to change your password."
msgstr ""
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:230
msgid ""
"Could not send password recovery email as your username is inactive or "
"your account's email address has not been verified."
msgstr ""
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:287
msgid "You can now log in using your new password."
msgstr ""
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -114,7 +119,7 @@ msgid "Description of this work"
msgstr ""
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -131,11 +136,11 @@ msgstr ""
msgid "Separate tags by commas."
msgstr ""
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr ""
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr ""
@@ -163,45 +168,45 @@ msgid "This address contains errors"
msgstr ""
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr ""
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr ""
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr ""
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
msgstr ""
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
msgstr ""
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr ""
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr ""
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr ""
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr ""
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr ""
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr ""
@@ -226,44 +231,63 @@ msgstr ""
msgid "Profile changes saved"
msgstr ""
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr ""
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr ""
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
msgstr ""
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr ""
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr ""
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr ""
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr ""
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie "
@@ -271,11 +295,15 @@ msgid ""
"this domain."
msgstr ""
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr ""
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr ""
+
#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr ""
@@ -347,7 +375,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
msgstr ""
@@ -366,7 +394,7 @@ msgstr ""
msgid "Add"
msgstr ""
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr ""
@@ -374,45 +402,45 @@ msgstr ""
msgid "File"
msgstr ""
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr ""
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr ""
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -420,76 +448,25 @@ msgstr ""
msgid "Media processing panel"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> "
-"project."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a"
-" href=\"%(source_link)s\">Source code</a> available."
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, "
-"an extraordinarily great piece of media hosting software."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your"
-" MediaGoblin account."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an "
-"account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" "
-"href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on "
-"your own server</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr ""
@@ -594,6 +571,57 @@ msgid ""
"%(verification_url)s"
msgstr ""
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> "
+"project."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a"
+" href=\"%(source_link)s\">Source code</a> available."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, "
+"an extraordinarily great piece of media hosting software."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your"
+" MediaGoblin account."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an "
+"account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" "
+"href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on "
+"your own server</a>"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -606,13 +634,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
msgid "Attachments"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:193
msgid "Add attachment"
msgstr ""
@@ -629,12 +657,22 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr ""
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
@@ -645,7 +683,7 @@ msgid "Yes, really delete my account"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr ""
@@ -662,7 +700,11 @@ msgstr ""
msgid "Changing %(username)s's account settings"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
msgstr ""
@@ -687,6 +729,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -711,6 +754,7 @@ msgid ""
msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr ""
@@ -719,6 +763,18 @@ msgstr ""
msgid "WebM file (Vorbis codec)"
msgstr ""
+#: mediagoblin/templates/mediagoblin/media_displays/image.html:36
+msgid "Created"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/media_displays/image.html:39
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#, python-format
+msgid "%(formatted_time)s ago"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -729,6 +785,10 @@ msgstr ""
msgid "Image for %(media_title)s"
msgstr ""
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
msgstr ""
@@ -827,7 +887,7 @@ msgstr ""
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr ""
@@ -871,23 +931,16 @@ msgstr ""
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
-#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
@@ -1042,7 +1095,7 @@ msgstr ""
msgid "Tagged with"
msgstr ""
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr ""
@@ -1072,6 +1125,30 @@ msgid ""
"moved or deleted."
msgstr ""
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr ""
+
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
msgstr ""
@@ -1103,74 +1180,78 @@ msgstr ""
msgid "Include a note"
msgstr ""
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
msgstr ""
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr ""
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr ""
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr ""
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr ""
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr ""
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed "
"with caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were "
"sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid "You are about to delete another user's collection. Proceed with caution."
msgstr ""
diff --git a/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.mo
index ac74a68b..645af16b 100644
--- a/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.po
index e7785d73..873869f0 100644
--- a/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.po
@@ -3,18 +3,18 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
-# <deletesoftware@yandex.ru>, 2013.
-# <deletesoftware@yandex.ru>, 2011-2012.
-# Fernando Inocencio <faigos@gmail.com>, 2011.
-# <john_w1954@fastmail.fm>, 2011.
+# aleksejrs <deletesoftware@yandex.ru>, 2013
+# aleksejrs <deletesoftware@yandex.ru>, 2011-2012
+# Fernando Inocencio <faigos@gmail.com>, 2011
+# tiguliano <john_w1954@fastmail.fm>, 2011
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-10 16:50+0000\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-06-01 21:16+0000\n"
"Last-Translator: aleksejrs <deletesoftware@yandex.ru>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language-Team: Esperanto (http://www.transifex.com/projects/p/mediagoblin/language/eo/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -22,34 +22,39 @@ msgstr ""
"Language: eo\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
-msgstr "Nevalida ensalutnomo aÅ­ retpoÅtadreso."
-
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
-msgstr "Ĉi tiu kampo ne akceptas retpoÅtadresojn."
-
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
-msgstr "Ĉi tiu kampo postulas retpoÅtadreson."
-
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
+#: mediagoblin/auth/forms.py:26
msgid "Username"
msgstr "Uzantnomo"
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
msgid "Password"
msgstr "Pasvorto"
-#: mediagoblin/auth/forms.py:60
+#: mediagoblin/auth/forms.py:34
msgid "Email address"
msgstr "RetpoÅtadreso"
-#: mediagoblin/auth/forms.py:78
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
+msgstr "Uzantonomo aÅ­ retpoÅtadreso"
+
+#: mediagoblin/auth/forms.py:52
msgid "Username or email"
msgstr "Salutnomo aÅ­ retpoÅtadreso"
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr "Nevalida ensalutnomo aÅ­ retpoÅtadreso."
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr "Ĉi tiu kampo ne akceptas retpoÅtadresojn."
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr "Ĉi tiu kampo postulas retpoÅtadreson."
+
#: mediagoblin/auth/views.py:54
msgid "Sorry, registration is disabled on this instance."
msgstr "Bedaŭrinde, registrado estas malaktivigita en tiu ĉi instalaĵo."
@@ -62,54 +67,54 @@ msgstr "BedaÅ­rinde, uzanto kun tiu nomo jam ekzistas."
msgid "Sorry, a user with that email address already exists."
msgstr "Ni bedaÅ­ras, sed konto kun tiu retpoÅtadreso jam ekzistas."
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr "Via retpoÅtadreso estas konfirmita. Vi povas nun ensaluti, redakti vian profilon, kaj alÅuti bildojn!"
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr "La kontrol-kodo aÅ­ la uzantonomo ne estas korekta"
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr "Vi devas esti ensalutita, por ke ni sciu, al kiu sendi la retleteron!"
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr "Vi jam konfirmis vian retpoÅtadreson!"
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr "Resendi vian kontrol-mesaÄon."
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
msgstr "Se tiu retpoÅtadreso (majuskloj gravas!) estas registrita, tien senditas retletero kun instrukcio pri kiel ÅanÄi vian pasvorton."
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
msgstr "Trovitas neniu kun tiu ensalutnomo."
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
msgstr "Senditas retletero kun instrukcio pri kiel ÅanÄi vian pasvorton."
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr "Ni ne povas sendi pasvortsavan retleteron, ĉar aÅ­ via konto estas neaktiva, aÅ­ Äia retpoÅtadreso ne estis konfirmita."
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
msgstr "Nun vi povas ensaluti per via nova pasvorto."
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -120,7 +125,7 @@ msgid "Description of this work"
msgstr "Priskribo de ĉi tiu verko"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -136,11 +141,11 @@ msgstr "Etikedoj"
msgid "Separate tags by commas."
msgstr "Dividu la etikedojn per komoj."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "La distingiga adresparto"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "La distingiga adresparto ne povas esti malplena"
@@ -168,45 +173,45 @@ msgid "This address contains errors"
msgstr "Ĉi tiu adreso enhavas erarojn"
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr "La malnova pasvorto"
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr "Enigu vian malnovan pasvorton por pruvi, ke ĉi tiu konto estas via."
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr "La nova pasvorto"
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
msgstr "Permesila prefero"
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
-msgstr ""
+msgstr "Tiu ĉi permesilo estos antaÅ­elektita en la alÅutformularoj."
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr "RetpoÅtu min kiam aliaj komentas pri miaj alÅutaĵoj."
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr "La titolo ne povas malpleni."
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr "Priskribo de la kolekto"
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr "La distingiga adresparto de ĉi tiu kolekto. Ordinare ne necesas Äin ÅanÄi."
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr "La malnova pasvorto"
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr "Enigu vian malnovan pasvorton por pruvi, ke ĉi tiu konto estas via."
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr "La nova pasvorto"
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr "Ĉi tiu uzanto jam havas dosieron kun tiu distingiga adresparto."
@@ -231,44 +236,63 @@ msgstr "Vi redaktas profilon de alia uzanto. Agu singardeme."
msgid "Profile changes saved"
msgstr "ProfilÅanÄoj estis konservitaj"
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr "MalÄusta pasvorto"
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr "Kontagordoj estis konservitaj"
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
msgstr "Vi bezonas konfirmi la forigon de via konto."
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr "Vi jam havas kolekton kun la nomo «%s»!"
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr "Ĉi tiu uzanto jam havas kolekton kun tiu distingiga adresparto."
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr "Vi redaktas kolekton de alia uzanto. Agu singardeme."
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr "MalÄusta pasvorto"
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr "Via pasvorto estas sukcese ÅanÄita"
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr "Alligo de etoso ne eblas… ne estas elektita ekzistanta etoso\n"
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr "Mankas dosierujo kun aspektiloj por la etoso\n"
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr "Tamen trovitas — kaj forigitas — malnova simbola ligilo al dosierujo.\n"
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr ""
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
@@ -276,12 +300,16 @@ msgid ""
"domain."
msgstr ""
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr "Mi pardonpetas, mi ne subtenas tiun dosiertipon :("
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr ""
+
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr "Malsukcesis transkodado de filmo"
@@ -348,7 +376,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
msgstr ""
@@ -367,7 +395,7 @@ msgstr ""
msgid "Add"
msgstr "Aldoni"
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr "La provizita dosiero ne konformas al la informtipo."
@@ -375,45 +403,45 @@ msgstr "La provizita dosiero ne konformas al la informtipo."
msgid "File"
msgstr "Dosiero"
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr "Vi devas provizi dosieron."
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr "Hura! AlÅutitas!"
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr "Kolekto «%s» aldonitas!"
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr "Konfirmu viecon de la retpoÅtadreso!"
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
msgstr "elsaluti"
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr "Ensaluti"
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr "Konto de <a href=\"%(user_url)s\">%(user_name)s</a>"
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr "ÅœanÄi kontagordojn"
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -421,72 +449,25 @@ msgstr "ÅœanÄi kontagordojn"
msgid "Media processing panel"
msgstr "Kontrolejo pri dosierpreparado."
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
msgstr "Elsaluti"
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr "Aldoni dosieron"
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
msgstr "Krei novan kolekton"
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr "Funkcias per <a href=\"http://mediagoblin.org/\" title='Versio %(version)s'>MediaGoblin</a>, unu el la <a href=\"http://gnu.org/\">projektoj de GNU</a>."
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr "Disponigita laÅ­ la permesilo <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. Haveblas<a href=\"%(source_link)s\">fontotekstaro</a>."
-
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
msgstr "Bildo de zorgigita koboldo"
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr "Ĉirkaŭrigardi"
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr "Saluton, kaj bonvenon al ĉi tiu MediaGoblina retpaÄaro!"
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr "Ĉi tiu retpaÄaro funkcias per <a href=\"http://mediagoblin.org\">MediaGoblin</a>, eksterordinare bonega programaro por gastigado de aÅ­dâ€vidâ€dosieroj."
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr "Por aldoni viajn proprajn dosierojn, afiÅi komentariojn ktp, vi povas ensaluti je via MediaGoblina konto."
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr "Ĉu vi ankoraÅ­ ne havas tian? Ne malÄoju!"
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">Kreu konton en ĉi tiu retejo</a>\n aŭ\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">ekfunkciigu MediaGoblin’on en via propra servilo</a>"
-
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr "Laste aldonitaj dosieroj"
@@ -592,6 +573,53 @@ msgid ""
"%(verification_url)s"
msgstr "Sal %(username)s,\n\npor aktivigi vian GNU MediaGoblin konton, malfermu la sekvantan URLon en via retumilo:\n\n%(verification_url)s"
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr "Funkcias per <a href=\"http://mediagoblin.org/\" title='Versio %(version)s'>MediaGoblin</a>, unu el la <a href=\"http://gnu.org/\">projektoj de GNU</a>."
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr "Disponigita laÅ­ la permesilo <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. Haveblas<a href=\"%(source_link)s\">fontotekstaro</a>."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr "Ĉirkaŭrigardi"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "Saluton, kaj bonvenon al ĉi tiu MediaGoblina retpaÄaro!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr "Ĉi tiu retpaÄaro funkcias per <a href=\"http://mediagoblin.org\">MediaGoblin</a>, eksterordinare bonega programaro por gastigado de aÅ­dâ€vidâ€dosieroj."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr "Por aldoni viajn proprajn dosierojn, afiÅi komentariojn ktp, vi povas ensaluti je via MediaGoblina konto."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr "Ĉu vi ankoraÅ­ ne havas tian? Ne malÄoju!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -604,13 +632,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr "Aldoni kundosierojn por %(media_title)s"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
msgstr "Kundosieroj"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
msgstr "Aldoni kundosieron"
@@ -627,12 +655,22 @@ msgstr "Nuligi"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr "Konservi ÅanÄojn"
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr "ÅœanÄado de pasvorto de %(username)s"
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr "Konservi"
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
@@ -643,7 +681,7 @@ msgid "Yes, really delete my account"
msgstr "Jes, efektive forigi mian konton"
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "Forigi senrevene"
@@ -660,7 +698,11 @@ msgstr "Priredaktado de %(media_title)s"
msgid "Changing %(username)s's account settings"
msgstr "ÅœanÄado de kontagordoj de %(username)s"
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr "ÅœanÄi la pasvorton"
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
msgstr "Forigi mian konton."
@@ -685,6 +727,7 @@ msgstr "Dosieroj kun etikedo: %(tag_name)s"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -709,6 +752,7 @@ msgid ""
msgstr "Vi povas akiri modernan TTT-legilon, kapablan \n\tsonigi la registraĵon ĉe <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!"
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr "originalan dosieron"
@@ -717,6 +761,7 @@ msgstr "originalan dosieron"
msgid "WebM file (Vorbis codec)"
msgstr "WebMan dosieron (kun Vorbisa kodaĵo)"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -727,6 +772,10 @@ msgstr "WebMan dosieron (kun Vorbisa kodaĵo)"
msgid "Image for %(media_title)s"
msgstr "Bildo de «%(media_title)s»"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr "PDF-dosiero"
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
msgstr ""
@@ -825,7 +874,7 @@ msgstr "Ĉu vere forigi %(title)s?"
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr "Ĉu vere forigi %(media_title)s el %(collection_title)s?"
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr "Forigi"
@@ -868,24 +917,28 @@ msgstr "Dosieroj de <a href=\"%(user_url)s\">%(username)s</a>"
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr "■ПроÑмотр файлов Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ <a href=\"%(user_url)s\">%(username)s</a>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
msgstr "Aldoni komenton"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
msgstr "Aldoni ĉi tiun komenton"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
-msgstr "je"
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
-msgstr "<h3>Aldonita je</h3>\n <p>la %(date)s</p>"
+msgid "%(formatted_time)s ago"
+msgstr "antaÅ­ %(formatted_time)s"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr "Aldonita"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
+msgstr "Kreita"
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40
@@ -1041,7 +1094,7 @@ msgstr "malpli nova"
msgid "Tagged with"
msgstr "Markita per"
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr "Malsukcesis lego de la bildodosiero"
@@ -1071,6 +1124,30 @@ msgid ""
" deleted."
msgstr ""
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr "jaro(j)"
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr "monato(j)"
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr "semajno(j)"
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr "tago(j)"
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr "horo(j)"
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr "minuto(j)"
+
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
msgstr "Komenti"
@@ -1102,73 +1179,77 @@ msgstr "-- Elektu --"
msgid "Include a note"
msgstr "Rimarko"
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
msgstr "komentis je via afiÅo"
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr "Ve, komentado estas malebligita."
+
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr "Oj, via komento estis malplena."
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr "Via komento estis afiÅita!"
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
msgstr "Bonvolu kontroli vian enigitaĵon kaj reprovi."
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr "Necesas elekti aÅ­ aldoni kolekton"
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr "«%s» jam estas en la kolekto «%s»"
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr "«%s» estis aldonita al la kolekto «%s»"
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr "Vi forigis la dosieron."
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr "La dosiero ne estis forigita, ĉar vi ne konfirmis vian certecon per la markilo."
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr "Vi estas forigonta dosieron de alia uzanto. Estu singardema."
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr "Vi forigis la dosieron el la kolekto."
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr "La dosiero ne estis forigita, ĉar vi ne konfirmis vian certecon per la markilo."
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr "Vi estas forigonta dosieron el kolekto de alia uzanto. Agu singardeme."
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr "Vi forigis la kolekton «%s»"
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr "La kolekto ne estis forigita, ĉar vi ne konfirmis vian certecon per la markilo."
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr "Vi estas forigonta kolekton de alia uzanto. Agu singardeme."
diff --git a/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.mo
index e2df0731..c5e50f53 100644
--- a/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.po
index 21dce0b1..8c2f046f 100644
--- a/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.po
@@ -3,25 +3,25 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
-# <deletesoftware@yandex.ru>, 2011, 2012.
-# <ekenbrand@hotmail.com>, 2011.
-# <jacobo@gnu.org>, 2011-2012.
-# Javier Di Mauro <javierdimauro@gmail.com>, 2011.
-# <juangsub@gmail.com>, 2011.
-# <juanma@kde.org.ar>, 2011, 2012.
-# <larjona99@gmail.com>, 2012.
-# Laura Arjona Reina <larjona99@gmail.com>, 2013.
-# Mario Rodriguez <msrodriguez00@gmail.com>, 2011.
-# <mu@member.fsf.org>, 2011.
-# <shackra@riseup.net>, 2012.
-# <stardustprincess17@hotmail.com>, 2012.
+# aleksejrs <deletesoftware@yandex.ru>, 2011, 2012
+# ekenbrand <ekenbrand@hotmail.com>, 2011
+# nvjacobo <jacobo@gnu.org>, 2011-2012
+# Javier Di Mauro <javierdimauro@gmail.com>, 2011
+# case <juangsub@gmail.com>, 2011
+# juanman <juanma@kde.org.ar>, 2011, 2012
+# larjona <larjona99@gmail.com>, 2012
+# larjona <larjona99@gmail.com>, 2013
+# Mario Rodriguez <msrodriguez00@gmail.com>, 2011
+# Manuel Urbano Santos <mu@member.fsf.org>, 2011
+# shackra <shackra@riseup.net>, 2012
+# Elesa <stardustprincess17@hotmail.com>, 2012
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-05 00:04+0000\n"
-"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-06-02 21:23+0000\n"
+"Last-Translator: larjona <larjona99@gmail.com>\n"
"Language-Team: Spanish (http://www.transifex.com/projects/p/mediagoblin/language/es/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -30,34 +30,39 @@ msgstr ""
"Language: es\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
-msgstr "Nombre de usuario o correo electrónico inválido."
-
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
-msgstr "Este campo no acepta direcciones de correo."
-
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
-msgstr "Este campo requiere una dirección de correo."
-
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
+#: mediagoblin/auth/forms.py:26
msgid "Username"
msgstr "Nombre de usuario"
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
msgid "Password"
msgstr "Contraseña"
-#: mediagoblin/auth/forms.py:60
+#: mediagoblin/auth/forms.py:34
msgid "Email address"
msgstr "Dirección de correo electrónico"
-#: mediagoblin/auth/forms.py:78
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
+msgstr "Nombre de usuario o correo electrónico"
+
+#: mediagoblin/auth/forms.py:52
msgid "Username or email"
msgstr "Nombre de usuario o email"
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr "Nombre de usuario o correo electrónico inválido."
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr "Este campo no acepta direcciones de correo."
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr "Este campo requiere una dirección de correo."
+
#: mediagoblin/auth/views.py:54
msgid "Sorry, registration is disabled on this instance."
msgstr "Lo sentimos, el registro está deshabilitado en este momento."
@@ -70,54 +75,54 @@ msgstr "Lo sentimos, ya existe un usuario con ese nombre."
msgid "Sorry, a user with that email address already exists."
msgstr "Lo sentimos, ya existe un usuario con esa dirección de email."
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr "Tu dirección de correo electrónico ha sido verificada. ¡Ahora puedes iniciar sesión, editar tu perfil, y enviar imágenes!"
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr "La clave de verificación o la identificación de usuario son incorrectas"
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr "¡Debes iniciar sesión para que podamos saber a quién le enviamos el correo electrónico!"
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr "¡Ya has verificado tu dirección de correo!"
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr "Se reenvió tu correo electrónico de verificación."
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
msgstr "Si esa dirección de correo (¡sensible a mayúsculas y minúsculas!) está registrada, se ha enviado un correo con instrucciones para cambiar la contraseña."
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
msgstr "No se ha podido encontrar a nadie con ese nombre de usuario."
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
msgstr "Un correo electrónico ha sido enviado con instrucciones sobre cómo cambiar tu contraseña."
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr "No se pudo enviar un correo electrónico de recuperación de contraseñas porque tu nombre de usuario está inactivo o la dirección de su cuenta de correo electrónico no ha sido verificada."
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
msgstr "Ahora tu puedes iniciar sesión usando tu nueva contraseña."
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -128,7 +133,7 @@ msgid "Description of this work"
msgstr "Descripción de esta obra"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -144,11 +149,11 @@ msgstr "Etiquetas"
msgid "Separate tags by commas."
msgstr "Separa las etiquetas por comas."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "Ficha"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "La ficha no puede estar vacía"
@@ -176,45 +181,45 @@ msgid "This address contains errors"
msgstr "La dirección contiene errores"
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr "Vieja contraseña"
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr "Escriba la anterior contraseña para demostrar que esta cuenta te pertenece."
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr "Nueva contraseña"
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
msgstr "Preferencias de licencia"
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
msgstr "Ésta será tu licencia predeterminada en los formularios de subida."
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr "Envíame un correo cuando otros escriban comentarios sobre mi contenido"
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr "El título no puede estar vacío"
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr "Descripción de esta colección"
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr "El título de la dirección de esta colección. Generalmente no necesitas cambiar esto."
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr "Vieja contraseña"
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr "Escriba la anterior contraseña para demostrar que esta cuenta te pertenece."
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr "Nueva contraseña"
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr "Una entrada con esa ficha ya existe para este usuario."
@@ -239,44 +244,63 @@ msgstr "Estás editando un perfil de usuario. Procede con precaución."
msgid "Profile changes saved"
msgstr "Los cambios de perfil fueron salvados"
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr "Contraseña incorrecta"
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr "las configuraciones de cuenta fueron salvadas"
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
msgstr "Necesitas confirmar el borrado de tu cuenta."
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr "¡Ya tienes una colección llamada \"%s\"!"
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr "Una colección con esa ficha ya existe para este usuario/a."
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr "Estás editando la colección de otro usuario/a. Ten cuidado."
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr "Contraseña incorrecta"
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr "Se ha cambiado la contraseña correctamente"
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr "No se puede enlazar al tema... no hay un tema seleccionado\n"
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr "No hay directorio activo para este tema\n\n\n"
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr "Sin embargo, se encontró un enlace simbólico de un directorio antiguo; ha sido borrado.\n"
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr "No se pudo enlazar \"%s\": %s existe y no es un enlace simbólico\n"
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr "Omitiendo \"%s\"; ya está establecido.\n"
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr "Se encontró un enlace antiguo para \"%s\"; se eliminará.\n"
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
@@ -284,12 +308,16 @@ msgid ""
"domain."
msgstr "No se encuentra la cookie CSRF. Esto suele ser debido a un bloqueador de cookies o similar.<br/> Por favor asegúrate de permitir las cookies para este dominio."
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr "Lo sentidos, No soportamos ese tipo de archivo :("
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr "ha fallado la ejecución de unoconv, comprueba el fichero de registro (log)"
+
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr "Ha fallado la conversión de vídeo"
@@ -356,7 +384,7 @@ msgstr "La URI para redireccionar las aplicaciones, este campo es <strong>requer
msgid "This field is required for public clients"
msgstr "Este campo es requerido para los clientes públicos"
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
msgstr "¡El cliente {0} ha sido registrado!"
@@ -375,7 +403,7 @@ msgstr "Tus clientes OAuth"
msgid "Add"
msgstr "Añadir "
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr "Archivo inválido para el formato seleccionado."
@@ -383,45 +411,45 @@ msgstr "Archivo inválido para el formato seleccionado."
msgid "File"
msgstr "Archivo"
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr "Debes proporcionar un archivo."
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr "¡Yuju! ¡Enviado!"
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr "¡Colección \"%s\" añadida!"
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr "¡Verifica tu email!"
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
msgstr "cerrar sesión"
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr "Iniciar sesión"
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr "Cuenta de <a href=\"%(user_url)s\">%(user_name)s</a>"
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr "Cambiar la configuración de la cuenta"
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -429,72 +457,25 @@ msgstr "Cambiar la configuración de la cuenta"
msgid "Media processing panel"
msgstr "Panel de procesamiento de contenido"
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
-msgstr ""
+msgstr "Cerrar sesión"
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr "Añadir contenido"
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
msgstr "Crear nueva colección"
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr "Funciona con <a href=\"http://mediagoblin.org/\" title='Version %(version)s'>MediaGoblin</a>, un proyecto <a href=\"http://gnu.org/\">GNU</a>."
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr "Publicado bajo la <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\"> Código fuente</a> disponible."
-
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
msgstr "Imagen de un goblin estresándose"
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr "Explorar"
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr "Hola, ¡bienvenido a este sitio de MediaGoblin!"
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr "Este sitio está montado con <a href=\"http://mediagoblin.org\">MediaGoblin</a>, un extraordinario programa libre para alojar, gestionar y compartir contenido multimedia."
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr "Para añadir tus propios contenidos, dejar comentarios y más, puedes iniciar sesión con tu cuenta de MediaGoblin."
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr "¿Aún no tienes una? ¡Es fácil!"
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">Crea una cuenta en este sitio</a>\n o\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Instala Mediagoblin en tu propio servidor</a>"
-
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr "El contenido más reciente"
@@ -600,6 +581,53 @@ msgid ""
"%(verification_url)s"
msgstr "Hola %(username)s,\n\npara activar tu cuenta de GNU MediaGoblin, abre la siguiente URL en tu navegador:\n\n%(verification_url)s "
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr "Funciona con <a href=\"http://mediagoblin.org/\" title='Version %(version)s'>MediaGoblin</a>, un proyecto <a href=\"http://gnu.org/\">GNU</a>."
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr "Publicado bajo la <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\"> Código fuente</a> disponible."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr "Explorar"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "Hola, ¡bienvenido a este sitio de MediaGoblin!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr "Este sitio está montado con <a href=\"http://mediagoblin.org\">MediaGoblin</a>, un extraordinario programa libre para alojar, gestionar y compartir contenido multimedia."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr "Para añadir tus propios contenidos, dejar comentarios y más, puedes iniciar sesión con tu cuenta de MediaGoblin."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr "¿Aún no tienes una? ¡Es fácil!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">Crear una cuenta en este sitio</a>\n o\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Instalar MediaGoblin en tu propio servidor</a>"
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -612,13 +640,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr "Editando archivos adjuntos a %(media_title)s"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
msgstr "Adjuntos"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
msgstr "Agregar adjunto"
@@ -635,12 +663,22 @@ msgstr "Cancelar"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr "Guardar cambios"
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr "Cambiando la contraseña de %(username)s"
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr "Guardar"
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
@@ -651,7 +689,7 @@ msgid "Yes, really delete my account"
msgstr "Sí, borrar mi cuenta"
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "Eliminar permanentemente"
@@ -668,7 +706,11 @@ msgstr "Editando %(media_title)s "
msgid "Changing %(username)s's account settings"
msgstr "Cambio de %(username)s la configuración de la cuenta "
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr "Cambiar tu contraseña."
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
msgstr "Borrar mi cuenta"
@@ -693,6 +735,7 @@ msgstr "Contenido etiquetado con: %(tag_name)s"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -717,6 +760,7 @@ msgid ""
msgstr "Tú puedes obtener un navegador más moderno que \n\tpueda reproducir el audio <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!"
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr "Archivo original"
@@ -725,6 +769,7 @@ msgstr "Archivo original"
msgid "WebM file (Vorbis codec)"
msgstr "Archivo WebM (códec Vorbis)"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -735,6 +780,10 @@ msgstr "Archivo WebM (códec Vorbis)"
msgid "Image for %(media_title)s"
msgstr "Imágenes para %(media_title)s"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr "Fichero PDF"
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
msgstr "Alternar Rotar"
@@ -833,7 +882,7 @@ msgstr "¿Realmente deseas eliminar %(title)s?"
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr "¿Realmente quieres quitar %(media_title)s de %(collection_title)s?"
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr "Quitar"
@@ -876,24 +925,28 @@ msgstr "Contenido de <a href=\"%(user_url)s\">%(username)s</a>"
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr "â– Explorando contenido de <a href=\"%(user_url)s\">%(username)s</a>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
msgstr "Añadir un comentario"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
msgstr "Añade un comentario "
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
-msgstr "en"
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
-msgstr "<h3>Añadido en</h3>\n <p>%(date)s</p>"
+msgid "%(formatted_time)s ago"
+msgstr "hace %(formatted_time)s"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr "Agregado"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
+msgstr "Creado"
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40
@@ -1049,7 +1102,7 @@ msgstr "Más viejo"
msgid "Tagged with"
msgstr "Marcado con"
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr "No se pudo leer el archivo de imagen."
@@ -1079,6 +1132,30 @@ msgid ""
" deleted."
msgstr "Parece que no hay ninguna página en esta dirección. ¡Lo siento!</p><p>Si estás seguro de que la dirección es correcta, quizá han borrado o movido la página que estás buscando."
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr "año"
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr "mes"
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr "semana"
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr "día"
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr "hora"
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr "minuto"
+
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
msgstr "Comentario"
@@ -1110,73 +1187,77 @@ msgstr "-- Selecciona --"
msgid "Include a note"
msgstr "Incluir una nota"
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
msgstr "comentó tu publicación"
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr "Lo siento, los comentarios están desactivados."
+
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr "Ups, tu comentario estaba vacío."
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr "¡Tu comentario ha sido publicado!"
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
msgstr "Por favor, revisa tus entradas e inténtalo de nuevo."
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr "Tienes que seleccionar o añadir una colección"
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr "%s\" ya está en la colección \"%s\""
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr "\"%s\" añadido a la colección \"%s\""
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr "Eliminaste el contenido"
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr "El contenido no se eliminó porque no marcaste que estabas seguro."
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr "Estás a punto de eliminar un contenido de otro usuario. Procede con precaución."
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr "Borraste el ítem de la colección."
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr "El ítem no fue removido porque no confirmaste que estuvieras seguro/a."
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr "Estás a punto de borrar un ítem de la colección de otro usuario. Procede con cuidado."
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr "Borraste la colección \"%s\""
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr "La colección no fue borrada porque no confirmaste que estuvieras seguro/a."
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr "Estás a punto de borrar la colección de otro usuario. Procede con cuidado."
diff --git a/mediagoblin/i18n/fa/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/fa/LC_MESSAGES/mediagoblin.mo
index 4b319ebd..3422ad97 100644
--- a/mediagoblin/i18n/fa/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/fa/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/fa/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/fa/LC_MESSAGES/mediagoblin.po
index 028ab5d4..08e73e1a 100644
--- a/mediagoblin/i18n/fa/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/fa/LC_MESSAGES/mediagoblin.po
@@ -3,15 +3,15 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
-# <amir007ag@gmail.com>, 2012.
+# Numb <amir007ag@gmail.com>, 2012
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-05 00:04+0000\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-05-27 18:54+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language-Team: Persian (http://www.transifex.com/projects/p/mediagoblin/language/fa/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -19,34 +19,39 @@ msgstr ""
"Language: fa\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
+#: mediagoblin/auth/forms.py:26
msgid "Username"
msgstr "نام کاربری"
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
msgid "Password"
msgstr "گذرواٰژه"
-#: mediagoblin/auth/forms.py:60
+#: mediagoblin/auth/forms.py:34
msgid "Email address"
msgstr "آدرس ایمیل"
-#: mediagoblin/auth/forms.py:78
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
+msgstr ""
+
+#: mediagoblin/auth/forms.py:52
msgid "Username or email"
msgstr ""
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr ""
+
#: mediagoblin/auth/views.py:54
msgid "Sorry, registration is disabled on this instance."
msgstr "Ù…ØªØ§Ø³ÙØ§Ù†Ù‡ØŒØ«Ø¨ØªÙ†Ø§Ù… به طور موقت غیر ÙØ¹Ø§Ù„ است."
@@ -59,54 +64,54 @@ msgstr "Ù…ØªØ§Ø³ÙØ§Ù†Ù‡ کاربری با این نام کاربری وجود Ø
msgid "Sorry, a user with that email address already exists."
msgstr ""
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr "ایمیل شما تایید شد.شما می توانید حالا وارد شوید،نمایه خود را ویرایش کنید و تصاویر خود را ثبت کنید!"
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr "این کد تاییدیه یا شناسه کاربری صحیح نیست."
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr ""
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr ""
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr "ایمیل تاییدیه باز ارسال شد."
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
msgstr ""
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
msgstr ""
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
msgstr ""
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr ""
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
msgstr ""
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -117,7 +122,7 @@ msgid "Description of this work"
msgstr ""
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -133,11 +138,11 @@ msgstr "برچسب"
msgid "Separate tags by commas."
msgstr ""
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr ""
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr ""
@@ -165,45 +170,45 @@ msgid "This address contains errors"
msgstr ""
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr ""
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr ""
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr ""
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
msgstr ""
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
msgstr ""
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr ""
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr ""
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr ""
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr ""
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr ""
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr ""
@@ -228,44 +233,63 @@ msgstr "شما در حال ویرایش نمایه کاربر دیگری هستÛ
msgid "Profile changes saved"
msgstr ""
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr ""
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr ""
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
msgstr ""
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr ""
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr ""
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr ""
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr ""
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
@@ -273,12 +297,16 @@ msgid ""
"domain."
msgstr ""
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr ""
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr ""
+
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr ""
@@ -345,7 +373,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
msgstr ""
@@ -364,7 +392,7 @@ msgstr ""
msgid "Add"
msgstr ""
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr "ÙØ§ÛŒÙ„ÛŒ نا معتبر برای نوع رسانه داده شده."
@@ -372,45 +400,45 @@ msgstr "ÙØ§ÛŒÙ„ÛŒ نا معتبر برای نوع رسانه داده شده."
msgid "File"
msgstr "ÙØ§ÛŒÙ„"
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr "شما باید ÙØ§ÛŒÙ„ÛŒ ارايه بدهید."
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr "هورا!ثبت شد!"
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr "ورود"
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -418,72 +446,25 @@ msgstr ""
msgid "Media processing panel"
msgstr "پنل رسیدگی به رسانه ها"
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr ""
@@ -589,6 +570,53 @@ msgid ""
"%(verification_url)s"
msgstr "سلام %(username)s,\n\nبرای ÙØ¹Ø§Ù„ سازی شناسه کاربری گنو مدیاگوبلین خود ،پیوند زیر را در مرورگر خود باز کنید.\n\n%(verification_url)s"
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -601,13 +629,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
msgstr ""
@@ -624,12 +652,22 @@ msgstr "انصراÙ"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr "ذخیره تغییرات"
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
@@ -640,7 +678,7 @@ msgid "Yes, really delete my account"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr ""
@@ -657,7 +695,11 @@ msgstr "ویرایش %(media_title)s"
msgid "Changing %(username)s's account settings"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
msgstr ""
@@ -682,6 +724,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -706,6 +749,7 @@ msgid ""
msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr ""
@@ -714,6 +758,7 @@ msgstr ""
msgid "WebM file (Vorbis codec)"
msgstr ""
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -724,6 +769,10 @@ msgstr ""
msgid "Image for %(media_title)s"
msgstr ""
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
msgstr ""
@@ -822,7 +871,7 @@ msgstr ""
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr ""
@@ -865,23 +914,27 @@ msgstr "<a href=\"%(user_url)s\">%(username)s</a>'s رسانه های"
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
+#, python-format
+msgid "%(formatted_time)s ago"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
-#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
@@ -1038,7 +1091,7 @@ msgstr ""
msgid "Tagged with"
msgstr ""
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr ""
@@ -1068,6 +1121,30 @@ msgid ""
" deleted."
msgstr ""
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr ""
+
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
msgstr ""
@@ -1099,73 +1176,77 @@ msgstr ""
msgid "Include a note"
msgstr ""
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
msgstr ""
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr ""
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr ""
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr ""
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr ""
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr ""
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr ""
diff --git a/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.mo
index ada992ce..7bc860a0 100644
--- a/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.po
index b4c76bd2..6103c439 100644
--- a/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.po
@@ -3,22 +3,22 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
-# <a5565930@nepwk.com>, 2011.
-# <alexispay@gmail.com>, 2012.
-# <chesuidayeur@yahoo.fr>, 2011.
-# <crash_bibit@hotmail.com>, 2013.
-# <joehillen@gmail.com>, 2011.
-# Laurent Pointecouteau <hell_pe@no-log.org>, 2013.
-# <marktraceur@gmail.com>, 2011.
-# <maxineb@members.fsf.org>, 2011.
-# <transifex@wandborg.se>, 2011.
-# Valentin Villenave <valentin@villenave.net>, 2011.
+# ianux <a5565930@nepwk.com>, 2011
+# alcazar <alexispay@gmail.com>, 2012
+# chesuidayeur <chesuidayeur@yahoo.fr>, 2011
+# Bibit <crash_bibit@hotmail.com>, 2013
+# joehillen <joehillen@gmail.com>, 2011
+# hellpe <hell_pe@no-log.org>, 2013
+# MarkTraceur <marktraceur@gmail.com>, 2011
+# maxineb <maxineb@members.fsf.org>, 2011
+# joar <transifex@wandborg.se>, 2011
+# Valentin Villenave <valentin@villenave.net>, 2011
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-05 00:04+0000\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-05-27 18:54+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: French (http://www.transifex.com/projects/p/mediagoblin/language/fr/)\n"
"MIME-Version: 1.0\n"
@@ -28,34 +28,39 @@ msgstr ""
"Language: fr\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
-msgstr "Nom d'utilisateur ou adresse de courriel invalide."
-
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
+#: mediagoblin/auth/forms.py:26
msgid "Username"
msgstr "Nom d'utilisateur"
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
msgid "Password"
msgstr "Mot de passe"
-#: mediagoblin/auth/forms.py:60
+#: mediagoblin/auth/forms.py:34
msgid "Email address"
msgstr "Adresse e-mail"
-#: mediagoblin/auth/forms.py:78
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
+msgstr ""
+
+#: mediagoblin/auth/forms.py:52
msgid "Username or email"
msgstr "Nom d'utilisateur ou email"
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr "Nom d'utilisateur ou adresse de courriel invalide."
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr ""
+
#: mediagoblin/auth/views.py:54
msgid "Sorry, registration is disabled on this instance."
msgstr "L'inscription n'est pas activée sur ce serveur, désolé."
@@ -68,54 +73,54 @@ msgstr "Un utilisateur existe déjà avec ce nom, désolé."
msgid "Sorry, a user with that email address already exists."
msgstr "Désolé, il existe déjà un utilisateur ayant cette adresse e-mail."
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr "Votre adresse e-mail a bien été vérifiée. Vous pouvez maintenant vous identifier, modifier votre profil, et soumettre des images !"
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr "La clé de vérification ou le nom d'utilisateur est incorrect."
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr "Vous devez être authentifié afin que nous sachions à qui envoyer l'e-mail !"
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr "Votre adresse e-mail a déjà été vérifiée !"
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr "E-mail de vérification renvoyé."
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
msgstr ""
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
msgstr "Nom d'utilisateur introuvable."
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
msgstr "Un email contenant les instructions pour changer votre mot de passe viens de vous être envoyé"
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr "Impossible d'envoyer un email de récupération de mot de passe : votre compte est inactif ou bien l'email de votre compte n'a pas été vérifiée."
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
msgstr "Vous pouvez maintenant vous connecter avec votre nouveau mot de passe."
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -126,7 +131,7 @@ msgid "Description of this work"
msgstr "Descriptif pour ce travail"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -142,11 +147,11 @@ msgstr "Tags"
msgid "Separate tags by commas."
msgstr "Séparez les champs avec des virgules."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "Légende"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "La légende ne peut pas être laissée vide."
@@ -174,45 +179,45 @@ msgid "This address contains errors"
msgstr "Cette adresse contiens des erreurs"
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr "Ancien mot de passe."
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr "Entrez votre ancien mot de passe pour prouver que vous êtes bien le propriétaire de ce compte."
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr "Nouveau mot de passe"
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
msgstr ""
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
msgstr ""
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr "Me prévenir par email lorsque d'autres commentent mes médias"
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr "Le titre ne peut être vide"
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr "Description de cette collection"
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr "Le titre affiché dans l'URL de la collection. Vous n'avez généralement pas besoin d'y toucher."
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr "Ancien mot de passe."
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr "Entrez votre ancien mot de passe pour prouver que vous êtes bien le propriétaire de ce compte."
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr "Nouveau mot de passe"
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr "Une entrée existe déjà pour cet utilisateur avec la même légende."
@@ -237,44 +242,63 @@ msgstr "Vous vous apprêtez à modifier le profil d'un utilisateur. Veuillez pre
msgid "Profile changes saved"
msgstr "Les changements apportés au profile ont étés sauvegardés"
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr "Mauvais mot de passe"
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr "Les changements des préférences du compte ont étés sauvegardés"
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
msgstr "Vous devez confirmer la suppression de votre compte."
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr "Vous avez déjà une collection appelée \"%s\" !"
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr "Vous éditez la collection d'un autre utilisateurs. Faites attention."
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr "Mauvais mot de passe"
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr "Impossible de lier le thème... Aucun thème associé\n"
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr "Aucun répertoire \"asset\" pour ce thème\n"
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr ""
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr ""
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
@@ -282,12 +306,16 @@ msgid ""
"domain."
msgstr ""
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr "Désolé, mais je ne prends pas en charge cette extension de fichier :("
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr ""
+
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr "L'encodage de la vidéo à échoué"
@@ -354,7 +382,7 @@ msgstr "L'URI de redirection pour l'application, ce champ est <strong>requis</st
msgid "This field is required for public clients"
msgstr "Ce champ est requis pour les clients publics"
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
msgstr "Le client {0} as été enregistré !"
@@ -373,7 +401,7 @@ msgstr ""
msgid "Add"
msgstr "Ajouter"
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr "Le fichier envoyé ne correspond pas au type de média."
@@ -381,45 +409,45 @@ msgstr "Le fichier envoyé ne correspond pas au type de média."
msgid "File"
msgstr "Fichier"
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr "Il vous faut fournir un fichier."
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr "Youhou, c'est envoyé !"
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr "Collection \"%s\" ajoutée !"
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr "Vérifiez votre adresse e-mail !"
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
msgstr "Déconnexion"
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr "S'identifier"
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr "Changer les paramètres du compte"
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -427,72 +455,25 @@ msgstr "Changer les paramètres du compte"
msgid "Media processing panel"
msgstr "Panneau pour le traitement des médias"
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr "Ajouter des médias"
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
msgstr "Créer une nouvelle collection"
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr "Disponible sous la licence <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Code source</a> disponible."
-
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr "Explorer"
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr "Bonjour, et bienvenue sur ce site MediaGoblin !"
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr "Ce site fait tourner <a href=\"http://mediagoblin.org\">MediaGoblin</a>, un logiciel d'hébergement de média extraordinairement génial."
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr "Pour ajouter vos propres médias, commenter, et bien plus encore, vous pouvez vous connecter avec votre compte MediaGoblin"
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr "Vous n'en avez pas ? C'est facile !"
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">Créez un compte sur ce site</a>\n ou\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Déployez MediaGoblin sur votre propre serveur</a>"
-
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr "Tout derniers media"
@@ -598,6 +579,53 @@ msgid ""
"%(verification_url)s"
msgstr "Bonjour %(username)s,\n\npour activer votre compte sur GNU MediaGoblin, veuillez vous rendre à l'adresse suivante avec votre navigateur web:\n\n%(verification_url)s"
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr "Disponible sous la licence <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Code source</a> disponible."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr "Explorer"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "Bonjour, et bienvenue sur ce site MediaGoblin !"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr "Ce site fait tourner <a href=\"http://mediagoblin.org\">MediaGoblin</a>, un logiciel d'hébergement de média extraordinairement génial."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr "Pour ajouter vos propres médias, commenter, et bien plus encore, vous pouvez vous connecter avec votre compte MediaGoblin"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr "Vous n'en avez pas ? C'est facile !"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -610,13 +638,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr "Éditer les pièces jointes de %(media_title)s"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
msgstr "Pièces jointes"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
msgstr "Ajouter une pièce jointe"
@@ -633,12 +661,22 @@ msgstr "Annuler"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr "Enregistrer les modifications"
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
@@ -649,7 +687,7 @@ msgid "Yes, really delete my account"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "Supprimer définitivement"
@@ -666,7 +704,11 @@ msgstr "Modification de %(media_title)s"
msgid "Changing %(username)s's account settings"
msgstr "Changement des préférences du compte de %(username)s"
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
msgstr ""
@@ -691,6 +733,7 @@ msgstr "Médias taggés avec : %(tag_name)s "
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -715,6 +758,7 @@ msgid ""
msgstr "Vous pouvez obtenir un navigateur à jour capable de lire cette vidéo sur <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!"
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr "Fichier original"
@@ -723,6 +767,7 @@ msgstr "Fichier original"
msgid "WebM file (Vorbis codec)"
msgstr "fichier WebM (codec Vorbis)"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -733,6 +778,10 @@ msgstr "fichier WebM (codec Vorbis)"
msgid "Image for %(media_title)s"
msgstr "Image de %(media_title)s"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
msgstr ""
@@ -831,7 +880,7 @@ msgstr "Voulez-vous vraiment supprimer %(title)s ?"
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr "Voulez vous vraiment retirer %(media_title)s de %(collection_title)s ?"
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr "Retirer"
@@ -874,24 +923,28 @@ msgstr "Médias de <a href=\"%(user_url)s\">%(username)s</a>"
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr "■Parcourir les médias de <a href=\"%(user_url)s\">%(username)s</a>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
msgstr "Ajouter un commentaire"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
msgstr "Ajouter ce commentaire"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
-msgstr "à"
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
-msgstr "<h3>Ajouté le</h3>\n<p>%(date)s</p>"
+msgid "%(formatted_time)s ago"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
+msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40
@@ -1047,7 +1100,7 @@ msgstr "le plus vieux"
msgid "Tagged with"
msgstr "Taggé avec"
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr "Impossible de lire l'image."
@@ -1077,6 +1130,30 @@ msgid ""
" deleted."
msgstr "Il ne semble pas y avoir de page à cette adresse. Désolé ! </p><p>Si vous êtes sûr que l'adresse est correcte, peut-être que la page que vous recherchez a été déplacée ou supprimée."
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr ""
+
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
msgstr ""
@@ -1108,73 +1185,77 @@ msgstr "-- Sélectionner --"
msgid "Include a note"
msgstr "Inclure une note"
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
msgstr "a commenté votre post"
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr "Oups, votre commentaire était vide."
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr "Votre commentaire a été posté !"
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
msgstr "Veuillez vérifier vos entrées et réessayer."
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr "Vous devez sélectionner ou ajouter une collection"
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr "\"%s\" est déjà dans la collection \"%s\""
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr "\"%s\" as été ajouté à la collection \"%s\""
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr "Vous avez supprimé le media."
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr "Ce media n'a pas été supprimé car vous n'avez pas confirmer que vous étiez sur."
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr "Vous êtes sur le point de supprimer des médias d'un autre utilisateur. Procédez avec prudence."
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr "Vous avez supprimé cet élément de la collection."
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr "L'élément n'as pas été supprimé car vous n'avez pas confirmé votre certitude."
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr "Vous vous apprêtez à supprimer un élément de la collection d'un autre utilisateur. Procédez avec attention."
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr "Vous avez supprimé la collection \"%s\""
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr "La collection n'as pas été supprimée car vous n'avez pas confirmé votre certitude"
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr "Vous vous apprêtez à supprimer la collection d'un autre utilisateur. Procédez avec attention."
diff --git a/mediagoblin/i18n/he/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/he/LC_MESSAGES/mediagoblin.mo
index ce2963f7..09412b0a 100644
--- a/mediagoblin/i18n/he/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/he/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/he/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/he/LC_MESSAGES/mediagoblin.po
index 12d932c8..4a5c2b52 100644
--- a/mediagoblin/i18n/he/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/he/LC_MESSAGES/mediagoblin.po
@@ -3,16 +3,17 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
-# <genghiskhan@gmx.ca>, 2012.
-# Isratine Citizen <genghiskhan@gmx.ca>, 2012.
+# GenghisKhan <genghiskhan@gmx.ca>, 2013
+# GenghisKhan <genghiskhan@gmx.ca>, 2012
+# GenghisKhan <genghiskhan@gmx.ca>, 2012
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-05 00:04+0000\n"
-"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-06-01 07:11+0000\n"
+"Last-Translator: GenghisKhan <genghiskhan@gmx.ca>\n"
+"Language-Team: Hebrew (http://www.transifex.com/projects/p/mediagoblin/language/he/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -20,34 +21,39 @@ msgstr ""
"Language: he\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
+#: mediagoblin/auth/forms.py:26
msgid "Username"
msgstr "×©× ×ž×©×ª×ž×©"
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
msgid "Password"
msgstr "סיסמה"
-#: mediagoblin/auth/forms.py:60
+#: mediagoblin/auth/forms.py:34
msgid "Email address"
msgstr "כתובת דו×״ל"
-#: mediagoblin/auth/forms.py:78
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
+msgstr "×©× ×ž×©×ª×ž×© ×ו דו×״ל"
+
+#: mediagoblin/auth/forms.py:52
msgid "Username or email"
msgstr "×©× ×ž×©×ª×ž×© ×ו דו×״ל"
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr "×©× ×ž×©×ª×ž×© ×ו דו×״ל שגוי."
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr "שדה ×–×” ×œ× ×œ×•×§×— כתובות דו×״ל."
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr "שדה ×–×” מצריך כתובת דו×״ל."
+
#: mediagoblin/auth/views.py:54
msgid "Sorry, registration is disabled on this instance."
msgstr "צר לי, ×¨×™×©×•× ×”×™× ×• מנוטרל על שרת ×–×”."
@@ -60,54 +66,54 @@ msgstr "צר לי, משתמש ×¢× ×©× ×–×” כבר ×§×™×™×."
msgid "Sorry, a user with that email address already exists."
msgstr "צר לי, משתמש ×¢× ×“×•×״ל ×–×” כבר ×§×™×™×."
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr "כתובת הדו×״ל שלך ×ומתה. כעת ב×פשרותך להתחבר, לערוך ×ת דיוקנך, ולשלוח תמונות!"
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr "מפתח ×”×ימות ×ו זהות משתמש ×”×™× × ×©×’×•×™×™×"
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr "עליך להתחבר על מנת שנדע ×ל מי לשלוח ×ת הדו×״ל!"
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr "כבר ×ימתת ×ת כתובת הדו×״ל שלך!"
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr "שלח שוב ×ת דו×״ל ×”×ימות שלך."
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
-msgstr ""
+msgstr "במידה וכתובת הדו×״ל הזו (תלוי רישיות!) רשומה דו×״ל נשלח ×¢× ×”×•×¨×ות בנוגע לכיצד לשנות ×ת סיסמתך."
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
-msgstr ""
+msgstr "×œ× ×”×™×” ניתן ×œ×ž×¦×•× ×ž×™×©×”×• ×¢× ×©× ×ž×©×ª×ž×© ×–×”."
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
msgstr "דו×״ל נשלח בצירוף הור×ות בנוגע לכיצד ניתן לשנות ×ת סיסמתך."
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr "×œ× ×”×™×” ניתן לשלוח דו×״ל לשחזור סיסמה מ×חר ×•×©× ×”×ž×©×ª×ž×© שלך ×ינו פעיל ×ו שכתובת הדו×״ל של חשבונך ×œ× ×ומתה."
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
msgstr "כעת ביכולתך להתחבר ב×מצעות סיסמתך החדשה."
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -118,7 +124,7 @@ msgid "Description of this work"
msgstr "תי×ור של מל××›×” זו"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -134,11 +140,11 @@ msgstr "תגיות"
msgid "Separate tags by commas."
msgstr "הפרד תגיות בעזרת פסיקי×."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "חשופית"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "החשופית ×œ× ×™×›×•×œ×” להיות ריקה"
@@ -166,45 +172,45 @@ msgid "This address contains errors"
msgstr "כתובת זו מכילה שגי×ות"
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr "סיסמה ישנה"
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr "הזן ×ת סיסמתך הישנה כדי להוכיח ש×תה ×”×‘×¢×œ×™× ×©×œ חשבון ×–×”."
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr "סיסמה חדשה"
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
-msgstr ""
+msgstr "עדיפות רשיון"
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
-msgstr ""
+msgstr "×–×” ×™×”×™×” הרשיוןן המשתמט (ברירת מחדל) שלך בטופסי העל××”."
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr "שלח לי דו×״ל ×›×שר ××—×¨×™× ×ž×’×™×‘×™× ×¢×œ המדיה שלי"
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr "הכותרת ×œ× ×™×›×•×œ×” להיות ריקה"
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr "תי×ור ×וסף ×–×”"
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr "×זור הכותרת של כתובת ×וסף ×–×”. לרוב ×ין הכרח לשנות ×ת חלק ×–×”."
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr "סיסמה ישנה"
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr "הזן ×ת סיסמתך הישנה כדי להוכיח ש×תה ×”×‘×¢×œ×™× ×©×œ חשבון ×–×”."
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr "סיסמה חדשה"
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr "רשומה ×¢× ×—×©×•×¤×™×ª זו כבר קיימת עבור משתמש ×–×”."
@@ -219,7 +225,7 @@ msgstr "הוספת ×ת התצריף %s!"
#: mediagoblin/edit/views.py:182
msgid "You can only edit your own profile."
-msgstr ""
+msgstr "ב×פשרותך לערוך רק ×ת הדיוקן שלך."
#: mediagoblin/edit/views.py:188
msgid "You are editing a user's profile. Proceed with caution."
@@ -229,57 +235,80 @@ msgstr "×תה עורך דיוקן של משתמש. המשך בזהירות."
msgid "Profile changes saved"
msgstr "שינויי דיוקן נשמרו"
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr "סיסמה שגויה"
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr "הגדרות חשבון נשמרו"
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
-msgstr ""
+msgstr "עליך ל×מת ×ת המחיקה של חשבונך."
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr "כבר יש לך ×וסף שקרוי ×‘×©× \"%s\"!"
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr "×וסף ×¢× ×—×©×•×¤×™×ª זו כבר ×§×™×™× ×¢×‘×•×¨ משתמש ×–×”."
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr "×תה עורך ×וסף של משתמש ×חר. המשך בזהירות."
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr "סיסמה שגויה"
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr "סיסמתך שונתה בהצלחה"
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr "×œ× × ×™×ª×Ÿ לקשר ×ל מוטיב... ×œ× ×”×•×’×“×¨ מוטיב\n"
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr "×ין מדור נכס עבור מוטיב ×–×”\n"
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr "בכל ×ופן, קישור מדור symlink נמצ×; הוסר.\n"
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr "×œ× ×”×™×ª×” ×פשרות לקשר ×ת \"%s\": %s ×§×™×™× ×•×ינו קישור סמלי (symlink)\n"
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr "מדלג על \"%s\"; כבר מוגדר.\n"
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr "קישור ישן × ×ž×¦× ×¢×‘×•×¨ \"%s\"; מסיר כעת.\n"
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
"or somesuch.<br/>Make sure to permit the settings of cookies for this "
"domain."
-msgstr ""
+msgstr "עוגיית CSRF ×œ× × ×•×›×—×ª. ×–×” קרוב לווד××™ נובע ×ž×©×•× ×—×•×¡× ×¢×•×’×™×™×” ×ו משהו בסגנון.<br/>הבטח קביעה של עוגיות עבור ×ª×—×•× ×–×”."
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr "צר לי, ××™× × ×™ תומך בטיפוס קובץ ×–×” :("
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr "unoconv נכשל לפעול, בדוק קובץ יומן"
+
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr "המרת ויד×ו נכשלה"
@@ -316,7 +345,7 @@ msgstr "תי×ור"
msgid ""
"This will be visible to users allowing your\n"
" application to authenticate as them."
-msgstr ""
+msgstr "×–×” יר××” ×œ×ž×©×ª×ž×©×™× ×©×ž×ª×™×¨×™×\n ×œ×™×™×©×•×ž×™× ×©×œ×š ל×מת ×ות×."
#: mediagoblin/plugins/oauth/forms.py:40
msgid "Type"
@@ -346,17 +375,17 @@ msgstr ""
msgid "This field is required for public clients"
msgstr "שדה ×–×” הינו דרוש עבור לקוחות פומביי×"
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
msgstr "הלקוח {0} נרש×!"
#: mediagoblin/plugins/oauth/templates/oauth/client/connections.html:22
msgid "OAuth client connections"
-msgstr ""
+msgstr "חיבורי לקוח OAuth"
#: mediagoblin/plugins/oauth/templates/oauth/client/list.html:22
msgid "Your OAuth clients"
-msgstr ""
+msgstr "לקוחות OAuth שלך"
#: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
@@ -365,7 +394,7 @@ msgstr ""
msgid "Add"
msgstr "הוסף"
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr "ניתן קובץ שגוי עבור טיפוס מדיה."
@@ -373,45 +402,45 @@ msgstr "ניתן קובץ שגוי עבור טיפוס מדיה."
msgid "File"
msgstr "קובץ"
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr "עליך לספק קובץ."
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr "הידד! נשלח!"
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr "×וסף \"%s\" התווסף!"
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr "×מת ×ת הדו×״ל שלך!"
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
msgstr "התנתקות"
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr "התחברות"
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr "החשבון של <a href=\"%(user_url)s\">%(user_name)s</a>"
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr "שנה הגדרות חשבון"
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -419,72 +448,25 @@ msgstr "שנה הגדרות חשבון"
msgid "Media processing panel"
msgstr "לוח עיבוד מדיה"
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
-msgstr ""
+msgstr "התנתקות"
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr "הוספת מדיה"
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
msgstr "צור ×וסף חדש"
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr "משוחרר תחת הרשיון <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">קוד מקור</a> זמין."
-
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
msgstr "תמונה של גובלין מת×מץ יתר על המידה"
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr "לחקור"
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr "×©×œ×•× ×œ×š, ברוך בו×ך ×ל ×תר MediaGoblin ×–×”!"
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr "×תר ×–×” מריץ <a href=\"http://mediagoblin.org\">MediaGoblin</a>, חתיכת תוכנת ×ירוח מדיה יוצ×ת מן הכלל."
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr "בכדי להוסיף ×ת המדיה שלך, ×œ×”×©×™× ×ª×’×•×‘×•×ª, ועוד, ביכולתך להתחבר ×¢× ×—×©×‘×•×Ÿ MediaGoblin."
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr "×ין ברשותך חשבון עדיין? ×–×” קל!"
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">יצירת חשבון ×צל ×תר ×–×”</a>\n ×ו\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">להתקין ×ת MediaGoblin על שרתך</a>"
-
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr "המדיה ×”×חרונה ביותר"
@@ -573,11 +555,11 @@ msgstr "שכחת ×ת סיסמתך?"
#: mediagoblin/templates/mediagoblin/auth/register.html:28
#: mediagoblin/templates/mediagoblin/auth/register.html:36
msgid "Create an account!"
-msgstr "יצירת חשבון!"
+msgstr "צור חשבון!"
#: mediagoblin/templates/mediagoblin/auth/register.html:40
msgid "Create"
-msgstr "יצירה"
+msgstr "צור"
#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19
#, python-format
@@ -590,6 +572,53 @@ msgid ""
"%(verification_url)s"
msgstr "×©×œ×•× %(username)s,\n\nבכדי להפעיל ×ת חשבונך ×צל GNU MediaGoblin, עליך לפתוח ×ת הכתובת הב××”\nבתוך דפדפן הרשת שלך:\n\n%(verification_url)s"
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr "ממונע על ידי <a href=\"http://mediagoblin.org/\" title='גירסה %(version)s'>MediaGoblin</a>, פרויקט <a href=\"http://gnu.org/\">GNU</a>."
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr "משוחרר תחת הרשיון <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">קוד מקור</a> זמין."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr "לחקור"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "×©×œ×•× ×œ×š, ברוך בו×ך ×ל ×תר MediaGoblin ×–×”!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr "×תר ×–×” מריץ <a href=\"http://mediagoblin.org\">MediaGoblin</a>, חתיכת תוכנת ×ירוח מדיה יוצ×ת מן הכלל."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr "בכדי להוסיף ×ת המדיה שלך, ×œ×”×©×™× ×ª×’×•×‘×•×ª, ועוד, ביכולתך להתחבר ×¢× ×—×©×‘×•×Ÿ MediaGoblin."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr "×ין ברשותך חשבון עדיין? ×–×” קל!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">צור חשבון ב×תר ×–×”</a>\n ×ו\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">התקן ×ת MediaGoblin על שרתך</a>"
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -602,13 +631,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr "עריכת ×ª×¦×¨×™×¤×™× ×¢×‘×•×¨ %(media_title)s"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
msgstr "תצריפי×"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
msgstr "הוספת תצריף"
@@ -625,23 +654,33 @@ msgstr "ביטול"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr "שמור שינויי×"
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr "משנה כעת ×ת הסיסמה של %(username)s'"
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr "שמור"
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
-msgstr ""
+msgstr "ב×מת למחוק ×ת המשתמש '%(user_name)s' ו×ת כל המדיה/התגובות הקשורות?"
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:35
msgid "Yes, really delete my account"
-msgstr ""
+msgstr "כן, ב×מת למחוק ×ת חשבוני"
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "מחק לצמיתות"
@@ -658,9 +697,13 @@ msgstr "ערוך %(media_title)s"
msgid "Changing %(username)s's account settings"
msgstr "שינוי הגדרות חשבון עבור %(username)s"
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr "שנה ×ת סיסמתך."
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
-msgstr ""
+msgstr "מחק ×ת החשבון שלי"
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29
#, python-format
@@ -683,6 +726,7 @@ msgstr "מדיה מתויגת ×¢×: %(tag_name)s"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -704,9 +748,10 @@ msgid ""
"You can get a modern web browser that \n"
"\tcan play the audio at <a href=\"http://getfirefox.com\">\n"
"\t http://getfirefox.com</a>!"
-msgstr "ביכולתך להשיג דפדפן רשת מודרני שכן \n\tמסוגל לנגן ×ת ×ודיו ×–×” ×צל <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!"
+msgstr "ביכולתך להשיג דפדפן רשת מודרני \n\tשכן מסוגל לנגן ×ת ×ודיו ×–×” ×צל <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!"
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr "קובץ מקורי"
@@ -715,6 +760,7 @@ msgstr "קובץ מקורי"
msgid "WebM file (Vorbis codec)"
msgstr "קובץ WebM (קודק Vorbis)"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -725,9 +771,13 @@ msgstr "קובץ WebM (קודק Vorbis)"
msgid "Image for %(media_title)s"
msgstr "תמונה עבור %(media_title)s"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr "קובץ PDF"
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
-msgstr ""
+msgstr "החלף סיבוב"
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113
msgid "Perspective"
@@ -755,7 +805,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138
msgid "Download model"
-msgstr ""
+msgstr "הורד מודל"
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146
msgid "File Format"
@@ -770,14 +820,14 @@ msgid ""
"Sorry, this video will not work because\n"
" your web browser does not support HTML5 \n"
" video."
-msgstr ""
+msgstr "צר לי, ויד×ו ×–×” ×œ× ×™×¢×‘×•×“ מכיוון \n שדפדפן הרשת שלך ×œ× ×ª×•×ž×š \n ויד×ו של HTML5."
#: mediagoblin/templates/mediagoblin/media_displays/video.html:47
msgid ""
"You can get a modern web browser that \n"
" can play this video at <a href=\"http://getfirefox.com\">\n"
" http://getfirefox.com</a>!"
-msgstr ""
+msgstr "ביכולתך להשיג דפדפן רשת מודרני \n שכן מסוגל לנגן ×ת ויד×ו ×–×” ×צל <a href=\"http://getfirefox.com\">\n http://getfirefox.com</a>!"
#: mediagoblin/templates/mediagoblin/media_displays/video.html:69
msgid "WebM file (640p; VP8/Vorbis)"
@@ -823,19 +873,19 @@ msgstr "ב×מת למחוק ×ת %(title)s?"
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr "ב×מת להסיר ×ת %(media_title)s מן %(collection_title)s?"
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr "הסר"
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:21
#, python-format
msgid "%(username)s's collections"
-msgstr ""
+msgstr "××•×¡×¤×™× ×©×œ %(username)s"
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:28
#, python-format
msgid "<a href=\"%(user_url)s\">%(username)s</a>'s collections"
-msgstr ""
+msgstr "××•×¡×¤×™× ×©×œ <a href=\"%(user_url)s\">%(username)s</a>"
#: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19
#, python-format
@@ -854,7 +904,7 @@ msgstr "המדיה של %(username)s"
msgid ""
"<a href=\"%(user_url)s\">%(username)s</a>'s media with tag <a "
"href=\"%(tag_url)s\">%(tag)s</a>"
-msgstr ""
+msgstr "מדיה משתמש <a href=\"%(user_url)s\">%(username)s</a> ×¢× ×ª×’×™×ª <a href=\"%(tag_url)s\">%(tag)s</a>"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48
#, python-format
@@ -866,30 +916,34 @@ msgstr "המדיה של <a href=\"%(user_url)s\">%(username)s</a>"
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr "■עיון במדיה מ×ת <a href=\"%(user_url)s\">%(username)s</a>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
msgstr "הוסף תגובה"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
msgstr "הוסף ×ת תגובה זו"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
-msgstr "×צל"
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
-msgstr "<h3>הוסף בת×ריך</h3>\n <p>%(date)s</p>"
+msgid "%(formatted_time)s ago"
+msgstr "מלפני %(formatted_time)s"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr "התווסף"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
+msgstr "נוצר"
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40
#, python-format
msgid "Add “%(media_title)s†to a collection"
-msgstr ""
+msgstr "הוסף ×ת “%(media_title)s†×ל ×וסף"
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:54
msgid "+"
@@ -968,7 +1022,7 @@ msgstr "משתמש ×–×” ×œ× ×ž×™×œ× ×“×™×•×§×Ÿ (עדיין)."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:124
msgid "Browse collections"
-msgstr ""
+msgstr "עיון ב×וספי×"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:137
#, python-format
@@ -997,7 +1051,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/utils/collections.html:40
msgid "Add to a collection"
-msgstr ""
+msgstr "הוסף ×ל ×וסף"
#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
#: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:21
@@ -1039,7 +1093,7 @@ msgstr "ישן יותר"
msgid "Tagged with"
msgstr "מתויגת ×¢×"
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr "×œ× ×”×™×” ניתן ×œ×§×¨×•× ×ת קובץ התמונה."
@@ -1069,9 +1123,33 @@ msgid ""
" deleted."
msgstr "×œ× × ×¨××” ×©×§×™×™× ×¢×ž×•×“ בכתובת זו. צר לי!</p><p>×× ×תה בטוח שהכתובת ×”×™× ×” מדויקת, ייתכן שהעמוד ש×תה מחפש כעת הועבר ×ו נמחק."
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr "שנה"
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr "חודש"
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr "שבוע"
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr "יו×"
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr "שעה"
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr "דקה"
+
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
-msgstr ""
+msgstr "תגובה"
#: mediagoblin/user_pages/forms.py:25
msgid ""
@@ -1090,7 +1168,7 @@ msgstr "×× ×™ בטוח שברצוני להסיר ×ת פריט ×–×” מן ×”×ו
#: mediagoblin/user_pages/forms.py:39
msgid "Collection"
-msgstr ""
+msgstr "×וסף"
#: mediagoblin/user_pages/forms.py:40
msgid "-- Select --"
@@ -1100,73 +1178,77 @@ msgstr "-- בחר --"
msgid "Include a note"
msgstr "הכללת פתק"
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
msgstr "הגיב/ה על פרסומך"
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr "מצטערי×, תגובות מנוטרלות."
+
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr "×ופס, תגובתך היתה ריקה."
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr "תגובתך פורסמה!"
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
msgstr "×× × ×‘×“×•×§ ×ת רשומותיך ונסה שוב."
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr "עליך לבחור ×ו להוסיף ×וסף"
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr "\"%s\" כבר ×§×™×™× ×‘×וסף \"%s\""
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr "\"%s\" התווסף ×ל ×”×וסף \"%s\""
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr "מחקת ×ת מדיה זו."
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr "המדיה ×œ× × ×ž×—×§×” מכיוון ×©×œ× ×¡×™×ž× ×ª ש×תה בטוח."
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr "בחרת למחוק מדיה של משתמש ×חר. המשך בזהירות."
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr "מחקת ×ת הפריט מן ×וסף ×–×”."
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr "הפריט ×œ× ×”×•×¡×¨ מכיוון ×©×œ× ×¡×™×ž× ×ª ש×תה בטוח."
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr "בחרת למחוק פריט מן ×וסף של משתמש ×חר. המשך בזהירות."
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr "מחקת ×ת ×”×וסף \"%s\""
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr "×”×וסף ×œ× ×”×•×¡×¨ מכיוון ×©×œ× ×¡×™×ž× ×ª ש×תה בטוח."
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr "בחרת למחוק ×וסף של משתמש ×חר. המשך בזהירות."
diff --git a/mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.mo
index d9addaa6..d22f6ee6 100644
--- a/mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.po
index 73180e86..c9f814fc 100644
--- a/mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.po
@@ -3,16 +3,16 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
-# Aleksandr Brezhnev <abrezhnev@gmail.com>, 2012.
-# Emilio Sepúlveda <djfunkinmixer@gmail.com>, 2011.
+# Aleksandr Brezhnev <abrezhnev@gmail.com>, 2012
+# Emilio Sepúlveda <emisepulvedam@gmail.com>, 2011
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-05 00:04+0000\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-05-27 18:54+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language-Team: Interlingua (http://www.transifex.com/projects/p/mediagoblin/language/ia/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -20,34 +20,39 @@ msgstr ""
"Language: ia\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
+#: mediagoblin/auth/forms.py:26
msgid "Username"
msgstr "Nomine de usator"
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
msgid "Password"
msgstr "Contrasigno"
-#: mediagoblin/auth/forms.py:60
+#: mediagoblin/auth/forms.py:34
msgid "Email address"
msgstr "Adresse de e-posta"
-#: mediagoblin/auth/forms.py:78
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
+msgstr ""
+
+#: mediagoblin/auth/forms.py:52
msgid "Username or email"
msgstr ""
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr ""
+
#: mediagoblin/auth/views.py:54
msgid "Sorry, registration is disabled on this instance."
msgstr ""
@@ -60,54 +65,54 @@ msgstr ""
msgid "Sorry, a user with that email address already exists."
msgstr ""
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr ""
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr ""
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr ""
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr ""
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr ""
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
msgstr ""
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
msgstr ""
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
msgstr ""
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr ""
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
msgstr ""
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -118,7 +123,7 @@ msgid "Description of this work"
msgstr ""
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -134,11 +139,11 @@ msgstr "Etiquettas"
msgid "Separate tags by commas."
msgstr ""
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr ""
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr ""
@@ -166,45 +171,45 @@ msgid "This address contains errors"
msgstr ""
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr ""
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr ""
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr ""
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
msgstr ""
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
msgstr ""
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr ""
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr ""
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr ""
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr ""
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr ""
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr ""
@@ -229,44 +234,63 @@ msgstr ""
msgid "Profile changes saved"
msgstr ""
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr ""
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr ""
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
msgstr ""
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr ""
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr ""
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr ""
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr ""
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
@@ -274,12 +298,16 @@ msgid ""
"domain."
msgstr ""
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr ""
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr ""
+
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr ""
@@ -346,7 +374,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
msgstr ""
@@ -365,7 +393,7 @@ msgstr ""
msgid "Add"
msgstr ""
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr ""
@@ -373,45 +401,45 @@ msgstr ""
msgid "File"
msgstr "File"
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr ""
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr ""
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr "Initiar session"
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -419,72 +447,25 @@ msgstr ""
msgid "Media processing panel"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr ""
@@ -590,6 +571,53 @@ msgid ""
"%(verification_url)s"
msgstr ""
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -602,13 +630,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
msgstr ""
@@ -625,12 +653,22 @@ msgstr "Cancellar"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr ""
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
@@ -641,7 +679,7 @@ msgid "Yes, really delete my account"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr ""
@@ -658,7 +696,11 @@ msgstr ""
msgid "Changing %(username)s's account settings"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
msgstr ""
@@ -683,6 +725,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -707,6 +750,7 @@ msgid ""
msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr ""
@@ -715,6 +759,7 @@ msgstr ""
msgid "WebM file (Vorbis codec)"
msgstr ""
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -725,6 +770,10 @@ msgstr ""
msgid "Image for %(media_title)s"
msgstr ""
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
msgstr ""
@@ -823,7 +872,7 @@ msgstr ""
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr ""
@@ -866,23 +915,27 @@ msgstr ""
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
+#, python-format
+msgid "%(formatted_time)s ago"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
-#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
@@ -1039,7 +1092,7 @@ msgstr ""
msgid "Tagged with"
msgstr ""
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr ""
@@ -1069,6 +1122,30 @@ msgid ""
" deleted."
msgstr ""
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr ""
+
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
msgstr ""
@@ -1100,73 +1177,77 @@ msgstr ""
msgid "Include a note"
msgstr ""
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
msgstr ""
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr ""
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr ""
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr ""
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr ""
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr ""
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr ""
diff --git a/mediagoblin/i18n/is_IS/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/is_IS/LC_MESSAGES/mediagoblin.mo
index 376aace4..596ab843 100644
--- a/mediagoblin/i18n/is_IS/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/is_IS/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/is_IS/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/is_IS/LC_MESSAGES/mediagoblin.po
index 1b298a64..77896b87 100644
--- a/mediagoblin/i18n/is_IS/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/is_IS/LC_MESSAGES/mediagoblin.po
@@ -3,15 +3,16 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
-# <tryggvib@fsfi.is>, 2012.
+# tryggvib <tryggvib@fsfi.is>, 2012
+# tryggvib <tryggvib@fsfi.is>, 2013
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-05 00:04+0000\n"
-"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-06-05 22:51+0000\n"
+"Last-Translator: tryggvib <tryggvib@fsfi.is>\n"
+"Language-Team: Icelandic (Iceland) (http://www.transifex.com/projects/p/mediagoblin/language/is_IS/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -19,34 +20,39 @@ msgstr ""
"Language: is_IS\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
+#: mediagoblin/auth/forms.py:26
msgid "Username"
msgstr "Notandanafn"
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
msgid "Password"
msgstr "Lykilorð"
-#: mediagoblin/auth/forms.py:60
+#: mediagoblin/auth/forms.py:34
msgid "Email address"
msgstr "Netfang"
-#: mediagoblin/auth/forms.py:78
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
+msgstr "Notandanafn eða tölvupóstur"
+
+#: mediagoblin/auth/forms.py:52
msgid "Username or email"
msgstr "Notandanafn eða netfang"
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr "Ógilt notandanafn eða netfang"
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr "Þessi reitur tekur ekki við netföngum."
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr "í þennan reit verður að slá inn netfang."
+
#: mediagoblin/auth/views.py:54
msgid "Sorry, registration is disabled on this instance."
msgstr "Því miður er nýskráning ekki leyfð á þessu svæði."
@@ -59,54 +65,54 @@ msgstr "Því miður er nú þegar til notandi með þetta nafn."
msgid "Sorry, a user with that email address already exists."
msgstr "Því miður þá er annar notandi í kerfinu með þetta netfang skráð."
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr "Netfangið þitt hefur verið staðfest. Þú getur núna innskráð þig, breytt kenniskránni þinni og sent inn efni!"
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr "Staðfestingarlykillinn eða notendaauðkennið er rangt"
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr "Þú verður að hafa innskráð þig svo við vitum hvert á að senda tölvupóstinn!"
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr "Þú hefur staðfest netfangið þitt!"
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr "Endursendi staðfestingartölvupóst"
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
-msgstr ""
+msgstr "Ef þetta netfang (há- og lágstafir skipta máli) er skráð hjá okkur hefur tölvupóstur verið sendur með leiðbeiningum um hvernig þú getur breytt lykilorðinu þínu."
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
-msgstr ""
+msgstr "Gat ekki fundið neinn með þetta notandanafn."
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
msgstr "Tölvupóstur hefur verið sendur með leiðbeiningum um hvernig þú átt að breyta lykilorðinu þínu."
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr "Gat ekki sent tölvupóst um endurstillingu lykilorðs því notandanafnið þitt er óvirkt eða þá að þú hefur ekki staðfest netfangið þitt."
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
msgstr "Þú getur núna innskráð þig með nýja lykilorðinu þínu."
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -117,7 +123,7 @@ msgid "Description of this work"
msgstr "Lýsing á þessu efni"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -133,11 +139,11 @@ msgstr "Efnisorð"
msgid "Separate tags by commas."
msgstr "Aðskildu efnisorðin með kommum."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "Vefslóðarormur"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "Vefslóðarormurinn getur ekki verið tómur"
@@ -165,45 +171,45 @@ msgid "This address contains errors"
msgstr "Þetta netfang inniheldur villur"
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr "Gamla lykilorðið"
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr "Skráðu gamla lykilorðið þitt til að sanna að þú átt þennan aðgang."
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr "Nýtt lykilorð"
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
-msgstr ""
+msgstr "Leyfiskjörstilling"
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
-msgstr ""
+msgstr "Þetta verður sjálfgefna leyfið þegar þú vilt hlaða upp efni."
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr "Senda mér tölvupóst þegar einhver bætir athugasemd við efnið mitt"
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr "Þessi titill getur verið innihaldslaus"
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr "Lýsing á þessu albúmi"
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr "Titilhlutinn í vefslóð þessa albúms. Þú þarft vanalega ekki að breyta þessu."
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr "Gamla lykilorðið"
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr "Skráðu gamla lykilorðið þitt til að sanna að þú átt þennan aðgang."
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr "Nýtt lykilorð"
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr "Efni merkt með þessum vefslóðarormi er nú þegar til fyrir þennan notanda."
@@ -218,7 +224,7 @@ msgstr "Þú bættir við viðhenginu %s!"
#: mediagoblin/edit/views.py:182
msgid "You can only edit your own profile."
-msgstr ""
+msgstr "Þú getur bara breytt þinni eigin kenniskrá."
#: mediagoblin/edit/views.py:188
msgid "You are editing a user's profile. Proceed with caution."
@@ -228,57 +234,80 @@ msgstr "Þú ert að breyta kenniskrá notanda. Farðu mjög varlega."
msgid "Profile changes saved"
msgstr "Breytingar á kenniskrá vistaðar"
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr "Vitlaust lykilorð"
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr "Aðgangsstillingar vistaðar"
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
-msgstr ""
+msgstr "Þú verður að samþykkja eyðingu á notandaaðganginum þínum."
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr "Þú hefur nú þegar albúm sem kallast \"%s\"!"
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr "Albúm með þessu vefslóðarormi er nú þegar til fyrir þennan notanda."
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr "Þú ert að breyta albúmi annars notanda. Farðu mjög varlega."
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr "Vitlaust lykilorð"
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr "Það tókst að breyta lykilorðinu þínu"
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr "Get ekki hlekkjað í þema... ekkert þema stillt\n"
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr "Engin eignamappa fyrir þetta þema\n"
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr "Fann samt gamlan táknrænan tengil á möppu; fjarlægður.\n"
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr "Gat ekki tengt \"%s\": %s er til og er ekki sýndartengill\n"
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr "Hoppa yfir \"%s\"; hefur nú þegar verið sett upp.\n"
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr "Gamall tengill fannst fyrir \"%s\"; fjarlægi.\n"
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
"or somesuch.<br/>Make sure to permit the settings of cookies for this "
"domain."
-msgstr ""
+msgstr "CSRF smygildi ekki til staðar. Þetta er líklegast orsakað af smygildishindrara eða einhverju þess háttar.<br/>Athugaðu hvort þú leyfir ekki alveg örugglega smygildi fyrir þetta lén."
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr "Ég styð því miður ekki þessa gerð af skrám :("
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr "tekst ekki að keyra unoconv, athugaðu annálsskrá"
+
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr "Myndbandsþverkótun mistókst"
@@ -345,17 +374,17 @@ msgstr "Ãframsendingarvefslóðin fyrir forritin, þessi reitur\n er
msgid "This field is required for public clients"
msgstr "Þessi reitur er nauðsynlegur fyrir opinbera biðlara"
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
msgstr "Biðlarinn {0} hefur verið skráður!"
#: mediagoblin/plugins/oauth/templates/oauth/client/connections.html:22
msgid "OAuth client connections"
-msgstr ""
+msgstr "Biðlarartengingar OAuth"
#: mediagoblin/plugins/oauth/templates/oauth/client/list.html:22
msgid "Your OAuth clients"
-msgstr ""
+msgstr "OAuth-biðlararnir þínir"
#: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
@@ -364,7 +393,7 @@ msgstr ""
msgid "Add"
msgstr "Bæta við"
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr "Ógild skrá gefin fyrir þessa margmiðlunartegund."
@@ -372,45 +401,45 @@ msgstr "Ógild skrá gefin fyrir þessa margmiðlunartegund."
msgid "File"
msgstr "Skrá"
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr "Þú verður að gefa upp skrá."
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr "Jibbí jei! Það tókst að senda inn!"
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr "Albúmið \"%s\" var búið til!"
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr "Staðfestu netfangið þitt!"
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
msgstr "útskrá"
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
-msgstr "Innskráning"
+msgstr "Innskrá"
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
-msgstr "Notandaaðgangur <a href=\"%(user_url)s\">%(user_name)s</a>"
+msgstr "Notandaaðgangur: <a href=\"%(user_url)s\">%(user_name)s</a>"
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr "Breyta stillingum notandaaðgangs"
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -418,72 +447,25 @@ msgstr "Breyta stillingum notandaaðgangs"
msgid "Media processing panel"
msgstr "Margmiðlunarvinnsluskiki"
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
-msgstr ""
+msgstr "Skrá út"
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr "Senda inn efni"
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
msgstr "Búa til nýtt albúm"
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr "Gefið út undir <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Frumkóti</a> aðgengilegur."
-
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
msgstr "Mynd af durt í stresskasti"
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr "Skoða"
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr "Hæ! Gakktu í bæinn á þetta MediaGoblin vefsvæði!"
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr "Þetta vefsvæði keyrira á <a href=\"http://mediagoblin.org\">MediaGoblin</a> sem er ótrúlega frábær hugbúnaður til að geyma margmiðlunarefni."
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr "Til að senda inn þitt efni, gera athugasemdir og fleira getur þú skráð þig inn með þínum MediaGoblin aðgangi."
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr "Ertu ekki með aðgang? Það er auðvelt að búa til!"
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">Búa til aðgang á þessari síðu</a>\n eða\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Settu upp þinn eigin margmiðlunarþjón</a>"
-
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr "Nýlegt efni"
@@ -589,6 +571,53 @@ msgid ""
"%(verification_url)s"
msgstr "Hæ %(username)s,\n\ntil að virkja GNU MediaGoblin aðganginn þinn, opnaðu þá eftirfarandi vefslóði í\nvafranum þínum:\n\n%(verification_url)s"
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr "Keyrt af <a href=\"http://mediagoblin.org/\" title='Version %(version)s'>MediaGoblin</a>, sem er <a href=\"http://gnu.org/\">GNU</a> verkefni."
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr "Gefið út undir <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Frumkóti</a> aðgengilegur."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr "Skoða"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "Hæ! Gakktu í bæinn á þetta MediaGoblin vefsvæði!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr "Þetta vefsvæði keyrir á <a href=\"http://mediagoblin.org\">MediaGoblin</a> sem er ótrúlega frábær hugbúnaður til að geyma margmiðlunarefni."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr "Til að senda inn þitt efni, gera athugasemdir og fleira getur þú skráð þig inn með þínum MediaGoblin aðgangi."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr "Ertu ekki með aðgang? Það er auðvelt að búa til!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">Búa til aðgang á þessari síðu</a>\neða\n<a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Settu upp þinn eigin margmiðlunarþjón</a>"
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -601,13 +630,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr "Breyti viðhengjum við: %(media_title)s"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
msgstr "Viðhengi"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
msgstr "Bæta við viðhengi"
@@ -624,23 +653,33 @@ msgstr "Hætta við"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr "Vista breytingar"
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr "Breyti lykilorði fyrir notandann: %(username)s"
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr "Vista"
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
-msgstr ""
+msgstr "Virkilega eyða notanda '%(user_name)s' og tengt efni/athugasemdir?"
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:35
msgid "Yes, really delete my account"
-msgstr ""
+msgstr "Já, ég vil örugglega eyða aðganginum mínum"
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "Eytt algjörlega"
@@ -657,9 +696,13 @@ msgstr "Breyti %(media_title)s"
msgid "Changing %(username)s's account settings"
msgstr "Breyti notandaaðgangsstillingum fyrir: %(username)s"
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr "Breyta lykilorðinu þínu."
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
-msgstr ""
+msgstr "Eyða aðganginum mínum"
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29
#, python-format
@@ -682,6 +725,7 @@ msgstr "Efni merkt með: %(tag_name)s"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -706,6 +750,7 @@ msgid ""
msgstr "Þú getur náð í nýlegan vafra sem \n\tgetur spilað hljóðskrár á <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!"
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr "Upphaflega skráin"
@@ -714,6 +759,7 @@ msgstr "Upphaflega skráin"
msgid "WebM file (Vorbis codec)"
msgstr "WebM skrá (Vorbis víxlþjöppun)"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -724,6 +770,10 @@ msgstr "WebM skrá (Vorbis víxlþjöppun)"
msgid "Image for %(media_title)s"
msgstr "Mynd fyrir %(media_title)s"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr "PDF skrá"
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
msgstr "Stilla snúning af eða á"
@@ -769,14 +819,14 @@ msgid ""
"Sorry, this video will not work because\n"
" your web browser does not support HTML5 \n"
" video."
-msgstr ""
+msgstr "Því miður mun þetta myndband ekki virka því\n vafrinn þinn styður ekki HTML5 \n myndbönd."
#: mediagoblin/templates/mediagoblin/media_displays/video.html:47
msgid ""
"You can get a modern web browser that \n"
" can play this video at <a href=\"http://getfirefox.com\">\n"
" http://getfirefox.com</a>!"
-msgstr ""
+msgstr "Þú getur náð í nýlegan vafra sem \n sem getur spilað myndbandið á <a href=\"http://getfirefox.com\">\n http://getfirefox.com</a>!"
#: mediagoblin/templates/mediagoblin/media_displays/video.html:69
msgid "WebM file (640p; VP8/Vorbis)"
@@ -822,19 +872,19 @@ msgstr "Virkilega eyða %(title)s?"
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr "Virkilega fjarlægja %(media_title)s úr %(collection_title)s albúminu?"
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr "Fjarlægja"
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:21
#, python-format
msgid "%(username)s's collections"
-msgstr ""
+msgstr "Albúm sem %(username)s á"
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:28
#, python-format
msgid "<a href=\"%(user_url)s\">%(username)s</a>'s collections"
-msgstr ""
+msgstr "Albúm sem <a href=\"%(user_url)s\">%(username)s</a> á"
#: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19
#, python-format
@@ -853,7 +903,7 @@ msgstr "Efni sem %(username)s á"
msgid ""
"<a href=\"%(user_url)s\">%(username)s</a>'s media with tag <a "
"href=\"%(tag_url)s\">%(tag)s</a>"
-msgstr ""
+msgstr "Efni sem <a href=\"%(user_url)s\">%(username)s</a> á og er merkt með <a href=\"%(tag_url)s\">%(tag)s</a>"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48
#, python-format
@@ -865,30 +915,34 @@ msgstr "Efni sem <a href=\"%(user_url)s\">%(username)s</a> á"
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr "■Skoða efnið sem <a href=\"%(user_url)s\">%(username)s</a> setti inn"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
msgstr "Bæta við athugasemd"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
msgstr "Senda inn þessa athugasemd"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
-msgstr "hjá"
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
-msgstr "<h3>Bætt við:</h3>\n <p>%(date)s</p>"
+msgid "%(formatted_time)s ago"
+msgstr "Fyrir %(formatted_time)s"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr "Bætt við"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
+msgstr "Skapað"
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40
#, python-format
msgid "Add “%(media_title)s†to a collection"
-msgstr ""
+msgstr "Setja '%(media_title)s' í albúm"
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:54
msgid "+"
@@ -967,7 +1021,7 @@ msgstr "Þessi notandi hefur ekki fyllt inn í upplýsingar um sig (ennþá)."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:124
msgid "Browse collections"
-msgstr ""
+msgstr "Skoða albúm"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:137
#, python-format
@@ -992,11 +1046,11 @@ msgstr "(fjarlægja)"
#: mediagoblin/templates/mediagoblin/utils/collections.html:21
msgid "Collected in"
-msgstr ""
+msgstr "Sett í albúm"
#: mediagoblin/templates/mediagoblin/utils/collections.html:40
msgid "Add to a collection"
-msgstr ""
+msgstr "Setja í albúm"
#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
#: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:21
@@ -1038,7 +1092,7 @@ msgstr "eldri"
msgid "Tagged with"
msgstr "Merkt með"
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr "Gat ekki lesið myndskrána."
@@ -1068,9 +1122,33 @@ msgid ""
" deleted."
msgstr "Því miður! Það virðist ekki vera nein síða á þessari vefslóð.</p><p>Ef þú ert viss um að vefslóðin sé rétt hefur vefsíðan sem þú ert að leita að kannski verið flutt eða fjarlægð."
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr "ár"
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr "mánuður"
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr "vika"
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr "dagur"
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr "klukkustund"
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr "mínúta"
+
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
-msgstr ""
+msgstr "Athugasemd"
#: mediagoblin/user_pages/forms.py:25
msgid ""
@@ -1089,7 +1167,7 @@ msgstr "Ég er viss um að ég vilji fjarlægja þetta efni úr albúminu"
#: mediagoblin/user_pages/forms.py:39
msgid "Collection"
-msgstr ""
+msgstr "Albúm"
#: mediagoblin/user_pages/forms.py:40
msgid "-- Select --"
@@ -1099,73 +1177,77 @@ msgstr "-- Velja --"
msgid "Include a note"
msgstr "Bæta við minnispunktum"
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
msgstr "skrifaði athugasemd við færsluna þína"
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr "Því miður, athugasemdir eru óvirkar."
+
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr "Obbosí! Athugasemdin þín var innihaldslaus."
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr "Athugasemdin þín var skráð!"
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
msgstr "Vinsamlegast kíktu á innsendingarnar þínar og reyndu aftur."
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr "Þú verður að velja eða búa til albúm"
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr "\"%s\" er nú þegar í albúminu \"%s\""
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr "\"%s\" sett í albúmið \"%s\""
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr "Þú eyddir þessu efni."
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr "Efninu var ekki eytt þar sem þú merktir ekki við að þú værir viss."
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr "Þú ert í þann mund að fara að eyða efni frá öðrum notanda. Farðu mjög varlega."
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr "Þú tókst þetta efni úr albúminu."
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr "Þetta efni var ekki fjarlægt af því að þú merktir ekki við að þú værir viss."
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr "Þú ert í þann mund að fara að eyða efni úr albúmi annars notanda. Farðu mjög varlega."
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr "Þú eyddir albúminu \"%s\""
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr "Þessu albúmi var ekki eytt vegna þess að þu merktir ekki við að þú værir viss."
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr "Þú ert í þann mund að fara að eyða albúmi annars notanda. Farðu mjög varlega."
diff --git a/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.mo
index 62451511..62575b62 100644
--- a/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.po
index e13345a7..c782fc62 100644
--- a/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.po
@@ -3,18 +3,19 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
-# Francesco Apruzzese <cescoap@gmail.com>, 2012.
-# <pikappa469@alice.it>, 2011.
-# <robi@nunnisoft.ch>, 2011.
-# <sun_lion@live.com>, 2012.
+# Francesco Apruzzese <cescoap@gmail.com>, 2012
+# gdb <gaedeb01@gmail.com>, 2013
+# pikappa469 <pikappa469@alice.it>, 2011
+# nunni <robi@nunnisoft.ch>, 2011
+# Damtux <sun_lion@live.com>, 2012
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-05 00:04+0000\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-05-27 18:54+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language-Team: Italian (http://www.transifex.com/projects/p/mediagoblin/language/it/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -22,34 +23,39 @@ msgstr ""
"Language: it\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
+#: mediagoblin/auth/forms.py:26
msgid "Username"
msgstr "Nome utente"
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
msgid "Password"
msgstr "Password"
-#: mediagoblin/auth/forms.py:60
+#: mediagoblin/auth/forms.py:34
msgid "Email address"
msgstr "Indirizzo email"
-#: mediagoblin/auth/forms.py:78
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
+msgstr ""
+
+#: mediagoblin/auth/forms.py:52
msgid "Username or email"
msgstr "Nome utente o indirizzo email"
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr ""
+
#: mediagoblin/auth/views.py:54
msgid "Sorry, registration is disabled on this instance."
msgstr "Spiacente, la registrazione è disabilitata su questa istanza."
@@ -62,54 +68,54 @@ msgstr "Spiacente, esiste già un utente con quel nome."
msgid "Sorry, a user with that email address already exists."
msgstr "Siamo spiacenti, un utente con quell'indirizzo email esiste già."
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr "Il tuo indirizzo email è stato verificato. Ora puoi accedere, modificare il tuo profilo e caricare immagini!"
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr "La chiave di verifica o l'id utente è sbagliato"
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr "Devi effettuare l'accesso così possiamo sapere a chi inviare l'email!"
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr "Hai già verificato il tuo indirizzo email!"
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr "Rispedisci email di verifica"
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
msgstr ""
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
msgstr ""
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
msgstr "Ti è stata inviata un'email con le istruzioni per cambiare la tua password."
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr "Impossibile inviare l'email di recupero password perchè il tuo nome utente è inattivo o il tuo indirizzo email non è stato verificato."
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
msgstr "Ora puoi effettuare l'accesso con la nuova password."
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -120,7 +126,7 @@ msgid "Description of this work"
msgstr "Descrizione di questo lavoro"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -136,11 +142,11 @@ msgstr "Tags"
msgid "Separate tags by commas."
msgstr "Separa le tags con la virgola."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr ""
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr ""
@@ -168,45 +174,45 @@ msgid "This address contains errors"
msgstr "Questo indirizzo contiene errori"
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr "Password vecchia"
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr "Inserisci la vecchia password per dimostrare di essere il proprietario dell'account."
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr "Nuova password"
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
msgstr ""
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
msgstr ""
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr "Inviami messaggi email quando altre persone commentano i miei files multimediali"
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr ""
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr ""
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr "Password vecchia"
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr "Inserisci la vecchia password per dimostrare di essere il proprietario dell'account."
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr "Nuova password"
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr ""
@@ -231,44 +237,63 @@ msgstr "Stai modificando il profilo di un utente. Procedi con attenzione."
msgid "Profile changes saved"
msgstr "Cambiamenti del profilo salvati"
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr "Password errata"
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr "Impostazioni del profilo salvate"
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
msgstr ""
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr ""
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr "Password errata"
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr ""
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr ""
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
@@ -276,12 +301,16 @@ msgid ""
"domain."
msgstr ""
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr "Mi dispiace, non supporto questo tipo di file :("
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr ""
+
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr "Transcodifica video fallita"
@@ -348,7 +377,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
msgstr ""
@@ -367,7 +396,7 @@ msgstr ""
msgid "Add"
msgstr "Aggiungi"
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr "File non valido per il tipo di file multimediale indicato."
@@ -375,45 +404,45 @@ msgstr "File non valido per il tipo di file multimediale indicato."
msgid "File"
msgstr "File"
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr "Devi specificare un file."
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr "Evviva! Caricato!"
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr "Verifica la tua email!"
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr "Accedi"
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr "Cambia le impostazioni dell'account"
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -421,72 +450,25 @@ msgstr "Cambia le impostazioni dell'account"
msgid "Media processing panel"
msgstr "Pannello di elaborazione files multimediali"
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr "Aggiungi files multimediali"
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr "Rilasciato con licenza <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Codice sorgente</a> disponibile."
-
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr "Esplora"
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr "Ciao, benvenuto in questo sito MediaGoblin!"
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr "Questo sito sta utilizzando <a href=\"http://mediagoblin.org\">Mediagoblin</a>, un ottimo programma per caricare e condividere files multimediali."
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr "Per aggiungere i tuoi file multimediali, scrivere commenti e altro puoi accedere con il tuo account MediaGoblin."
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr "Non ne hai già uno? E' semplice!"
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">Crea un account in questo sito</a>\n oppure\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Installa MediaGoblin sul tuo server</a>"
-
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr "Files multimediali più recenti"
@@ -592,6 +574,53 @@ msgid ""
"%(verification_url)s"
msgstr "Ciao %(username)s,\n\nper attivare il tuo account GNU MediaGoblin, apri il seguente URL nel \ntuo navigatore web.\n\n%(verification_url)s"
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr "Rilasciato con licenza <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Codice sorgente</a> disponibile."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr "Esplora"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "Ciao, benvenuto in questo sito MediaGoblin!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr "Questo sito sta utilizzando <a href=\"http://mediagoblin.org\">Mediagoblin</a>, un ottimo programma per caricare e condividere files multimediali."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr "Per aggiungere i tuoi file multimediali, scrivere commenti e altro puoi accedere con il tuo account MediaGoblin."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr "Non ne hai già uno? E' semplice!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -604,13 +633,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr "Stai modificando gli allegati di %(media_title)s"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
msgstr "Allegati"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
msgstr "Aggiungi allegato"
@@ -627,12 +656,22 @@ msgstr "Annulla"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr "Salva i cambiamenti"
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
@@ -643,7 +682,7 @@ msgid "Yes, really delete my account"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "Elimina definitivamente"
@@ -660,7 +699,11 @@ msgstr "Stai modificando %(media_title)s"
msgid "Changing %(username)s's account settings"
msgstr "Stai cambiando le impostazioni dell'account di %(username)s"
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
msgstr ""
@@ -685,6 +728,7 @@ msgstr "File taggato con: %(tag_name)s"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -709,6 +753,7 @@ msgid ""
msgstr "Puoi scaricare un browser web moderno,\n\t in grado di leggere questo file audio, qui <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!"
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr "File originario"
@@ -717,6 +762,7 @@ msgstr "File originario"
msgid "WebM file (Vorbis codec)"
msgstr "File WebM (codec Vorbis)"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -727,6 +773,10 @@ msgstr "File WebM (codec Vorbis)"
msgid "Image for %(media_title)s"
msgstr ""
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
msgstr ""
@@ -753,7 +803,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131
msgid "WebGL"
-msgstr ""
+msgstr "WebGL"
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138
msgid "Download model"
@@ -825,7 +875,7 @@ msgstr "Vuoi davvero eliminare %(title)s?"
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr ""
@@ -868,24 +918,28 @@ msgstr "Files multimediali di <a href=\"%(user_url)s\">%(username)s</a>"
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr "â– Stai guardando i files multimediali di <a href=\"%(user_url)s\">%(username)s</a>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
msgstr "Aggiungi un commento"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
msgstr "Aggiungi questo commento"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
-msgstr "a"
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
-msgstr "<h3>Aggiunto il</h3>\n <p>%(date)s</p>"
+msgid "%(formatted_time)s ago"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
+msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40
@@ -1041,7 +1095,7 @@ msgstr "più vecchio"
msgid "Tagged with"
msgstr "Taggato con"
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr "Impossibile leggere il file immagine."
@@ -1071,6 +1125,30 @@ msgid ""
" deleted."
msgstr ""
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr ""
+
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
msgstr ""
@@ -1102,73 +1180,77 @@ msgstr ""
msgid "Include a note"
msgstr ""
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
msgstr "ha commentato il tuo post"
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr "Oops, il tuo commento era vuoto."
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr "Il tuo commento è stato aggiunto!"
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr ""
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr "Hai eliminato il file."
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr "Il file non è stato eliminato perchè non hai confermato di essere sicuro."
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr "Stai eliminando un file multimediale di un altro utente. Procedi con attenzione."
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr ""
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr ""
diff --git a/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.mo
index 1344c9bd..3c82d1ff 100644
--- a/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.po
index 008a6d27..97d68127 100644
--- a/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.po
@@ -3,16 +3,16 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
-# <averym@gmail.com>, 2011.
-# <parlegon@gmail.com>, 2013.
+# Avery <averym@gmail.com>, 2011
+# parlegon <parlegon@gmail.com>, 2013
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-05 00:04+0000\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-05-27 18:54+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language-Team: Japanese (http://www.transifex.com/projects/p/mediagoblin/language/ja/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -20,34 +20,39 @@ msgstr ""
"Language: ja\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
+#: mediagoblin/auth/forms.py:26
msgid "Username"
msgstr "ユーザãƒãƒ¼ãƒ "
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
msgid "Password"
msgstr "パスワード"
-#: mediagoblin/auth/forms.py:60
+#: mediagoblin/auth/forms.py:34
msgid "Email address"
msgstr "メールアドレス"
-#: mediagoblin/auth/forms.py:78
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
+msgstr ""
+
+#: mediagoblin/auth/forms.py:52
msgid "Username or email"
msgstr ""
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr ""
+
#: mediagoblin/auth/views.py:54
msgid "Sorry, registration is disabled on this instance."
msgstr "申ã—訳ã‚りã¾ã›ã‚“ãŒã€ã“ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã§ç™»éŒ²ã¯ç„¡åйã«ãªã£ã¦ã„ã¾ã™ã€‚"
@@ -60,54 +65,54 @@ msgstr "申ã—訳ã‚りã¾ã›ã‚“ãŒã€ãã®åå‰ã‚’æŒã¤ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒã™ã§
msgid "Sorry, a user with that email address already exists."
msgstr ""
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr "メアドãŒç¢ºèªã•れã¦ã„ã¾ã™ã€‚ã“れã§ã€ãƒ­ã‚°ã‚¤ãƒ³ã—ã¦ãƒ—ロファイルを編集ã—ã€ç”»åƒã‚’æå‡ºã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ï¼"
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr "検証キーã¾ãŸã¯ãƒ¦ãƒ¼ã‚¶ãƒ¼IDãŒé–“é•ã£ã¦ã„ã¾ã™"
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr ""
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr ""
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr "検証メールをå†é€ã—ã¾ã—ãŸã€‚"
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
msgstr ""
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
msgstr ""
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
msgstr ""
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr ""
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
msgstr ""
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -118,7 +123,7 @@ msgid "Description of this work"
msgstr ""
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -134,11 +139,11 @@ msgstr "ã‚¿ã‚°"
msgid "Separate tags by commas."
msgstr ""
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "スラグ"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "スラグã¯å¿…è¦ã§ã™ã€‚"
@@ -166,45 +171,45 @@ msgid "This address contains errors"
msgstr ""
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr ""
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr ""
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr ""
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
msgstr ""
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
msgstr ""
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr ""
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr ""
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr ""
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr ""
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr ""
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr "ãã®ã‚¹ãƒ©ã‚°ã‚’æŒã¤ã‚¨ãƒ³ãƒˆãƒªã¯ã€ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯æ—¢ã«å­˜åœ¨ã—ã¾ã™ã€‚"
@@ -229,44 +234,63 @@ msgstr "ã‚ãªãŸã¯ã€ä»–ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ—ロファイルを編集ã—ã¦ã„
msgid "Profile changes saved"
msgstr ""
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr ""
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr ""
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
msgstr ""
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr ""
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr ""
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr ""
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr ""
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
@@ -274,12 +298,16 @@ msgid ""
"domain."
msgstr ""
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr ""
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr ""
+
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr ""
@@ -346,7 +374,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
msgstr ""
@@ -365,7 +393,7 @@ msgstr ""
msgid "Add"
msgstr "追加"
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr ""
@@ -373,45 +401,45 @@ msgstr ""
msgid "File"
msgstr "ファイル"
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr "ファイルをæä¾›ã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚"
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr "投稿終了ï¼"
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr "ログイン"
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -419,72 +447,25 @@ msgstr ""
msgid "Media processing panel"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr "ã“ã‚“ã«ã¡ã¯ã€ã“ã®MediaGoblinサイトã¸ã‚ˆã†ã“ãï¼"
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr ""
@@ -590,6 +571,53 @@ msgid ""
"%(verification_url)s"
msgstr "%(username)s様ã¸\n\nGNU MediaGoblinアカウントを検証ã«ã™ã‚‹ã«ã¯ã€ã“ã®URLã‚’é–‹ã„ã¦ãã ã•ã„。\n\n%(verification_url)s"
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "ã“ã‚“ã«ã¡ã¯ã€ã“ã®MediaGoblinサイトã¸ã‚ˆã†ã“ãï¼"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -602,13 +630,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
msgstr ""
@@ -625,12 +653,22 @@ msgstr "キャンセル"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr "投稿ã™ã‚‹"
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
@@ -641,7 +679,7 @@ msgid "Yes, really delete my account"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr ""
@@ -658,7 +696,11 @@ msgstr "%(media_title)sを編集中"
msgid "Changing %(username)s's account settings"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
msgstr ""
@@ -683,6 +725,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -707,6 +750,7 @@ msgid ""
msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr ""
@@ -715,6 +759,7 @@ msgstr ""
msgid "WebM file (Vorbis codec)"
msgstr ""
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -725,6 +770,10 @@ msgstr ""
msgid "Image for %(media_title)s"
msgstr ""
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
msgstr ""
@@ -823,7 +872,7 @@ msgstr ""
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr ""
@@ -866,23 +915,27 @@ msgstr "<a href=\"%(user_url)s\">%(username)s</a>ã•ã‚“ã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„"
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
+#, python-format
+msgid "%(formatted_time)s ago"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
-#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
@@ -1039,7 +1092,7 @@ msgstr ""
msgid "Tagged with"
msgstr ""
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr ""
@@ -1069,6 +1122,30 @@ msgid ""
" deleted."
msgstr ""
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr ""
+
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
msgstr ""
@@ -1100,73 +1177,77 @@ msgstr ""
msgid "Include a note"
msgstr ""
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
msgstr ""
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr ""
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr ""
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr ""
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr ""
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr ""
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr ""
diff --git a/mediagoblin/i18n/ko_KR/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ko_KR/LC_MESSAGES/mediagoblin.mo
index 69bf72bc..7d37ab7c 100644
--- a/mediagoblin/i18n/ko_KR/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/ko_KR/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/ko_KR/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/ko_KR/LC_MESSAGES/mediagoblin.po
index ac87c90f..5333de02 100644
--- a/mediagoblin/i18n/ko_KR/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/ko_KR/LC_MESSAGES/mediagoblin.po
@@ -3,15 +3,15 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
-# <newvgund@gmail.com>, 2012.
+# Jin-hoon Kim <newvgund@gmail.com>, 2012
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-05 00:04+0000\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-05-27 18:54+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language-Team: Korean (Korea) (http://www.transifex.com/projects/p/mediagoblin/language/ko_KR/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -19,34 +19,39 @@ msgstr ""
"Language: ko_KR\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
+#: mediagoblin/auth/forms.py:26
msgid "Username"
msgstr "ì‚¬ìš©ìž ì´ë¦„"
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
msgid "Password"
msgstr "비밀번호"
-#: mediagoblin/auth/forms.py:60
+#: mediagoblin/auth/forms.py:34
msgid "Email address"
msgstr "email 주소"
-#: mediagoblin/auth/forms.py:78
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
+msgstr ""
+
+#: mediagoblin/auth/forms.py:52
msgid "Username or email"
msgstr "ì‚¬ìš©ìž ì´ë¦„ ë˜ëŠ” email"
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr ""
+
#: mediagoblin/auth/views.py:54
msgid "Sorry, registration is disabled on this instance."
msgstr "죄송합니다. ì§€ê¸ˆì€ ê°€ìž… 하실 수 없습니다."
@@ -59,54 +64,54 @@ msgstr "죄송합니다. 해당 ì‚¬ìš©ìž ì´ë¦„ì´ ì´ë¯¸ 존재 합니다."
msgid "Sorry, a user with that email address already exists."
msgstr "죄송합니다. 사용ìžì™€ 해당 ì´ë©”ì¼ì€ ì´ë¯¸ 등ë¡ë˜ì–´ 있습니다."
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr "해당 email 주소가 ì´ë¯¸ ì¸ì¦ ë˜ì–´ 있습니다. 지금 로그ì¸í•˜ì‹œê³  계정 정보를 수정하고 ì‚¬ì§„ì„ ì „ì†¡í•´ 보세요!"
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr "ì¸ì¦ 키 ë˜ëŠ” ì‚¬ìš©ìž IDê°€ 올바르지 않습니다."
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr "로그ì¸ì„ 하셔야 고블린ì—서 ë©”ì¼ì„ 보낼 수 있습니다!"
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr "ì´ë¯¸ ì¸ì¦ë°›ì€ email 주소를 가지고 있습니다!"
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr "ì¸ì¦ ë©”ì¼ì„ 다시 ë³´ë‚´ 주세요."
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
msgstr ""
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
msgstr ""
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
msgstr "비밀번호를 변경하는 ë°©ë²•ì— ëŒ€í•œ 설명서가 ë©”ì¼ë¡œ 전송 ë˜ì—ˆìŠµë‹ˆë‹¤."
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr "사용ìžì˜ ì´ë¦„ì´ ì¡´ìž¬í•˜ì§€ 않거나, 사용ìžì˜ email 주소가 ì¸ì¦ë˜ì§€ 않아 비밀번호 복구 ë©”ì¼ì„ 보낼 수 없습니다."
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
msgstr "ì´ì œ 새로운 비밀번호로 ë¡œê·¸ì¸ í•˜ì‹¤ 수 있습니다."
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -117,7 +122,7 @@ msgid "Description of this work"
msgstr "ì´ ìž‘ì—…ì— ëŒ€í•œ 설명"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -133,11 +138,11 @@ msgstr "태그"
msgid "Separate tags by commas."
msgstr "태그는 , 로 구분 ë©ë‹ˆë‹¤."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "'슬러그'"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "'슬러그'는 ê³µë°±ì¼ ìˆ˜ 없습니다."
@@ -165,45 +170,45 @@ msgid "This address contains errors"
msgstr "ì£¼ì†Œì— ì—러가 있습니다."
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr "예전 비밀번호"
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr "계정 확ì¸ì„ 위해, ì´ì „ 비밀 번호를 입력해 주세요."
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr "새로운 비밀번호"
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
msgstr ""
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
msgstr ""
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr "ì œ ë¯¸ë””ì–´ì— ëŒ€í•œ 컨í…ì„ ì›í•œë‹¤ë©´, ë©”ì¼ì„ 보내주세요."
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr "ì œëª©ì€ ê³µë°±ì¼ ìˆ˜ 없습니다."
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr "모ìŒì§‘ì— ëŒ€í•œ 설명"
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr ""
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr "예전 비밀번호"
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr "계정 확ì¸ì„ 위해, ì´ì „ 비밀 번호를 입력해 주세요."
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr "새로운 비밀번호"
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr "해당 ìœ ì €ì— ëŒ€í•œ '슬러그'ê°€ ì´ë¯¸ 존재합니다."
@@ -228,44 +233,63 @@ msgstr "사용ìžì˜ 계정 정보를 수정하고 있습니다. 조심해서 ìˆ
msgid "Profile changes saved"
msgstr "계정 ì •ë³´ê°€ 저장 ë˜ì—ˆìŠµë‹ˆë‹¤."
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr "ìž˜ëª»ëœ ë¹„ë°€ë²ˆí˜¸"
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr "계정 ì„¤ì •ì´ ì €ìž¥ ë˜ì—ˆìŠµë‹ˆë‹¤."
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
msgstr ""
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr "\"%s\" 모ìŒì§‘ì„ ì´ë¯¸ 가지고 있습니다!"
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr "다른 ìœ ì €ì˜ ëª¨ìŒì§‘ì„ ìˆ˜ì • 중 입니다. 주ì˜í•˜ì„¸ìš”."
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr "ìž˜ëª»ëœ ë¹„ë°€ë²ˆí˜¸"
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr "í…Œë§ˆì— ì—°ê²°í•  수 없습니다... 테마 ì…‹ì´ ì—†ìŠµë‹ˆë‹¤.\n"
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr "ì´ í…Œë§ˆë¥¼ 위한 ì—ì…‹ 디렉토리가 없습니다.\n"
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr "그런ë°, ì˜¤ëž˜ëœ ë””ë ‰í† ë¦¬ 심볼릭 ë§í¬ë¥¼ 찾았습니다; 지워졌습니다.\n"
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr ""
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
@@ -273,12 +297,16 @@ msgid ""
"domain."
msgstr ""
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr "죄송합니다. 해당 íƒ€ìž…ì˜ íŒŒì¼ì€ ì§€ì›í•˜ì§€ 않아요 :("
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr ""
+
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr "비디오 ë³€í™˜ì— ì‹¤íŒ¨ 했습니다."
@@ -345,7 +373,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr "ì´ í•­ëª©ì€ ê³µê°œ 사용ìžë“¤ì„ 위해 ê¼­ í•„ìš” 합니다."
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
msgstr "ì‚¬ìš©ìž {0}ë‹˜ì´ ë“±ë¡ ë˜ì—ˆìŠµë‹ˆë‹¤!"
@@ -364,7 +392,7 @@ msgstr ""
msgid "Add"
msgstr "추가"
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr "알수없는 미디어 íŒŒì¼ ìž…ë‹ˆë‹¤."
@@ -372,45 +400,45 @@ msgstr "알수없는 미디어 íŒŒì¼ ìž…ë‹ˆë‹¤."
msgid "File"
msgstr "파ì¼"
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr "파ì¼ì„ 등ë¡í•˜ì…”야 합니다."
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr "ì´í–!! 등ë¡í–ˆìŠµë‹ˆë‹¤!"
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr "\"%s\" 모ìŒì§‘ì´ ì¶”ê°€ë˜ì—ˆìŠµë‹ˆë‹¤!"
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr "ë©”ì¼ì„ 확ì¸í•˜ì„¸ìš”!"
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr "로그ì¸"
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr "계정 설정 변경"
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -418,72 +446,25 @@ msgstr "계정 설정 변경"
msgid "Media processing panel"
msgstr "미디어 작업 패ë„"
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr "미디어 추가"
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr "Released under the <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Source code</a> available."
-
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr "íƒìƒ‰"
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr "안녕하세요! 미디어 고블린 사ì´íŠ¸ì— ì˜¨ê±¸ í™˜ì˜ í•©ë‹ˆë‹¤!"
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr "ì´ì‚¬ì´íŠ¸ëŠ” <a href=\"http://mediagoblin.org\">MediaGoblin</a>으로 ìž‘ë™ ì¤‘ìž…ë‹ˆë‹¤. ì´ëŠ” 특ì´í•œ 미디어 호스팅 소프트웨어중 하나 입니다."
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr "ìžì‹ ì˜ 미디어를 추가하고, ëŒ“ê¸€ì„ ë‚¨ê¸°ì„¸ìš”! 미디어 고블린 계정으로 ë‚´ì—­ì„ í™•ì¸ í•˜ì‹¤ 수 있습니다!"
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr "ì•„ì§ ì•„ë¬´ê²ƒë„ ì—†ìœ¼ì‹œë‹¤êµ¬ìš”? 매우 쉽습니다!"
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">ì‚¬ìš©ìž ê³„ì • 만들기</a>\n ë˜ëŠ”\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">서버를 위한 MediaGoblin 설정하기</a>"
-
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr "가장 ìµœê·¼ì— ë“±ë¡ëœ 미디어"
@@ -589,6 +570,53 @@ msgid ""
"%(verification_url)s"
msgstr "안녕하세요 %(username)s님,\n\nGNU MediaGoblin ê³„ì •ì„ í™œì„±í™” 하시려면, ì•„ëž˜ì˜ URL 주소를 브ë¼ìš°ì ¸ë¡œ ì ‘ì†í•˜ì„¸ìš”.\n\n%(verification_url)s"
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr "Released under the <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Source code</a> available."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr "íƒìƒ‰"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "안녕하세요! 미디어 고블린 사ì´íŠ¸ì— ì˜¨ê±¸ í™˜ì˜ í•©ë‹ˆë‹¤!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr "ì´ì‚¬ì´íŠ¸ëŠ” <a href=\"http://mediagoblin.org\">MediaGoblin</a>으로 ìž‘ë™ ì¤‘ìž…ë‹ˆë‹¤. ì´ëŠ” 특ì´í•œ 미디어 호스팅 소프트웨어중 하나 입니다."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr "ìžì‹ ì˜ 미디어를 추가하고, ëŒ“ê¸€ì„ ë‚¨ê¸°ì„¸ìš”! 미디어 고블린 계정으로 ë‚´ì—­ì„ í™•ì¸ í•˜ì‹¤ 수 있습니다!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr "ì•„ì§ ì•„ë¬´ê²ƒë„ ì—†ìœ¼ì‹œë‹¤êµ¬ìš”? 매우 쉽습니다!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -601,13 +629,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr "%(media_title)sì˜ ì²¨ë¶€ 수정 중..."
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
msgstr "첨부"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
msgstr "첨부 추가"
@@ -624,12 +652,22 @@ msgstr "취소"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr "저장"
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
@@ -640,7 +678,7 @@ msgid "Yes, really delete my account"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "ì˜êµ¬ì ìœ¼ë¡œ ì‚­ì œ"
@@ -657,7 +695,11 @@ msgstr "%(media_title)s 편집중..."
msgid "Changing %(username)s's account settings"
msgstr "%(username)s'ì˜ ê³„ì • 설정 변경중..."
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
msgstr ""
@@ -682,6 +724,7 @@ msgstr "미디어는 다ìŒìœ¼ë¡œ 태그 ë˜ì—ˆìŠµë‹ˆë‹¤.: %(tag_name)s"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -706,6 +749,7 @@ msgid ""
msgstr "사운드 파ì¼ì„ ìž¬ìƒ í•˜ì‹œë ¤ë©´\n\tì´ê³³ì—서 ìµœì‹ ì˜ ë¸Œë¼ìš°ì ¸ë¥¼ 다운받으세요! <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!"
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr "ì›ë³¸ 파ì¼"
@@ -714,6 +758,7 @@ msgstr "ì›ë³¸ 파ì¼"
msgid "WebM file (Vorbis codec)"
msgstr "WebM íŒŒì¼ (Vorbis ì½”ë±)"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -724,6 +769,10 @@ msgstr "WebM íŒŒì¼ (Vorbis ì½”ë±)"
msgid "Image for %(media_title)s"
msgstr "%(media_title)s ì´ë¯¸ì§€"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
msgstr ""
@@ -822,7 +871,7 @@ msgstr "%(title)s ì„ ì§€ìš°ì‹œê² ìŠµë‹ˆê¹Œ?"
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr "%(collection_title)sì˜ %(media_title)sì„ ì‚­ì œ 하시겠습니까?"
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr "지우기"
@@ -865,24 +914,28 @@ msgstr "<a href=\"%(user_url)s\">%(username)s</a>ì˜ ë¯¸ë””ì–´"
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr "â– <a href=\"%(user_url)s\">%(username)s</a>ì˜ ë¯¸ë””ì–´ë¥¼ ë³´ê³  있습니다."
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
msgstr "ë§ê¸€ 달기"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
msgstr "ë§ê¸€ 추가"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
-msgstr "ì—"
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
-msgstr "<h3>부가 기능</h3>\n <p>%(date)s</p>"
+msgid "%(formatted_time)s ago"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
+msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40
@@ -1038,7 +1091,7 @@ msgstr "ì´ì „"
msgid "Tagged with"
msgstr "태그 정보"
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr "ì´ë¯¸ì§€ 파ì¼ì„ ì½ì„ 수 없습니다."
@@ -1068,6 +1121,30 @@ msgid ""
" deleted."
msgstr ""
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr ""
+
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
msgstr ""
@@ -1099,73 +1176,77 @@ msgstr "-- ì„ íƒ --"
msgid "Include a note"
msgstr "노트 추가"
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
msgstr "ê²Œì‹œë¬¼ì— ë§ê¸€ì´ 달렸습니다."
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr "오우, ëŒ“ê¸€ì´ ë¹„ì—ˆìŠµë‹ˆë‹¤."
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr "ëŒ“ê¸€ì´ ë“±ë¡ ë˜ì—ˆìŠµë‹ˆë‹¤!"
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
msgstr "확ì¸ì„ 하시고 다시 시ë„하세요."
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr "모ìŒì§‘ì„ ì¶”ê°€í•˜ê±°ë‚˜ 기존 모ìŒì§‘ì„ ì„ íƒí•˜ì„¸ìš”."
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr "\"%s\" 모ìŒì§‘ì´ ì´ë¯¸ 존재 합니다. \"%s\""
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr "\"%s\" 모ìŒì§‘ì„ ì¶”ê°€í–ˆìŠµë‹ˆë‹¤. \"%s\""
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr "미디어를 삭제 했습니다."
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr "í™•ì¸ ì²´í¬ë¥¼ 하지 않았습니다. 미디어는 ì‚­ì œë˜ì§€ 않았습니다."
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr "다른 ì‚¬ëžŒì˜ ë¯¸ë””ì–´ë¥¼ 삭제하려고 합니다. 다시 한번 확ì¸í•˜ì„¸ìš”."
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr "모ìŒì§‘ì— ìžˆëŠ” í•­ëª©ì„ ì‚­ì œ 했습니다."
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr "확ì¸ì„ 하지 않았습니다. í•­ëª©ì€ ì‚­ì œí•˜ì§€ 않았습니다."
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr "다른 사용ìžì˜ 모ìŒì§‘ì— ìžˆëŠ” í•­ëª©ì„ ì‚­ì œí•˜ì˜€ìŠµë‹ˆë‹¤. 주ì˜í•˜ì„¸ìš”."
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr "\"%s\" 모ìŒì§‘ì„ ì‚­ì œí•˜ì…¨ìŠµë‹ˆë‹¤."
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr "확ì¸ì„ 하지 않았습니다. 모ìŒì§‘ì€ ì‚­ì œí•˜ì§€ 않았습니다."
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr "다른 사용ìžì˜ 모ìŒì§‘ì„ ì‚­ì œí•˜ë ¤ê³  합니다. 주ì˜í•˜ì„¸ìš”."
diff --git a/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.mo
index fe96d40e..4e6e51ce 100644
--- a/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.po
index 3fd26d23..14e4fb33 100644
--- a/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.po
@@ -3,16 +3,16 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
-# <mail@jefvanschendel.nl>, 2011, 2012.
-# <mvanderboom@gmail.com>, 2012.
+# schendje <mail@jefvanschendel.nl>, 2011, 2012
+# mvanderboom <mvanderboom@gmail.com>, 2012
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-05 00:04+0000\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-05-27 18:54+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language-Team: Dutch (http://www.transifex.com/projects/p/mediagoblin/language/nl/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -20,34 +20,39 @@ msgstr ""
"Language: nl\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
+#: mediagoblin/auth/forms.py:26
msgid "Username"
msgstr "Gebruikersnaam"
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
msgid "Password"
msgstr "Wachtwoord"
-#: mediagoblin/auth/forms.py:60
+#: mediagoblin/auth/forms.py:34
msgid "Email address"
msgstr "E-mail adres"
-#: mediagoblin/auth/forms.py:78
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
+msgstr ""
+
+#: mediagoblin/auth/forms.py:52
msgid "Username or email"
msgstr "Gebruikersnaam of email-adres"
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr ""
+
#: mediagoblin/auth/views.py:54
msgid "Sorry, registration is disabled on this instance."
msgstr "Sorry, registratie is uitgeschakeld op deze instantie."
@@ -60,54 +65,54 @@ msgstr "Sorry, er bestaat al een gebruiker met die naam."
msgid "Sorry, a user with that email address already exists."
msgstr "Sorry, een gebruiker met dat e-mailadres bestaat al."
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr "Uw e-mailadres is geverifieerd. U kunt nu inloggen, uw profiel bewerken, en afbeeldingen toevoegen!"
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr "De verificatie sleutel of gebruikers-ID is onjuist"
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr "Je moet ingelogd zijn, anders weten we niet waar we de e-mail naartoe moeten sturen!"
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr "Je hebt je e-mailadres al geverifieerd!"
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr "Verificatie e-mail opnieuw opgestuurd."
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
msgstr ""
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
msgstr ""
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
msgstr "Een e-mail met instructies om je wachtwoord te veranderen is verstuurd."
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr "Email kon niet verstuurd worden omdat je gebruikersnaam inactief is of omdat je e-mailadres nog niet geverifieerd is."
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
msgstr "Je kunt nu inloggen met je nieuwe wachtwoord."
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -118,7 +123,7 @@ msgid "Description of this work"
msgstr "Beschrijving van dit werk"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -134,11 +139,11 @@ msgstr "Etiket"
msgid "Separate tags by commas."
msgstr "Hou labels gescheiden met komma's."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "Slug"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "De slug kan niet leeg zijn"
@@ -166,45 +171,45 @@ msgid "This address contains errors"
msgstr "Dit adres bevat fouten"
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr "Oud wachtwoord"
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr "Vul je oude wachtwoord in om te bewijzen dat dit jouw account is"
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr "Nieuw wachtwoord"
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
msgstr ""
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
msgstr ""
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr ""
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr ""
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr ""
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr "Oud wachtwoord"
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr "Vul je oude wachtwoord in om te bewijzen dat dit jouw account is"
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr "Nieuw wachtwoord"
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr "Er bestaat al een met die slug voor deze gebruiker."
@@ -229,44 +234,63 @@ msgstr "U bent een gebruikersprofiel aan het aanpassen. Ga voorzichtig te werk."
msgid "Profile changes saved"
msgstr "Profielaanpassingen opgeslagen"
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr "Verkeerd wachtwoord"
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr "Accountinstellingen opgeslagen"
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
msgstr ""
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr ""
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr "Verkeerd wachtwoord"
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr ""
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr ""
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
@@ -274,12 +298,16 @@ msgid ""
"domain."
msgstr ""
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr "Sorry, dat bestandstype wordt niet ondersteunt."
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr ""
+
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr ""
@@ -346,7 +374,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
msgstr ""
@@ -365,7 +393,7 @@ msgstr ""
msgid "Add"
msgstr "Voeg toe"
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr "Verkeerd bestandsformaat voor mediatype opgegeven."
@@ -373,45 +401,45 @@ msgstr "Verkeerd bestandsformaat voor mediatype opgegeven."
msgid "File"
msgstr "Bestand"
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr "U moet een bestand aangeven."
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr "Mooizo! Toegevoegd!"
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr "Verifieer je e-mailadres!"
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr "Inloggen"
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr "Accountinstellingen aanpassen"
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -419,72 +447,25 @@ msgstr "Accountinstellingen aanpassen"
msgid "Media processing panel"
msgstr "Mediaverwerkingspaneel"
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr "Voeg media toe"
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr "Uitgegeven onder de <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>-licentie. <a href=\"%(source_link)s\">Broncode</a> available."
-
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr "Verkennen"
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr "Hoi, welkom op deze MediaGoblin website!"
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr "Deze website draait <a href=\"http://mediagoblin.org\">MediaGoblin</a>, een buitengewoon goed stuk software voor mediahosting."
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr "Heb je er nog geen? Het is heel eenvoudig!"
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr "&lt;a class=\"button_action_highlight\" href=\"%(register_url)s\"&gt;Creëer een account op deze website&lt;/a&gt;\n of\n &lt;a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\"&gt;Gebruik MediaGoblin op je eigen server&lt;/a&gt;"
-
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr "Nieuwste media"
@@ -590,6 +571,53 @@ msgid ""
"%(verification_url)s"
msgstr "Hallo %(username)s , open de volgende URL in uw webbrowser om uw GNU MediaGoblin account te activeren: %(verification_url)s "
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr "Uitgegeven onder de <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>-licentie. <a href=\"%(source_link)s\">Broncode</a> available."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr "Verkennen"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "Hoi, welkom op deze MediaGoblin website!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr "Deze website draait <a href=\"http://mediagoblin.org\">MediaGoblin</a>, een buitengewoon goed stuk software voor mediahosting."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr "Heb je er nog geen? Het is heel eenvoudig!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -602,13 +630,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
msgstr ""
@@ -625,12 +653,22 @@ msgstr "Annuleren"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr "Wijzigingen opslaan"
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
@@ -641,7 +679,7 @@ msgid "Yes, really delete my account"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "Permanent verwijderen"
@@ -658,7 +696,11 @@ msgstr "%(media_title)s aanpassen"
msgid "Changing %(username)s's account settings"
msgstr "%(username)ss accountinstellingen aanpassen"
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
msgstr ""
@@ -683,6 +725,7 @@ msgstr "Media met het label: %(tag_name)s"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -707,6 +750,7 @@ msgid ""
msgstr "U kunt een moderne web-browser die \n\taudio kan afspelen vinden op <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!"
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr ""
@@ -715,6 +759,7 @@ msgstr ""
msgid "WebM file (Vorbis codec)"
msgstr ""
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -725,6 +770,10 @@ msgstr ""
msgid "Image for %(media_title)s"
msgstr "Afbeelding voor %(media_title)s"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
msgstr ""
@@ -823,7 +872,7 @@ msgstr "Zeker weten dat je %(title)s wil verwijderen?"
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr ""
@@ -866,24 +915,28 @@ msgstr "Media van <a href=\"%(user_url)s\"> %(username)s </a>"
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr "â– Blader door media van <a href=\"%(user_url)s\">%(username)s</a>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
msgstr "Geef een reactie"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
msgstr "Voeg dit bericht toe"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
-msgstr "op"
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
-msgstr "<h3>Toegevoegd op</h3>\n <p>%(date)s</p>"
+msgid "%(formatted_time)s ago"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
+msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40
@@ -1039,7 +1092,7 @@ msgstr "ouder"
msgid "Tagged with"
msgstr "Getagged met"
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr "Kon het afbeeldingsbestand niet lezen."
@@ -1069,6 +1122,30 @@ msgid ""
" deleted."
msgstr ""
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr ""
+
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
msgstr ""
@@ -1100,73 +1177,77 @@ msgstr ""
msgid "Include a note"
msgstr ""
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
msgstr ""
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr "Oeps, je bericht was leeg."
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr "Je bericht is geplaatst!"
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr ""
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr "Je hebt deze media verwijderd."
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr "Deze media was niet verwijderd omdat je niet hebt aangegeven dat je het zeker weet."
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr "Je staat op het punt de media van iemand anders te verwijderen. Pas op."
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr ""
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr ""
diff --git a/mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.mo
index f58e6a45..9cbd03b2 100644
--- a/mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.po
index 12d34b55..6a11d5da 100644
--- a/mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.po
@@ -3,14 +3,14 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
-# <odin.omdal@gmail.com>, 2013.
-# <odin.omdal@gmail.com>, 2011-2012.
+# velmont <odin.omdal@gmail.com>, 2013
+# velmont <odin.omdal@gmail.com>, 2011-2012
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-10 13:31+0000\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-05-31 15:40+0000\n"
"Last-Translator: velmont <odin.omdal@gmail.com>\n"
"Language-Team: Norwegian Nynorsk (Norway) (http://www.transifex.com/projects/p/mediagoblin/language/nn_NO/)\n"
"MIME-Version: 1.0\n"
@@ -20,34 +20,39 @@ msgstr ""
"Language: nn_NO\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
-msgstr "Ugyldig brukarnamn eller passord."
-
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
-msgstr "Dette feltet tek ikkje epostadresser."
-
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
-msgstr "Dette feltet krev ei epostadresse."
-
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
+#: mediagoblin/auth/forms.py:26
msgid "Username"
msgstr "Brukarnamn"
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
msgid "Password"
msgstr "Passord"
-#: mediagoblin/auth/forms.py:60
+#: mediagoblin/auth/forms.py:34
msgid "Email address"
msgstr "Epost"
-#: mediagoblin/auth/forms.py:78
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
+msgstr "Brukarnamn eller epost"
+
+#: mediagoblin/auth/forms.py:52
msgid "Username or email"
msgstr "Brukarnamn eller epost"
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr "Ugyldig brukarnamn eller passord."
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr "Dette feltet tek ikkje epostadresser."
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr "Dette feltet krev ei epostadresse."
+
#: mediagoblin/auth/views.py:54
msgid "Sorry, registration is disabled on this instance."
msgstr "Registrering er slege av. Orsak."
@@ -60,54 +65,54 @@ msgstr "Ein konto med dette brukarnamnet finst allereide."
msgid "Sorry, a user with that email address already exists."
msgstr "Ein brukar med den epostadressa finst allereie."
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr "Kontoen din er stadfesta. Du kan no logga inn, endra profilen din og lasta opp filer."
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr "Stadfestingsnykelen eller brukar-ID-en din er feil."
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr "Du må vera innlogga, slik me veit kven som skal ha eposten."
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr "Du har allereie verifisiert epostadressa."
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr "Send ein ny stadfestingsepost."
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
msgstr "Dersom denne epostadressa er registrert, har ein epost med instruksjonar for å endra passord vorte sendt til han."
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
msgstr "Fann ingen med det brukarnamnet."
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
msgstr "Sender epost med instruksjonar for å endra passordet ditt."
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr "Kunne ikkje senda epost. Brukarnamnet ditt er inaktivt eller uverifisert."
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
msgstr "Du kan no logga inn med det nye passordet ditt."
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -118,7 +123,7 @@ msgid "Description of this work"
msgstr "Skildring av verk"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -134,11 +139,11 @@ msgstr "Merkelappar"
msgid "Separate tags by commas."
msgstr "Separer merkelappar med komma."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "Nettnamn"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "Nettnamnet kan ikkje vera tomt"
@@ -166,45 +171,45 @@ msgid "This address contains errors"
msgstr "Adressa inneheld feil"
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr "Gamalt passort"
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr "Skriv inn det gamle passordet ditt for å stadfesta at du eig denne kontoen."
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr "Nytt passord"
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
msgstr "Lisens-val"
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
msgstr "Dette vil vera standardvalet ditt for lisens."
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr "Send meg epost når andre kjem med innspel på verka mine."
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr "Tittelen kjan ikkje vera tom"
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr "Forklaringa til denne samlinga"
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr "Tittel-delen av denne samlinga si adresse. Du treng normalt sett ikkje endra denne."
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr "Gamalt passort"
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr "Skriv inn det gamle passordet ditt for å stadfesta at du eig denne kontoen."
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr "Nytt passord"
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr "Eit innlegg med denne adressetittelen finst allereie."
@@ -229,44 +234,63 @@ msgstr "Trå varsamt, du endrar nokon andre sin profil."
msgid "Profile changes saved"
msgstr "Lagra endring av profilen"
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr "Feil passord"
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr "Lagra kontoinstellingar"
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
msgstr "Du må stadfesta slettinga av kontoen din."
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr "Du har allereie ei samling med namn «%s»."
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr "Ei samling med den nettadressa finst allereie for denne brukaren."
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr "Du endrar ein annan brukar si samling. Trå varsamt."
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr "Feil passord"
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr "Endra passord"
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr "Cannot link theme... no theme set\n"
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr "No asset directory for this theme\n"
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr "However, old link directory symlink found; removed.\n"
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr "Kunne ikkje lenkja «%s»: %s eksisterer og er ikkje ei symlenkje\n"
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr "Hopper over «%s»: allereie satt opp.\n"
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr "Gamal lenkje funnen for «%s»; fjernar.\n"
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
@@ -274,12 +298,16 @@ msgid ""
"domain."
msgstr "Finn ikkje CSRF-cookien. Dette er truleg grunna ein cookie-blokkar.<br/>\nSjå til at du tillet cookies for dette domenet."
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr "Orsak, stør ikkje den filtypen :("
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr "klarte ikkje køyra unoconv, sjekk logg-fil"
+
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr "Skjedde noko gale med video transkodinga"
@@ -346,7 +374,7 @@ msgstr "Omdirigerings-URI-en for programmene. Denne feltet <strong>krevst</stron
msgid "This field is required for public clients"
msgstr "Dette feltet krevst for opne (public) klientar"
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
msgstr "Klienten {0} er registrert."
@@ -365,7 +393,7 @@ msgstr "Dine OAuth-klientar"
msgid "Add"
msgstr "Legg til"
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr "Ugyldig fil for medietypen."
@@ -373,45 +401,45 @@ msgstr "Ugyldig fil for medietypen."
msgid "File"
msgstr "Fil"
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr "Du må velja ei fil."
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr "Johoo! Opplasta!"
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr "La til samlinga «%s»."
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr "Verifiser epostadressa di."
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
msgstr "Logg ut"
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr "Logg inn"
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr "<a href=\"%(user_url)s\">%(user_name)s</a> sin konto"
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr "Endra kontoinstellingar"
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -419,72 +447,25 @@ msgstr "Endra kontoinstellingar"
msgid "Media processing panel"
msgstr "Verkprosesseringspanel"
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
msgstr "Logg ut"
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr "Legg til verk"
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
msgstr "Lag ny samling"
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr "Drive av <a href=\"http://mediagoblin.org\" title='Version %(version)s'>MediaGoblin</a>, eit <a href=\"http://gnu.org/\">GNU</a>-prosjekt."
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr "Lisensiert med <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Kjeldekode</a> er tilgjengeleg."
-
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
msgstr "Bilete av stressa goblin"
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr "Utforsk"
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr "Heihei, velkomen til denne MediaGoblin-sida."
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr "Denne sida køyrer <a href=\"http://mediagoblin.org\">MediaGoblin</a>, eit superbra program for å visa fram dine kreative verk."
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr "Vil du leggja til eigne verk og innpel, so må du logga inn."
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr "Har du ikkje ein enno? Det er enkelt!"
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">Opprett ein konto på denne sida</a> eller <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">set opp MediaGoblin på eigen tenar</a>"
-
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr "Nyaste verk"
@@ -590,6 +571,53 @@ msgid ""
"%(verification_url)s"
msgstr "Hei %(username)s,\n\nopna fylgjande netadresse i netlesaren din for å aktivera kontoen din:\n\n%(verification_url)s"
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr "Drive av <a href=\"http://mediagoblin.org\" title='Version %(version)s'>MediaGoblin</a>, eit <a href=\"http://gnu.org/\">GNU</a>-prosjekt."
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr "Lisensiert med <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Kjeldekode</a> er tilgjengeleg."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr "Utforsk"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "Heihei, velkomen til denne MediaGoblin-sida."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr "Denne sida køyrer <a href=\"http://mediagoblin.org\">MediaGoblin</a>, eit superbra program for å visa fram dine kreative verk."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr "Vil du leggja til eigne verk og innpel, so må du logga inn."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr "Har du ikkje ein enno? Det er enkelt!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">Opprett ein konto på denne sida</a>\n eller\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set opp din eigen MediaGoblin-server</a>"
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -602,13 +630,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr "Endrar vedlegg for %(media_title)s"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
msgstr "Vedlegg"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
msgstr "Legg ved vedlegg"
@@ -625,12 +653,22 @@ msgstr "Bryt av"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr "Lagra"
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr "Endrar passordet til %(username)s"
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr "Lagra"
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
@@ -641,7 +679,7 @@ msgid "Yes, really delete my account"
msgstr "Ja, slett kontoen min"
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "Slett permanent"
@@ -658,7 +696,11 @@ msgstr "Endrar %(media_title)s"
msgid "Changing %(username)s's account settings"
msgstr "Endrar kontoinnstellingane til %(username)s"
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr "Endra passordet ditt."
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
msgstr "Slett kontoen min"
@@ -683,6 +725,7 @@ msgstr "Verk merka med: %(tag_name)s"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -707,6 +750,7 @@ msgid ""
msgstr "Du kan skaffa ein moderne netlesar som kan spela av dette lydklippet hjå <a href=\"http://opera.com/download\">http://opera.com/download</a>."
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr "Opphavleg fil"
@@ -715,6 +759,7 @@ msgstr "Opphavleg fil"
msgid "WebM file (Vorbis codec)"
msgstr "WebM-fil (Vorbis-kodek)"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -725,6 +770,10 @@ msgstr "WebM-fil (Vorbis-kodek)"
msgid "Image for %(media_title)s"
msgstr "Bilete for %(media_title)s"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr "PDF-fil"
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
msgstr "Slå av/på rotering"
@@ -823,7 +872,7 @@ msgstr "Vil du verkeleg sletta %(title)s?"
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr "Fjerna %(media_title)s frå %(collection_title)s?"
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr "Fjern"
@@ -866,24 +915,28 @@ msgstr "<a href=\"%(user_url)s\">%(username)s</a> sine verk"
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr "■Ser på <a href=\"%(user_url)s\">%(username)s</a> sine verk"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
msgstr "Legg att innspel"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
msgstr "Legg til dette innspelet"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
-msgstr "hjå"
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
-msgstr "<h3>Lagt til</h3>\n <p>%(date)s</p>"
+msgid "%(formatted_time)s ago"
+msgstr "%(formatted_time)s sidan"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr "Lagt til"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
+msgstr "Oppretta"
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40
@@ -1039,7 +1092,7 @@ msgstr "eldre"
msgid "Tagged with"
msgstr "Merka med"
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr "Klarte ikkje lesa biletefila."
@@ -1069,6 +1122,30 @@ msgid ""
" deleted."
msgstr "Ser ikkje ut til å finnast noko her. Orsak.</p>\n<p>Dersom du er sikker på at adressa finst, so er ho truleg flytta eller sletta."
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr "Ã¥r"
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr "månad"
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr "veke"
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr "dag"
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr "time"
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr "minutt"
+
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
msgstr "Innspel"
@@ -1100,73 +1177,77 @@ msgstr "-- Vel --"
msgid "Include a note"
msgstr "Legg ved eit notat"
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
msgstr "kom med innspel på innlegget ditt"
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr "Innspel er avslege"
+
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr "Vops, innspelet ditt var tomt."
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr "Innspelet ditt er lagt til."
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
msgstr "Sjekk filene dine og prøv omatt."
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr "Du må velja eller laga ei samling"
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr "«%s» er allereie i samling «%s»"
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr "«%s» lagt til samling «%s»"
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr "Du sletta verket."
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr "Sletta ikkje verket."
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr "Du er i ferd med å sletta ein annan brukar sine verk. Trå varsamt."
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr "Du fjerna fila frå samlinga."
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr "Fila var ikkje fjerna fordi du ikkje var sikker."
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr "Du er i ferd med å fjerna ei fil frå ein annan brukar si samling. Trå varsamt."
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr "Samlinga «%s» sletta"
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr "Sletta ikkje samlinga."
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr "Du er i ferd med å sletta ein annan brukar si samling. Trå varsamt."
diff --git a/mediagoblin/i18n/pl/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/pl/LC_MESSAGES/mediagoblin.mo
index ea905b61..8b318329 100644
--- a/mediagoblin/i18n/pl/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/pl/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/pl/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/pl/LC_MESSAGES/mediagoblin.po
index 9edf8e2b..78ab219a 100644
--- a/mediagoblin/i18n/pl/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/pl/LC_MESSAGES/mediagoblin.po
@@ -3,15 +3,16 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
-# Daniel Koć <kocio@aster.pl>, 2012.
+# Daniel Koć <kocio@aster.pl>, 2012
+# Sergiusz Pawlowicz <transifex@pawlowicz.name>, 2013
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-05 00:04+0000\n"
-"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-05-28 13:51+0000\n"
+"Last-Translator: Sergiusz Pawlowicz <transifex@pawlowicz.name>\n"
+"Language-Team: Polish (http://www.transifex.com/projects/p/mediagoblin/language/pl/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -19,34 +20,39 @@ msgstr ""
"Language: pl\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
+#: mediagoblin/auth/forms.py:26
msgid "Username"
msgstr "Użytkownik"
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
msgid "Password"
msgstr "Hasło"
-#: mediagoblin/auth/forms.py:60
+#: mediagoblin/auth/forms.py:34
msgid "Email address"
msgstr "Adres e-mail"
-#: mediagoblin/auth/forms.py:78
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
+msgstr "Nazwa konta lub adres poczty elektronicznej"
+
+#: mediagoblin/auth/forms.py:52
msgid "Username or email"
msgstr "Użytkownik lub adres e-mail"
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr "Nieprawidłowa nazwa konta albo niewłaściwy adres poczty elektronicznej."
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr "Niniejsze pole nie jest przeznaczone na adres poczty elektronicznej."
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr "Niniejsze pole wymaga podania adresu poczty elektronicznej."
+
#: mediagoblin/auth/views.py:54
msgid "Sorry, registration is disabled on this instance."
msgstr "Niestety rejestracja w tym serwisie jest wyłączona."
@@ -59,54 +65,54 @@ msgstr "Niestety użytkownik o takiej nazwie już istnieje."
msgid "Sorry, a user with that email address already exists."
msgstr "Niestety użytkownik z tym adresem e-mail już istnieje."
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr "Twój adres e-mail został zweryfikowany. Możesz się teraz zalogować, wypełnić opis swojego profilu i wysyłać grafiki!"
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr "Nieprawidłowy klucz weryfikacji lub identyfikator użytkownika."
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr "Musisz się zalogować żebyśmy wiedzieli do kogo wysłać e-mail!"
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr "Twój adres e-mail już został zweryfikowany!"
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr "Wyślij ponownie e-mail weryfikujący."
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
-msgstr ""
+msgstr "Jeśli ten adres poczty elektronicznej istnieje (uwzględniając wielkość liter!), wysłano na niego list z instrukcją, w jaki sposób możesz zmienić swoje hasło."
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
-msgstr ""
+msgstr "Nie potrafię znaleźć nikogo o tej nazwie użytkownika."
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
msgstr "Wysłano e-mail z instrukcjami jak zmienić hasło."
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr "Nie udało się wysłać e-maila w celu odzyskania hasła, ponieważ twoje konto jest nieaktywne lub twój adres e-mail nie został zweryfikowany."
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
-msgstr "Teraz możesz się zalogować używając nowe hasło."
+msgstr "Teraz możesz się zalogować używając nowego hasła."
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -117,7 +123,7 @@ msgid "Description of this work"
msgstr "Opis tej pracy"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -133,11 +139,11 @@ msgstr "Znaczniki"
msgid "Separate tags by commas."
msgstr "Rozdzielaj znaczniki przecinkami."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "Slug"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "Slug nie może być pusty"
@@ -165,45 +171,45 @@ msgid "This address contains errors"
msgstr "Ten adres zawiera błędy"
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr "Stare hasło"
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr "Wprowadź swoje stare hasło aby udowodnić, że to twoje konto."
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr "Nowe hasło"
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
-msgstr ""
+msgstr "Ulubiona licencja"
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
-msgstr ""
+msgstr "To będzie twoja domyślna licencja dla wgrywanych mediów."
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr "Powiadamiaj mnie e-mailem o komentarzach do moich mediów"
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr "Tytuł nie może być pusty"
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr "Opis tej kolekcji"
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr "Część adresu zawierająca tytuł. Zwykle nie musisz tego zmieniać."
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr "Stare hasło"
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr "Wprowadź swoje stare hasło aby udowodnić, że to twoje konto."
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr "Nowe hasło"
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr "Adres z tym slugiem dla tego użytkownika już istnieje."
@@ -214,11 +220,11 @@ msgstr "Edytujesz media innego użytkownika. Zachowaj ostrożność."
#: mediagoblin/edit/views.py:155
#, python-format
msgid "You added the attachment %s!"
-msgstr ""
+msgstr "Dodałeś załącznik %s!"
#: mediagoblin/edit/views.py:182
msgid "You can only edit your own profile."
-msgstr ""
+msgstr "Masz możliwość edycji tylko własnego profilu."
#: mediagoblin/edit/views.py:188
msgid "You are editing a user's profile. Proceed with caution."
@@ -228,57 +234,80 @@ msgstr "Edytujesz profil innego użytkownika. Zachowaj ostrożność."
msgid "Profile changes saved"
msgstr "Zapisano zmiany profilu"
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr "Nieprawidłowe hasło"
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr "Zapisano ustawienia konta"
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
-msgstr ""
+msgstr "Musisz potwierdzić, że chcesz skasować swoje konto."
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr "Kolekcja \"%s\" już istnieje!"
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr "Kolekcja tego użytkownika z takim slugiem już istnieje."
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr "Edytujesz kolekcję innego użytkownika. Zachowaj ostrożność."
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr "Nieprawidłowe hasło"
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr "Twoje hasło zostało zmienione"
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr "Nie można podlinkować motywu... nie wybrano motywu\n"
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr "Brak katalogu danych dla tego motywu\n"
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr "Znaleziono stary odnośnik symboliczny do katalogu; usunięto.\n"
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr "Nie mogę zrobić odnośnika \"%s\": %s istnieje i nie jest odnośnikiem\n"
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr "Opuszczam \"%s\"; już jest gotowe.\n"
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr "Znaleziono stary odnośnik dla \"%s\"; usuwam.\n"
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
"or somesuch.<br/>Make sure to permit the settings of cookies for this "
"domain."
-msgstr ""
+msgstr "Ciasteczko CSFR nie jest dostępne. Najprawdopodobniej stosujesz jakąś formę blokowania ciasteczek.<br/>Upewnij się, że nasz serwer może zakładać ciasteczka w twojej przeglądarce."
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr "NIestety, nie obsługujemy tego typu plików :-("
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr "nie dało się uruchomić unoconv, sprawdź log"
+
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr "Konwersja wideo nie powiodła się"
@@ -315,7 +344,7 @@ msgstr "Opis"
msgid ""
"This will be visible to users allowing your\n"
" application to authenticate as them."
-msgstr ""
+msgstr "To będzie widoczne dla użytkowników, pozwalając⎠twojej aplikacji uwierzytelniać się jako oni."
#: mediagoblin/plugins/oauth/forms.py:40
msgid "Type"
@@ -345,17 +374,17 @@ msgstr "Przekierowanie URI dla aplikacji, to pole\n jest <strong>wyma
msgid "This field is required for public clients"
msgstr "To pole jest wymagane dla klientów publicznych"
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
msgstr "Klient {0} został zarejestrowany!"
#: mediagoblin/plugins/oauth/templates/oauth/client/connections.html:22
msgid "OAuth client connections"
-msgstr ""
+msgstr "Połączenia do OAuth"
#: mediagoblin/plugins/oauth/templates/oauth/client/list.html:22
msgid "Your OAuth clients"
-msgstr ""
+msgstr "Twoi klienci OAuth"
#: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
@@ -364,7 +393,7 @@ msgstr ""
msgid "Add"
msgstr "Dodaj"
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr "Niewłaściwy plik dla tego rodzaju mediów."
@@ -372,45 +401,45 @@ msgstr "Niewłaściwy plik dla tego rodzaju mediów."
msgid "File"
msgstr "Plik"
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr "Musisz podać plik."
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr "Hura! Wysłano!"
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr "Kolekcja \"%s\" została dodana!"
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr "Zweryfikuj swój adres e-mail!"
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
-msgstr ""
+msgstr "wyloguj siÄ™"
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr "Zaloguj siÄ™"
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
-msgstr ""
+msgstr "konto <a href=\"%(user_url)s\">%(user_name)s</a>"
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr "Zmień ustawienia konta"
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -418,72 +447,25 @@ msgstr "Zmień ustawienia konta"
msgid "Media processing panel"
msgstr "Panel przetwarzania mediów"
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
-msgstr ""
+msgstr "Wyloguj siÄ™"
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr "Dodaj media"
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr "Opublikowane na licencji <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. Dostępny jest <a href=\"%(source_link)s\">kod źródłowy</a>."
+msgstr "Utwórz nową kolekcję"
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr "Odkrywaj"
+msgstr "Grafika zestresowanego goblina"
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr "Cześć, witaj na stronie MediaGoblin!"
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr "Ten serwis działa w oparciu o <a href=\"http://mediagoblin.org\">MediaGoblin</a>, świetne oprogramowanie do publikowania mediów."
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr "Aby dodawać swoje pliki, komentować i wykonywać inne czynności, możesz się zalogować na swoje konto MediaGoblin."
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr "Jeszcze go nie masz? To proste!"
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">Utwórz konto w tym serwisie</a>\n lub\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">załóż własny serwis MediaGoblin</a>"
-
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr "Najnowsze media"
@@ -589,6 +571,53 @@ msgid ""
"%(verification_url)s"
msgstr "Cześć %(username)s,\n\naby aktywować twoje konto GNU MediaGoblin, otwórz następującą stronę w swojej przeglądarce:\n\n%(verification_url)s"
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr "Napędzane przez oprogramowanie <a href=\"http://mediagoblin.org/\" title='w wersji %(version)s'>MediaGoblin</a>, będące częścią projektu <a href=\"http://gnu.org/\">GNU</a>."
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr "Opublikowane na licencji <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. Dostępny jest <a href=\"%(source_link)s\">kod źródłowy</a>."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr "Odkrywaj"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "Cześć, witaj na stronie MediaGoblin!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr "Ten serwis działa w oparciu o <a href=\"http://mediagoblin.org\">MediaGoblin</a>, świetne oprogramowanie do publikowania mediów."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr "Aby dodawać swoje pliki, komentować i wykonywać inne czynności, możesz się zalogować na swoje konto MediaGoblin."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr "Jeszcze go nie masz? To proste!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">Załóż konto na tym serwerze</a>\n albo\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Uruchom MediaGoblin na swoim własnym serwerze</a>"
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -601,13 +630,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr "Edycja załączników do %(media_title)s"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
msgstr "Załączniki"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
msgstr "Dodaj załącznik"
@@ -624,23 +653,33 @@ msgstr "Anuluj"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr "Zapisz zmiany"
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr "Zmieniam hasło użytkownika %(username)s"
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr "Zachowaj"
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
-msgstr ""
+msgstr "Czy naprawdę skasować użytkownika '%(user_name)s' oraz usunąć wszystkie jego pliki i komentarze?"
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:35
msgid "Yes, really delete my account"
-msgstr ""
+msgstr "Tak, naprawdę chcę skasować swoje konto"
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "Usuń na stałe"
@@ -657,9 +696,13 @@ msgstr "Edytowanie %(media_title)s"
msgid "Changing %(username)s's account settings"
msgstr "Zmiana ustawień konta %(username)s"
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr "Zmień swoje hasło."
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
-msgstr ""
+msgstr "Usuń moje konto"
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29
#, python-format
@@ -682,6 +725,7 @@ msgstr "Media ze znacznikami: %(tag_name)s"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -706,6 +750,7 @@ msgid ""
msgstr "Proszę pobrać przeglądarkę, która obsługuje \n\tdźwięk w HTML5, pod adresem <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!"
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr "Oryginalny plik"
@@ -714,6 +759,7 @@ msgstr "Oryginalny plik"
msgid "WebM file (Vorbis codec)"
msgstr "plik WebM (kodek Vorbis)"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -724,59 +770,63 @@ msgstr "plik WebM (kodek Vorbis)"
msgid "Image for %(media_title)s"
msgstr "Grafika dla %(media_title)s"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr "Plik PDF"
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
-msgstr ""
+msgstr "Obróć"
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113
msgid "Perspective"
-msgstr ""
+msgstr "Perspektywa"
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117
msgid "Front"
-msgstr ""
+msgstr "PoczÄ…tek"
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121
msgid "Top"
-msgstr ""
+msgstr "Góra"
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125
msgid "Side"
-msgstr ""
+msgstr "Krawędź"
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131
msgid "WebGL"
-msgstr ""
+msgstr "WebGL"
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138
msgid "Download model"
-msgstr ""
+msgstr "Pobierz model"
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146
msgid "File Format"
-msgstr ""
+msgstr "Format pliku"
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148
msgid "Object Height"
-msgstr ""
+msgstr "Wysokość obiektu"
#: mediagoblin/templates/mediagoblin/media_displays/video.html:44
msgid ""
"Sorry, this video will not work because\n"
" your web browser does not support HTML5 \n"
" video."
-msgstr ""
+msgstr "Niestety ten materiaÅ‚ nie bÄ™dzie widocznyâŽ, ponieważ twoja przeglÄ…darka nie⎠osbÅ‚uguje formatu HTML5."
#: mediagoblin/templates/mediagoblin/media_displays/video.html:47
msgid ""
"You can get a modern web browser that \n"
" can play this video at <a href=\"http://getfirefox.com\">\n"
" http://getfirefox.com</a>!"
-msgstr ""
+msgstr "Możesz pobrać porządną przeglądarkę, która jest w stanie odtworzyć ten materiał filmowy, ze strony <a href=\"http://getfirefox.com/\">⎠http://getfirefox.com</a>!"
#: mediagoblin/templates/mediagoblin/media_displays/video.html:69
msgid "WebM file (640p; VP8/Vorbis)"
@@ -822,19 +872,19 @@ msgstr "Na pewno usunąć %(title)s?"
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr "Na pewno usunąć %(media_title)s z %(collection_title)s?"
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr "Usuń"
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:21
#, python-format
msgid "%(username)s's collections"
-msgstr ""
+msgstr "kolekcja użytkownika %(username)s"
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:28
#, python-format
msgid "<a href=\"%(user_url)s\">%(username)s</a>'s collections"
-msgstr ""
+msgstr "kolekcje użytkownika <a href=\"%(user_url)s\">%(username)s</a>"
#: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19
#, python-format
@@ -853,7 +903,7 @@ msgstr "Media użytkownika %(username)s"
msgid ""
"<a href=\"%(user_url)s\">%(username)s</a>'s media with tag <a "
"href=\"%(tag_url)s\">%(tag)s</a>"
-msgstr ""
+msgstr "pliki użytkownika <a href=\"%(user_url)s\">%(username)s</a> z tagiem <a href=\"%(tag_url)s\">%(tag)s</a>"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48
#, python-format
@@ -865,30 +915,34 @@ msgstr "media użytkownika <a href=\"%(user_url)s\">%(username)s</a>"
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr "■Przeglądanie mediów użytkownika <a href=\"%(user_url)s\">%(username)s</a>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
msgstr "Dodaj komentarz"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
msgstr "Dodaj komentarz"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
-msgstr "na"
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
-msgstr "<h3>Dodane</h3>\n <p>%(date)s</p>"
+msgid "%(formatted_time)s ago"
+msgstr "%(formatted_time)s temu"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr "Dodano"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
+msgstr "Utworzono"
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40
#, python-format
msgid "Add “%(media_title)s†to a collection"
-msgstr ""
+msgstr "Dodaj “%(media_title)s†do kolekcji"
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:54
msgid "+"
@@ -967,7 +1021,7 @@ msgstr "Ten użytkownik nie wypełnił (jeszcze) opisu swojego profilu."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:124
msgid "Browse collections"
-msgstr ""
+msgstr "PrzeglÄ…daj kolekcje"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:137
#, python-format
@@ -988,15 +1042,15 @@ msgstr "Tu nie ma jeszcze żadnych mediów..."
#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
msgid "(remove)"
-msgstr ""
+msgstr "(usuń)"
#: mediagoblin/templates/mediagoblin/utils/collections.html:21
msgid "Collected in"
-msgstr ""
+msgstr "Znajduje siÄ™ w kolekcji "
#: mediagoblin/templates/mediagoblin/utils/collections.html:40
msgid "Add to a collection"
-msgstr ""
+msgstr "Dodaj do kolekcji"
#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
#: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:21
@@ -1038,7 +1092,7 @@ msgstr "starsze"
msgid "Tagged with"
msgstr "Znaczniki:"
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr "Nie udało się odczytać pliku grafiki."
@@ -1048,29 +1102,53 @@ msgstr "Ups!"
#: mediagoblin/tools/response.py:36
msgid "An error occured"
-msgstr ""
+msgstr "Wystąpił błąd"
#: mediagoblin/tools/response.py:51
msgid "Operation not allowed"
-msgstr ""
+msgstr "Operacja niedozwolona"
#: mediagoblin/tools/response.py:52
msgid ""
"Sorry Dave, I can't let you do that!</p><p>You have tried to perform a "
"function that you are not allowed to. Have you been trying to delete all "
"user accounts again?"
-msgstr ""
+msgstr "Misiaczku, nie możesz tego uczynić!</p><p>Próbowałeś wykonać działanie, do którego nie masz uprawnień. Czy naprawdę chciałeś skasować znowu wszystkie konta?"
#: mediagoblin/tools/response.py:60
msgid ""
"There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure"
" the address is correct, maybe the page you're looking for has been moved or"
" deleted."
-msgstr ""
+msgstr "Wygląda na to, że nic tutaj nie ma!</p><p>Jeśli jesteś pewny, że adres jest prawidłowy, być może strona została skasowana lub przeniesiona."
+
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr "rok"
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr "miesiÄ…c"
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr "tydzień"
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr "dzień"
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr "godzina"
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr "minuta"
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
-msgstr ""
+msgstr "Komentarz"
#: mediagoblin/user_pages/forms.py:25
msgid ""
@@ -1089,7 +1167,7 @@ msgstr "Na pewno chcę usunąć ten element z kolekcji"
#: mediagoblin/user_pages/forms.py:39
msgid "Collection"
-msgstr ""
+msgstr "Kolekcja"
#: mediagoblin/user_pages/forms.py:40
msgid "-- Select --"
@@ -1099,73 +1177,77 @@ msgstr "-- wybierz --"
msgid "Include a note"
msgstr "Dodaj notatkÄ™"
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
msgstr "komentarze do twojego wpisu"
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr "Komentowanie jest wyłączone."
+
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr "Ups, twój komentarz nie zawierał treści."
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr "Twój komentarz został opublikowany!"
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
msgstr "Sprawdź swoje wpisy i spróbuj ponownie."
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr "Musisz wybrać lub dodać kolekcję"
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr "\"%s\" już obecne w kolekcji \"%s\""
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr "\"%s\" dodano do kolekcji \"%s\""
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr "Media zostały usunięte."
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr "Media nie zostały usunięte ponieważ nie potwierdziłeś, że jesteś pewien."
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr "Za chwilę usuniesz media innego użytkownika. Zachowaj ostrożność."
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr "Element został usunięty z kolekcji."
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr "Ten element nie został usunięty, ponieważ nie zaznaczono, że jesteś pewien."
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr "Zamierzasz usunąć element z kolekcji innego użytkownika. Zachowaj ostrożność."
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr "Usunięto kolekcję \"%s\""
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr "Ta kolekcja nie została usunięta, ponieważ nie zaznaczono, że jesteś pewien."
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr "Zamierzasz usunąć kolekcję innego użytkownika. Zachowaj ostrożność."
diff --git a/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.mo
index af50e027..5e83a7f2 100644
--- a/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.po
index 3b2ed203..fecb844c 100644
--- a/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.po
@@ -3,16 +3,17 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
-# Rafael Ferreira <rafael.f.f1@gmail.com>, 2013.
-# <snd.noise@gmail.com>, 2011.
-# ufa <ufa@technotroll.org>, 2011.
-# Vinicius SM <viniciussm@rocketmail.com>, 2013.
+# osc <snd.noise@gmail.com>, 2013
+# Rafael Ferreira <rafael.f.f1@gmail.com>, 2013
+# osc <snd.noise@gmail.com>, 2011
+# ufa <ufa@technotroll.org>, 2011
+# Canopus <viniciussm@rocketmail.com>, 2013
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-05 00:04+0000\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-05-27 18:54+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/mediagoblin/language/pt_BR/)\n"
"MIME-Version: 1.0\n"
@@ -22,34 +23,39 @@ msgstr ""
"Language: pt_BR\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
-msgstr "Nome de usuário ou email inválido."
-
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
-msgstr "Este campo não aceita endereços de email."
-
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
-msgstr "Este campo requer um endereço de email."
-
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
+#: mediagoblin/auth/forms.py:26
msgid "Username"
msgstr "Nome de Usuário"
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
msgid "Password"
msgstr "Senha"
-#: mediagoblin/auth/forms.py:60
+#: mediagoblin/auth/forms.py:34
msgid "Email address"
msgstr "Endereço de email"
-#: mediagoblin/auth/forms.py:78
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
+msgstr ""
+
+#: mediagoblin/auth/forms.py:52
msgid "Username or email"
msgstr "Nome de usuário ou email"
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr "Nome de usuário ou email inválido."
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr "Este campo não aceita endereços de email."
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr "Este campo requer um endereço de email."
+
#: mediagoblin/auth/views.py:54
msgid "Sorry, registration is disabled on this instance."
msgstr "Desculpa, o registro está desativado neste momento."
@@ -62,54 +68,54 @@ msgstr "Desculpe, um usuário com este nome já existe."
msgid "Sorry, a user with that email address already exists."
msgstr "Desculpe, um usuário com esse email já está cadastrado"
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr "O seu endereço de e-mail foi verificado. Você pode agora fazer login, editar seu perfil, e enviar imagens!"
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr "A chave de verificação ou nome usuário estão incorretos."
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr "Você precisa entrar primeiro para sabermos para quem mandar o email!"
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr "Você já verificou seu email!"
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr "O email de verificação foi enviado novamente."
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
-msgstr ""
+msgstr "Se esse endereço de email (sensível a maiúsculo/minúsculo!) estiver registrado, um email será enviado com instruções para alterar sua senha."
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
msgstr "Não foi possível encontrar alguém com esse nome de usuário."
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
msgstr "Um email foi enviado com instruções para trocar sua senha."
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr "Não foi possível enviar o email de recuperação de senha, pois seu nome de usuário está inativo ou o email da sua conta não foi confirmado."
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
msgstr "Agora você pode entrar usando sua nova senha."
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -120,7 +126,7 @@ msgid "Description of this work"
msgstr "Descrição desse trabalho"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -136,11 +142,11 @@ msgstr "Etiquetas"
msgid "Separate tags by commas."
msgstr "Separe as etiquetas com vírgulas."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "Arquivo"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "O arquivo não pode estar vazio"
@@ -168,45 +174,45 @@ msgid "This address contains errors"
msgstr "Este endereço contém erros"
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr "Senha antiga"
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr "Digite sua senha antiga para provar que esta conta é sua."
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr "Nova senha"
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
msgstr "Licença preferida"
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
msgstr "Esta será sua licença padrão nos formulários de envio."
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr "Me enviar um email quando outras pessoas comentarem em minhas mídias"
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr "O título não pode ficar vazio"
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr "Descrição desta coleção"
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr "A parte do título do endereço dessa coleção. Geralmente você não precisa mudar isso."
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr "Senha antiga"
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr "Digite sua senha antiga para provar que esta conta é sua."
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr "Nova senha"
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr "Uma entrada com esse arquivo já existe para esse usuário"
@@ -231,44 +237,63 @@ msgstr "Você está editando um perfil de usuário. Tenha cuidado."
msgid "Profile changes saved"
msgstr "As mudanças no perfil foram salvas"
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr "Senha errada"
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr "As mudanças na conta foram salvas"
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
msgstr "Você precisa confirmar a exclusão da sua conta."
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr "Você já tem uma coleção chamada \"%s\"!"
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr "Já existe uma coleção com este arquivo para este usuário."
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr "Você está editando a coleção de um outro usuário. Prossiga com cuidado."
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr "Senha errada"
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr "Não é possível fazer link de tema... nenhum tema definido\n"
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr ""
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr ""
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
@@ -276,12 +301,16 @@ msgid ""
"domain."
msgstr "Cookie CSFR não está presente. Isso é provavelmente o resultado de um bloqueador de cookies ou algo do tipo.<br/>Tenha certeza de autorizar este domínio a configurar cookies."
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr "Desculpe, não tenho suporte a este tipo de arquivo :("
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr ""
+
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr "Conversão do vídeo falhou"
@@ -348,7 +377,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr "Este campo é necessário para clientes públicos"
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
msgstr "O cliente {0} foi registrado!"
@@ -367,7 +396,7 @@ msgstr "Seus clientes OAuth"
msgid "Add"
msgstr "Adicionar"
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr "Arquivo inválido para esse tipo de mídia"
@@ -375,45 +404,45 @@ msgstr "Arquivo inválido para esse tipo de mídia"
msgid "File"
msgstr "Arquivo"
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr "Você deve fornecer um arquivo."
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr "Eba! Enviado!"
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr "Coleção \"%s\" adicionada!"
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr "Verifique seu email!"
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
msgstr "sair"
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr "Entrar"
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr "Conta de <a href=\"%(user_url)s\">%(user_name)s</a>"
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr "Mudar configurações da conta"
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -421,72 +450,25 @@ msgstr "Mudar configurações da conta"
msgid "Media processing panel"
msgstr "Painel de processamento de mídia"
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
-msgstr ""
+msgstr "Sair"
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr "Adicionar mídia"
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
msgstr "Criar nova coleção"
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr "Lançado sob a <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Código fonte</a> disponível."
-
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr "Explorar"
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr "Olá, bem-vindo a este site MediaGoblin."
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr "Este site roda o <a href=\"http://mediagoblin.org\">MediaGoblin</a>, um programa excelente para hospedar, gerenciar e compartilhar mídia."
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr "Para adicionar sua própria mídia, publicar comentários e mais outras coisas, você pode entrar com sua conta MediaGoblin."
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr " Ainda não tem uma conta? É facil!"
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">Criar uma conta neste site</a>\nou\n<a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Configurar MediaGoblin em seu próprio servidor</a>"
+msgstr "Imagem do goblin se estressando"
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr "Mídia mais recente"
@@ -592,6 +574,53 @@ msgid ""
"%(verification_url)s"
msgstr "Olá %(username)s,\n\nPara ativar sua conta GNU MediaGoblin, visite este endereço no seu navegador:\n\n%(verification_url)s"
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr "Fornecido pelo <a href=\"http://mediagoblin.org/\" title='Version %(version)s'>MediaGoblin</a>, um projeto <a href=\"http://gnu.org/\">GNU</a>."
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr "Lançado sob a <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Código fonte</a> disponível."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr "Explorar"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "Olá, bem-vindo a este site MediaGoblin."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr "Este site roda o <a href=\"http://mediagoblin.org\">MediaGoblin</a>, um programa excelente para hospedar, gerenciar e compartilhar mídia."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr "Para adicionar sua própria mídia, publicar comentários e mais outras coisas, você pode entrar com sua conta MediaGoblin."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr " Ainda não tem uma conta? É facil!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -604,13 +633,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr "Editando os anexos de %(media_title)s"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
msgstr "Anexos"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
msgstr "Adicionar anexo"
@@ -627,12 +656,22 @@ msgstr "Cancelar"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr "Salvar mudanças"
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
@@ -643,7 +682,7 @@ msgid "Yes, really delete my account"
msgstr "Sim, realmente deletar minha conta"
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "Deletar permanentemente"
@@ -660,7 +699,11 @@ msgstr "Editando %(media_title)s"
msgid "Changing %(username)s's account settings"
msgstr "Alterando as configurações da conta de %(username)s"
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
msgstr "Deletar minha conta"
@@ -685,6 +728,7 @@ msgstr "Etiquetas desta mídia: %(tag_name)s"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -709,6 +753,7 @@ msgid ""
msgstr "Você pode obter um navegador moderno\n »capaz de reproduzir o áudio em <a href=\"http://getfirefox.com\">\n » http://getfirefox.com</a>!"
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr "Arquivo original"
@@ -717,6 +762,7 @@ msgstr "Arquivo original"
msgid "WebM file (Vorbis codec)"
msgstr "Arquivo WebM (codec Vorbis)"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -727,6 +773,10 @@ msgstr "Arquivo WebM (codec Vorbis)"
msgid "Image for %(media_title)s"
msgstr "Imagem para %(media_title)s"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
msgstr "Alternar Rotação"
@@ -825,7 +875,7 @@ msgstr "Realmente apagar %(title)s ?"
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr "Realmente remover %(media_title)s de %(collection_title)s?"
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr "Apagar"
@@ -856,7 +906,7 @@ msgstr "Mídia de %(username)s's"
msgid ""
"<a href=\"%(user_url)s\">%(username)s</a>'s media with tag <a "
"href=\"%(tag_url)s\">%(tag)s</a>"
-msgstr ""
+msgstr "Mídias de <a href=\"%(user_url)s\">%(username)s</a> com a etiqueta <a href=\"%(tag_url)s\">%(tag)s</a>"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48
#, python-format
@@ -868,24 +918,28 @@ msgstr "Mídia de <a href=\"%(user_url)s\"> %(username)s </a> "
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr "■Vendo mídia de <a href=\"%(user_url)s\">%(username)s</a>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
msgstr "Adicionar um comentário"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
msgstr "Adicionar este comentário"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
-msgstr "em"
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
-msgstr "<h3>Adicionado em</h3>\n<p>%(date)s</p>"
+msgid "%(formatted_time)s ago"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
+msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40
@@ -987,7 +1041,7 @@ msgstr "Aqui é onde sua mídia vai aparecer, mas parece que você não adiciono
#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84
#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70
msgid "There doesn't seem to be any media here yet..."
-msgstr "Aparentemente não há nenhuma mídia aqui ainda..."
+msgstr "Parece que ainda não há nenhuma mídia por aqui..."
#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
msgid "(remove)"
@@ -999,7 +1053,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/utils/collections.html:40
msgid "Add to a collection"
-msgstr ""
+msgstr "Adicionar a uma coleção"
#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
#: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:21
@@ -1041,7 +1095,7 @@ msgstr "mais antiga"
msgid "Tagged with"
msgstr "Etiquetas"
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr "Não foi possível ler o arquivo de imagem."
@@ -1071,6 +1125,30 @@ msgid ""
" deleted."
msgstr "Parece que não há uma página com este endereço. Desculpe!</p><p>Se você tem certeza que este endereço está correto, talvez a página que esteja procurando tenha sido movida ou deletada."
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr ""
+
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
msgstr "Comentário"
@@ -1096,79 +1174,83 @@ msgstr "Coleção"
#: mediagoblin/user_pages/forms.py:40
msgid "-- Select --"
-msgstr ""
+msgstr "-- Selecionar --"
#: mediagoblin/user_pages/forms.py:42
msgid "Include a note"
msgstr "Incluir uma nota"
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
msgstr "comentou na sua publicação"
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr "Ops, seu comentário estava vazio."
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr "Seu comentário foi postado!"
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
-msgstr ""
+msgstr "Por favor, verifique suas entradas e tente novamente."
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr "Você deve selecionar ou adicionar uma coleção"
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr "\"%s\" já está na coleção \"%s\""
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr "\"%s\" adicionado à coleção \"%s\""
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr "Você deletou a mídia."
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr "A mídia não foi apagada porque você não marcou que tinha certeza."
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr "Você vai apagar uma mídia de outro usuário. Tenha cuidado."
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr "Você deletou o item da coleção."
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr "O item não foi apagado porque você não marcou que tinha certeza."
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr "Você está prestes a remover um item da coleção de um outro usuário. Prossiga com cuidado."
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr "Você deletou a coleção \"%s\""
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr "A coleção não foi apagada porque você não marcou que tinha certeza."
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr "Você está prestes a deletar a coleção de um outro usuário. Prossiga com cuidado."
diff --git a/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.mo
index 62cbf028..8cfdf339 100644
--- a/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.po
index da585d5c..af2d94d6 100644
--- a/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.po
@@ -3,14 +3,14 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
-# <gapop@hotmail.com>, 2011.
-# George Pop <gapop@hotmail.com>, 2011-2013.
+# George Pop <gapop@hotmail.com>, 2011
+# George Pop <gapop@hotmail.com>, 2011-2013
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-10 04:13+0000\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-05-27 20:40+0000\n"
"Last-Translator: George Pop <gapop@hotmail.com>\n"
"Language-Team: Romanian (http://www.transifex.com/projects/p/mediagoblin/language/ro/)\n"
"MIME-Version: 1.0\n"
@@ -20,34 +20,39 @@ msgstr ""
"Language: ro\n"
"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
-msgstr "Nume de utilizator sau adresă de e-mail nevalidă."
-
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
-msgstr "Această rubrică nu este pentru adrese de e-mail."
-
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
-msgstr "Această rubrică trebuie completată cu o adresă de e-mail."
-
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
+#: mediagoblin/auth/forms.py:26
msgid "Username"
msgstr "Nume de utilizator"
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
msgid "Password"
msgstr "Parolă"
-#: mediagoblin/auth/forms.py:60
+#: mediagoblin/auth/forms.py:34
msgid "Email address"
msgstr "Adresa de e-mail"
-#: mediagoblin/auth/forms.py:78
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
+msgstr "Numele de utilizator sau adresa de e-mail"
+
+#: mediagoblin/auth/forms.py:52
msgid "Username or email"
msgstr "Numele de utilizator sau adresa de e-mail"
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr "Nume de utilizator sau adresă de e-mail nevalidă."
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr "Această rubrică nu este pentru adrese de e-mail."
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr "Această rubrică trebuie completată cu o adresă de e-mail."
+
#: mediagoblin/auth/views.py:54
msgid "Sorry, registration is disabled on this instance."
msgstr "Ne pare rău, dar înscrierile sunt dezactivate pe acest server."
@@ -60,54 +65,54 @@ msgstr "Ne pare rău, există deja un utilizator cu același nume."
msgid "Sorry, a user with that email address already exists."
msgstr "Există deja un utilizator înregistrat cu această adresă de e-mail."
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr "Adresa ta de e-mail a fost verificată. Poți să te autentifici, să îți completezi profilul și să trimiți imagini!"
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr "Cheie de verificare sau user ID incorect."
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr "Trebuie să fii autentificat ca să știm cui să trimitem mesajul!"
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr "Adresa ta de e-mail a fost deja verificată!"
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr "E-mail-ul de verificare a fost retrimis."
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
msgstr "Dacă adresa de e-mail este în baza noastră de date, atunci se va trimite imediat un mesaj cu instrucțiuni pentru schimbarea parolei. Țineți cont de litere mari / litere mici la introducerea adresei!"
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
msgstr "Nu există nimeni cu acest nume de utilizator."
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
msgstr "S-a trimis un e-mail cu instrucțiuni pentru schimbarea parolei."
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr "E-mailul pentru recuperarea parolei nu a putut fi trimis deoarece contul tău e inactiv sau adresa ta de e-mail nu a fost verificată."
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
msgstr "Acum te poți autentifica cu noua parolă."
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -118,7 +123,7 @@ msgid "Description of this work"
msgstr "Descrierea acestui fișier"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -134,11 +139,11 @@ msgstr "Cuvinte-cheie"
msgid "Separate tags by commas."
msgstr "Desparte cuvintele-cheie prin virgulă."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "Identificator"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "Identificatorul nu poate să lipsească"
@@ -166,45 +171,45 @@ msgid "This address contains errors"
msgstr "Această adresă prezintă erori"
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr "Vechea parolă"
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr "Introdu vechea parolă pentru a demonstra că ești titularul acestui cont."
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr "Noua parolă"
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
msgstr "Licența preferată"
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
msgstr "Aceasta va fi licența implicită pe formularele de upload."
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr "Trimite-mi un e-mail când alții comentează fișierele mele"
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr "Titlul nu poate să fie gol"
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr "Descriere pentru această colecție"
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr "Partea din adresa acestei colecții care corespunde titlului. De regulă nu e necesar să faci o modificare."
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr "Vechea parolă"
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr "Introdu vechea parolă pentru a demonstra că ești titularul acestui cont."
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr "Noua parolă"
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr "Există deja un entry cu același identificator pentru acest utilizator."
@@ -229,44 +234,63 @@ msgstr "Editezi profilul unui utilizator. Se recomandă prudență."
msgid "Profile changes saved"
msgstr "Modificările profilului au fost salvate"
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr "Parolă incorectă"
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr "Setările pentru acest cont au fost salvate"
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
msgstr "Trebuie să confirmi ștergerea contului tău."
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr "Ai deja o colecție numită \"%s\"!"
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr "O colecție cu același slug există deja pentru acest utilizator."
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr "Lucrezi pe colecția unui alt utilizator. Se recomandă prudență."
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr "Parolă incorectă"
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr "Parola a fost schimbată cu succes"
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr "Tema nu poate fi atașată... nu există o temă selectată\n"
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr "Nu există un folder de elemente pentru această temă\n"
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr "A fost însă găsit un symlink către vechiul folder; s-a șters.\n"
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr "Nu s-a putut crea link pentru \"%s\": %s există deja și nu este symlink\n"
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr "S-a omis \"%s\"; configurat deja.\n"
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr "Există deja un link pentru \"%s\"; va fi șters.\n"
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
@@ -274,12 +298,16 @@ msgid ""
"domain."
msgstr "Lipsește cookie-ul CSRF. Probabil că blocați cookie-urile.<br/>Asigurați-vă că există permisiunea setării cookie-urilor pentru acest domeniu."
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr "Scuze, nu recunosc acest tip de fișier :("
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr "unoconv nu poate fi executat; verificați log-ul"
+
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr "Transcodarea video a eșuat"
@@ -346,7 +374,7 @@ msgstr "URI-ul de redirectare pentru aplicații, această rubrică\n
msgid "This field is required for public clients"
msgstr "Această rubrică este obligatorie pentru clienții publici"
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
msgstr "Clientul {0} a fost înregistrat!"
@@ -365,7 +393,7 @@ msgstr "Clienții tăi OAuth"
msgid "Add"
msgstr "Adaugă"
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr "Formatul fișierului nu corespunde cu tipul de media selectat."
@@ -373,45 +401,45 @@ msgstr "Formatul fișierului nu corespunde cu tipul de media selectat."
msgid "File"
msgstr "Fișier"
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr "Trebuie să selectezi un fișier."
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr "Ura! Trimis!"
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr "Colecția \"%s\" a fost creată!"
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr "Verifică adresa de e-mail!"
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
msgstr "Ieșire"
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr "Autentificare"
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr "Contul lui <a href=\"%(user_url)s\">%(user_name)s</a>"
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr "Modifică setările contului"
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -419,72 +447,25 @@ msgstr "Modifică setările contului"
msgid "Media processing panel"
msgstr "Panou de procesare media"
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
msgstr "Ieșire"
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr "Trimite fișier"
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
msgstr "Creează colecție nouă"
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr "Construit cu <a href=\"http://mediagoblin.org/\" title='Versiunea %(version)s'>MediaGoblin</a>, un proiect <a href=\"http://gnu.org/\">GNU</a>."
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr "Publicat sub licența <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Codul sursă</a> este disponibil."
-
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
msgstr "Imagine cu un goblin stresat"
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr "Explorează"
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr "Salut, bine ai venit pe acest site MediaGoblin!"
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr "Acest site folosește <a href=\"http://mediagoblin.org\">MediaGoblin</a>, un software excepțional pentru găzduirea fișierelor media."
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr "Pentru a adăuga fișierele tale și pentru a comenta te poți autentifica cu contul tău MediaGoblin."
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr "Încă nu ai unul? E simplu!"
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">Creează un cont pe acest site</a>\n sau\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Instalează MediaGoblin pe serverul tău</a>"
-
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr "Cele mai recente fișiere"
@@ -590,6 +571,53 @@ msgid ""
"%(verification_url)s"
msgstr "Bună, %(username)s,\n\npentru activarea contului tău la GNU MediaGoblin, accesează adresa următoare:\n\n%(verification_url)s"
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr "Construit cu <a href=\"http://mediagoblin.org/\" title='Versiunea %(version)s'>MediaGoblin</a>, un proiect <a href=\"http://gnu.org/\">GNU</a>."
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr "Publicat sub licența <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Codul sursă</a> este disponibil."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr "Explorează"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "Salut, bine ai venit pe acest site MediaGoblin!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr "Acest site folosește <a href=\"http://mediagoblin.org\">MediaGoblin</a>, un software excepțional pentru găzduirea fișierelor media."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr "Pentru a adăuga fișierele tale și pentru a comenta te poți autentifica cu contul tău MediaGoblin."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr "Încă nu ai unul? E simplu!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">Creați un cont pe acest site</a>\n sau\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Instalați MediaGoblin pe serverul dvs.</a>"
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -602,13 +630,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr "Editare anexe la %(media_title)s"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
msgstr "Anexe"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
msgstr "Atașează"
@@ -625,12 +653,22 @@ msgstr "Anulare"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr "Salvează modificările"
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr "Se modifică parola pentru %(username)s"
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr "Salvează"
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
@@ -641,7 +679,7 @@ msgid "Yes, really delete my account"
msgstr "Da, doresc ștergerea contului meu"
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "Șterge definitiv"
@@ -658,7 +696,11 @@ msgstr "Editare %(media_title)s"
msgid "Changing %(username)s's account settings"
msgstr "Se modifică setările contului pentru userul %(username)s"
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr "Modifică parolă."
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
msgstr "Șterge contul meu"
@@ -683,6 +725,7 @@ msgstr "Fișier etichetat cu cuvintele-cheie: %(tag_name)s"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -707,6 +750,7 @@ msgid ""
msgstr "Poți lua un browser modern \n\tcapabil să redea această înregistrare de la <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!"
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr "Fișierul original"
@@ -715,6 +759,7 @@ msgstr "Fișierul original"
msgid "WebM file (Vorbis codec)"
msgstr "Fișier WebM (codec Vorbis)"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -725,6 +770,10 @@ msgstr "Fișier WebM (codec Vorbis)"
msgid "Image for %(media_title)s"
msgstr "Imagine pentru %(media_title)s"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr "Fișier PDF"
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
msgstr "Rotire"
@@ -823,7 +872,7 @@ msgstr "Sigur dorești să ștergi %(title)s?"
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr "Sigur dorești să ștergi %(media_title)s din %(collection_title)s?"
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr "Șterge"
@@ -866,24 +915,28 @@ msgstr "Fișierele media ale lui <a href=\"%(user_url)s\">%(username)s</a>"
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr "<p>■Fișierele media ale lui <a href=\"%(user_url)s\">%(username)s</a></p>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
msgstr "Adaugă un comentariu"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
msgstr "Trimite acest comentariu"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
-msgstr "la"
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
-msgstr "<h3>Adăugat la</h3>\n <p>%(date)s</p>"
+msgid "%(formatted_time)s ago"
+msgstr "în urmă cu %(formatted_time)s"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr "Adăugat"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
+msgstr "Creat"
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40
@@ -1039,7 +1092,7 @@ msgstr "mai vechi"
msgid "Tagged with"
msgstr "Etichetat cu cuvintele-cheie"
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr "Fișierul cu imaginea nu a putut fi citit."
@@ -1069,6 +1122,30 @@ msgid ""
" deleted."
msgstr "Nu există nicio pagină la această adresă.</p><p>Dacă sunteți sigur că adresa este corectă, poate că pagina pe care o căutați a fost mutată sau ștearsă."
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr "anul"
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr "luna"
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr "săptămâna"
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr "ziua"
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr "ora"
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr "minutul"
+
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
msgstr "Comentariu"
@@ -1100,73 +1177,77 @@ msgstr "-- Selectează --"
msgid "Include a note"
msgstr "Adaugă o notiță"
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
msgstr "a făcut un comentariu la postarea ta"
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr "Comentariile sunt dezactivate."
+
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr "Hopa, ai uitat să scrii comentariul."
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr "Comentariul tău a fost trimis!"
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
msgstr "Verifică datele și încearcă din nou."
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr "Trebuie să alegi sau să creezi o colecție"
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr "\"%s\" este deja în colecția \"%s\""
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr "\"%s\" a fost adăugat la colecția \"%s\""
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr "Ai șters acest fișier"
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr "Fișierul nu a fost șters deoarece nu ai confirmat că ești sigur."
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr "Urmează să ștergi fișierele media ale unui alt utilizator. Se recomandă prudență."
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr "Ai șters acest articol din colecție."
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr "Articolul nu a fost șters pentru că nu ai confirmat că ești sigur(ă)."
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr "Urmează să ștergi un articol din colecția unui alt utilizator. Se recomandă prudență."
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr "Ai șters colecția \"%s\""
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr "Colecția nu a fost ștearsă pentru că nu ai confirmat că ești sigur(ă)."
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr "Urmează să ștergi colecția unui alt utilizator. Se recomandă prudență."
diff --git a/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.mo
index 759f5337..ed28ff43 100644
--- a/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.po
index 0dc099ed..d0ff7bdd 100644
--- a/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.po
@@ -3,16 +3,16 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
-# <deletesoftware@yandex.ru>, 2013.
-# <deletesoftware@yandex.ru>, 2011-2012.
+# aleksejrs <deletesoftware@yandex.ru>, 2013
+# aleksejrs <deletesoftware@yandex.ru>, 2011-2012
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-10 15:35+0000\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-06-01 21:08+0000\n"
"Last-Translator: aleksejrs <deletesoftware@yandex.ru>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language-Team: Russian (http://www.transifex.com/projects/p/mediagoblin/language/ru/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -20,34 +20,39 @@ msgstr ""
"Language: ru\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
-msgstr "Это поле не Ð´Ð»Ñ Ð°Ð´Ñ€ÐµÑа Ñлектронной почты."
-
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
-msgstr "Это поле — Ð´Ð»Ñ Ð°Ð´Ñ€ÐµÑа Ñлектронной почты."
-
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
+#: mediagoblin/auth/forms.py:26
msgid "Username"
msgstr "Логин"
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
msgid "Password"
msgstr "Пароль"
-#: mediagoblin/auth/forms.py:60
+#: mediagoblin/auth/forms.py:34
msgid "Email address"
msgstr "ÐÐ´Ñ€ÐµÑ Ñлектронной почты"
-#: mediagoblin/auth/forms.py:78
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
+msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ Ð°Ð´Ñ€ÐµÑ Ñлектронной почты"
+
+#: mediagoblin/auth/forms.py:52
msgid "Username or email"
msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ Ð°Ð´Ñ€ÐµÑ Ñлектронной почты"
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr "Это поле не Ð´Ð»Ñ Ð°Ð´Ñ€ÐµÑа Ñлектронной почты."
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr "Это поле — Ð´Ð»Ñ Ð°Ð´Ñ€ÐµÑа Ñлектронной почты."
+
#: mediagoblin/auth/views.py:54
msgid "Sorry, registration is disabled on this instance."
msgstr "Извините, на Ñтом Ñайте региÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ð·Ð°Ð¿Ñ€ÐµÑ‰ÐµÐ½Ð°."
@@ -60,54 +65,54 @@ msgstr "Извините, пользователь Ñ Ñтим именем уж
msgid "Sorry, a user with that email address already exists."
msgstr "Сожалеем, но на Ñтот Ð°Ð´Ñ€ÐµÑ Ñлектронной почты уже зарегиÑтрирована Ð´Ñ€ÑƒÐ³Ð°Ñ ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ."
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr "Ваш Ð°Ð´Ñ€ÐµÑ Ñлектронной почты потвержден. Ð’Ñ‹ теперь можете войти и начать редактировать Ñвой профиль и загружать новые изображениÑ!"
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr "Ðеверный ключ проверки или идентификатор пользователÑ"
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr "Вам надо предÑтавитьÑÑ, чтобы мы знали, кому отправлÑть Ñообщение!"
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr "Ð’Ñ‹ уже потвердили Ñвой Ð°Ð´Ñ€ÐµÑ Ñлектронной почты!"
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr "ПереÑлать Ñообщение Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸ÐµÐ¼ аккаунта."
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
msgstr "ЕÑли Ñ Ñтим адреÑом Ñлектронной почты (Ñравниваемым чувÑтвительно к региÑтру Ñимволов!) еÑть ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ, то на него отправлено Ñообщение Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ñми о том, как Ñменить пароль."
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
msgstr "Ðе найдено никого Ñ Ñ‚Ð°ÐºÐ¸Ð¼ именем пользователÑ."
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
msgstr "Вам отправлено Ñлектронное пиÑьмо Ñ Ð¸Ð½ÑтрукциÑми по Ñмене паролÑ."
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr "Мы не можем отправить Ñообщение Ð´Ð»Ñ Ð²Ð¾ÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ, потому что ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ неактивна, либо указанный в ней Ð°Ð´Ñ€ÐµÑ Ñлектронной почты не был подтверждён."
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
msgstr "Теперь вы можете войти, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð²Ð°Ñˆ новый пароль."
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -118,7 +123,7 @@ msgid "Description of this work"
msgstr "ОпиÑание Ñтого произведениÑ"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -134,11 +139,11 @@ msgstr "Метки"
msgid "Separate tags by commas."
msgstr "(через запÑтую)"
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "ÐžÑ‚Ð»Ð¸Ñ‡Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ñ‡Ð°Ñть адреÑа"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "ÐžÑ‚Ð»Ð¸Ñ‡Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ñ‡Ð°Ñть адреÑа необходима"
@@ -166,45 +171,45 @@ msgid "This address contains errors"
msgstr "Этот Ð°Ð´Ñ€ÐµÑ Ñодержит ошибки"
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr "Старый пароль"
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr "Введите Ñвой Ñтарый пароль в качеÑтве доказательÑтва, что Ñто ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ."
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr "Ðовый пароль"
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
msgstr "ÐŸÑ€ÐµÐ´Ð¿Ð¾Ñ‡Ð¸Ñ‚Ð°ÐµÐ¼Ð°Ñ Ð»Ð¸Ñ†ÐµÐ½Ð·Ð¸Ñ"
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
msgstr "Она будет лицензией по умолчанию Ð´Ð»Ñ Ð²Ð°ÑˆÐ¸Ñ… загрузок"
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr "УведомлÑть Ð¼ÐµÐ½Ñ Ð¿Ð¾ e-mail о комментариÑÑ… к моим файлам"
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr "Ðазвание не может быть пуÑтым"
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr "ОпиÑание Ñтой коллекции"
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr "ÐžÑ‚Ð»Ð¸Ñ‡Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ñ‡Ð°Ñть адреÑа Ñтой коллекции, оÑÐ½Ð¾Ð²Ð°Ð½Ð½Ð°Ñ Ð½Ð° названии. Обычно не нужно её изменÑть."
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr "Старый пароль"
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr "Введите Ñвой Ñтарый пароль в качеÑтве доказательÑтва, что Ñто ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ."
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr "Ðовый пароль"
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr "У Ñтого Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ ÑƒÐ¶Ðµ еÑть файл Ñ Ñ‚Ð°ÐºÐ¾Ð¹ отличительной чаÑтью адреÑа."
@@ -229,44 +234,63 @@ msgstr "Ð’Ñ‹ редактируете профиль пользователÑ. Ð
msgid "Profile changes saved"
msgstr "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ñ„Ð¸Ð»Ñ Ñохранены"
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr "Ðеправильный пароль"
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr "ÐаÑтройки учётной запиÑи запиÑаны"
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
msgstr "Вам нужно подтвердить, что вы хотите удалить Ñвою учётную запиÑÑŒ."
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr "У Ð²Ð°Ñ ÑƒÐ¶Ðµ еÑть ÐºÐ¾Ð»Ð»ÐµÐºÑ†Ð¸Ñ Ñ Ð½Ð°Ð·Ð²Ð°Ð½Ð¸ÐµÐ¼ «%s»!"
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr "У Ñтого Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ ÑƒÐ¶Ðµ еÑть ÐºÐ¾Ð»Ð»ÐµÐºÑ†Ð¸Ñ Ñ Ñ‚Ð°ÐºÐ¾Ð¹ отличительной чаÑтью адреÑа."
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr "Ð’Ñ‹ редактируете коллекцию другого пользователÑ. Будьте оÑторожны."
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr "Ðеправильный пароль"
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr "Ваш пароль Ñменён уÑпешно"
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr "Ðевозможно привÑзать тему… не выбрано ÑущеÑтвующей темы\n"
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr "У Ñтой темы отÑутÑтвует каталог Ñ Ñлементами оформлениÑ\n"
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr "Однако найдена (и удалена) ÑÑ‚Ð°Ñ€Ð°Ñ ÑимволичеÑÐºÐ°Ñ ÑÑылка на каталог.\n"
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr ""
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
@@ -274,12 +298,16 @@ msgid ""
"domain."
msgstr ""
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr "Увы, Ñ Ð½Ðµ поддерживаю Ñтот тип файлов :("
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr ""
+
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr "Перекодировка видео не удалаÑÑŒ"
@@ -346,7 +374,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
msgstr "Клиент {0} зарегиÑтрирован!"
@@ -365,7 +393,7 @@ msgstr ""
msgid "Add"
msgstr "Добавить"
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr "Ðеправильный формат файла."
@@ -373,45 +401,45 @@ msgstr "Ðеправильный формат файла."
msgid "File"
msgstr "Файл"
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr "Вы должны загрузить файл."
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr "Ура! Файл загружен!"
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr "ÐšÐ¾Ð»Ð»ÐµÐºÑ†Ð¸Ñ Â«%s» добавлена!"
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr "Подтвердите ваш Ð°Ð´Ñ€ÐµÑ Ñлектронной почты!"
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
msgstr "завершение ÑеанÑа"
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr "Войти"
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr "Ð£Ñ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ <a href=\"%(user_url)s\">%(user_name)s</a>"
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr "Изменить наÑтройки учётной запиÑи"
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -419,72 +447,25 @@ msgstr "Изменить наÑтройки учётной запиÑи"
msgid "Media processing panel"
msgstr "Панель обработки файлов"
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
msgstr "Завершение ÑеанÑа"
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr "Добавить файлы"
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
msgstr "Создать новую коллекцию"
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr "Работает на <a href=\"http://mediagoblin.org/\" title='ВерÑии %(version)s'>MediaGoblin</a>, проекте <a href=\"http://gnu.org/\">GNU</a>."
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr "Он опубликован на уÑловиÑÑ… <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. ДоÑтупны <a href=\"%(source_link)s\">иÑходные текÑты</a>."
-
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
msgstr "Изображение нервничающего гоблина"
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr "Смотреть"
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr "Привет! Добро пожаловать на наш MediaGoblin’овый Ñайт!"
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr "Этот Ñайт работает на <a href=\"http://mediagoblin.org\">MediaGoblin</a>, необыкновенно замечательном ПО Ð´Ð»Ñ Ñ…Ð¾Ñтинга мультимедийных файлов."
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr "Ð”Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ ÑобÑтвенных файлов, ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¸ Ñ‚. п. вы можете предÑтавитьÑÑ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ вашей MediaGoblin’овой учётной запиÑи."
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr "У Ð²Ð°Ñ ÐµÑ‘ ещё нет? Ðе проблема!"
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">Создайте учётную запиÑÑŒ на Ñтом Ñайте</a>\n или\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">уÑтановите MediaGoblin на ÑобÑтвенный Ñервер</a>"
-
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr "Самые новые файлы"
@@ -590,6 +571,53 @@ msgid ""
"%(verification_url)s"
msgstr "Привет, %(username)s!\n\nЧтобы активировать Ñвой аккаунт в GNU MediaGoblin, откройте в Ñвоём вебâ€Ð±Ñ€Ð°ÑƒÐ·ÐµÑ€Ðµ Ñледующую ÑÑылку:\n\n%(verification_url)s"
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr "Работает на <a href=\"http://mediagoblin.org/\" title='ВерÑии %(version)s'>MediaGoblin</a>, проекте <a href=\"http://gnu.org/\">GNU</a>."
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr "Он опубликован на уÑловиÑÑ… <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. ДоÑтупны <a href=\"%(source_link)s\">иÑходные текÑты</a>."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr "Смотреть"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "Привет! Добро пожаловать на наш MediaGoblin’овый Ñайт!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr "Этот Ñайт работает на <a href=\"http://mediagoblin.org\">MediaGoblin</a>, необыкновенно замечательном ПО Ð´Ð»Ñ Ñ…Ð¾Ñтинга мультимедийных файлов."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr "Ð”Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ ÑобÑтвенных файлов, ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¸ Ñ‚. п. вы можете предÑтавитьÑÑ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ вашей MediaGoblin’овой учётной запиÑи."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr "У Ð²Ð°Ñ ÐµÑ‘ ещё нет? Ðе проблема!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -602,13 +630,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr "Добавление ÑопутÑтвующего файла Ð´Ð»Ñ %(media_title)s"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
msgstr "СопутÑтвующие файлы"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
msgstr "Добавить ÑопутÑтвующий файл"
@@ -625,12 +653,22 @@ msgstr "Отмена"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr "Сохранить изменениÑ"
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr "Смена Ð¿Ð°Ñ€Ð¾Ð»Ñ %(username)s"
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr "Сохранить"
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
@@ -641,7 +679,7 @@ msgid "Yes, really delete my account"
msgstr "Да, на Ñамом деле удалить мою учётную запиÑÑŒ"
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "Удалить безвозвратно"
@@ -658,7 +696,11 @@ msgstr "Редактирование %(media_title)s"
msgid "Changing %(username)s's account settings"
msgstr "ÐаÑтройка учётной запиÑи %(username)s"
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr "Сменить пароль"
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
msgstr "Удалить мою учётную запиÑÑŒ"
@@ -683,6 +725,7 @@ msgstr "Файлы Ñ Ð¼ÐµÑ‚ÐºÐ¾Ð¹: %(tag_name)s"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -707,6 +750,7 @@ msgid ""
msgstr "Ð’Ñ‹ можете Ñкачать Ñовременный браузер, \n\tÑпоÑобный проиграть Ñто аудио, Ñ <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!"
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr "ИÑходный файл"
@@ -715,6 +759,7 @@ msgstr "ИÑходный файл"
msgid "WebM file (Vorbis codec)"
msgstr "WebMâ€Ñ„айл (кодек — Vorbis)"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -725,6 +770,10 @@ msgstr "WebMâ€Ñ„айл (кодек — Vorbis)"
msgid "Image for %(media_title)s"
msgstr "Изображение «%(media_title)s»"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr "PDF-файл"
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
msgstr ""
@@ -823,7 +872,7 @@ msgstr "Удалить %(title)s?"
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr "Ð’ Ñамом деле иÑключить %(media_title)s из %(collection_title)s?"
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr "ИÑключить"
@@ -866,24 +915,28 @@ msgstr "Файлы Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ <a href=\"%(user_url)s\">%(username)
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr "■ПроÑмотр файлов Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ <a href=\"%(user_url)s\">%(username)s</a>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
msgstr "Добавить комментарий"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
msgstr "Добавить Ñтот комментарий"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
-msgstr "в"
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
-msgstr "<h3>Добавлено</h3>\n <p>%(date)s</p>"
+msgid "%(formatted_time)s ago"
+msgstr "%(formatted_time)s назад"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr "Добавлен"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
+msgstr "Создан"
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40
@@ -1039,7 +1092,7 @@ msgstr "более Ñтарые"
msgid "Tagged with"
msgstr "Метки"
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr "Ðе удалоÑÑŒ прочитать файл Ñ Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸ÐµÐ¼."
@@ -1069,6 +1122,30 @@ msgid ""
" deleted."
msgstr ""
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr "мин"
+
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
msgstr "Комментировать"
@@ -1100,73 +1177,77 @@ msgstr "-- Выберите --"
msgid "Include a note"
msgstr "Примечание"
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
msgstr "оÑтавил комментарий к вашему файлу"
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr "Сожалеем: возможноÑть ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½Ð°."
+
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr "Ой, ваш комментарий был пуÑÑ‚."
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr "Ваш комментарий размещён!"
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
msgstr "ПожалуйÑта, проверьте введённое и попробуйте ещё раз."
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr "Ðеобходимо выбрать или добавить коллекцию"
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr "«%s» — уже в коллекции «%s»"
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr "«%s» добавлено в коллекцию «%s»"
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr "Вы удалили файл."
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr "Файл не удалён, так как вы не подтвердили Ñвою уверенноÑть галочкой."
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr "Ð’Ñ‹ на пороге ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° другого пользователÑ. Будьте оÑторожны."
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr "Ð’Ñ‹ иÑключили файл из коллекции."
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr "Файл не иÑключён из коллекции, так как вы не подтвердили Ñвоё намерение отметкой."
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr "Ð’Ñ‹ на пороге иÑÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° из коллекции другого пользователÑ. Будьте оÑторожны."
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr "Вы удалили коллекцию «%s»"
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr "ÐšÐ¾Ð»Ð»ÐµÐºÑ†Ð¸Ñ Ð½Ðµ удалена, так как вы не подтвердили Ñвоё намерение отметкой."
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr "Ð’Ñ‹ на пороге ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ ÐºÐ¾Ð»Ð»ÐµÐºÑ†Ð¸Ð¸ другого пользователÑ. Будьте оÑторожны."
diff --git a/mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.mo
index bc92bb13..fd48a37f 100644
--- a/mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.po
index 07932b77..e4d1bacc 100644
--- a/mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.po
@@ -3,20 +3,20 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
-# Martin <zatroch.martin@gmail.com>, 2013.
-# Martin Zatroch <zatroch.martin@gmail.com>, 2012.
-# Morten Juhl-Johansen Zölde-Fejér <morten@writtenandread.net>, 2012.
-# Olle Jonsson <olle.jonsson@gmail.com>, 2012.
-# Tanja Trudslev <tanja.trudslev@gmail.com>, 2012.
-# <zatroch.martin@gmail.com>, 2011-2012.
+# martin <zatroch.martin@gmail.com>, 2013
+# martin <zatroch.martin@gmail.com>, 2012-2013
+# Morten Juhl-Johansen Zölde-Fejér <morten@writtenandread.net>, 2012
+# Olle Jonsson <olle.jonsson@gmail.com>, 2012
+# ttrudslev <tanja.trudslev@gmail.com>, 2012
+# martin <zatroch.martin@gmail.com>, 2011-2012
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-05 00:04+0000\n"
-"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-05-28 07:47+0000\n"
+"Last-Translator: martin <zatroch.martin@gmail.com>\n"
+"Language-Team: Slovak (http://www.transifex.com/projects/p/mediagoblin/language/sk/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -24,34 +24,39 @@ msgstr ""
"Language: sk\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
-msgstr "Nesprávne používateľské meno alebo e-mailová adresa."
-
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
-msgstr "Toto pole neakceptuje e-mailové adresy."
-
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
-msgstr "Toto pole vyžaduje e-mailovú adresu."
-
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
+#: mediagoblin/auth/forms.py:26
msgid "Username"
msgstr "Používateľské meno"
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
msgid "Password"
msgstr "Heslo"
-#: mediagoblin/auth/forms.py:60
+#: mediagoblin/auth/forms.py:34
msgid "Email address"
msgstr "Email adresse"
-#: mediagoblin/auth/forms.py:78
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
+msgstr "Použivateľské meno alebo e-mail"
+
+#: mediagoblin/auth/forms.py:52
msgid "Username or email"
msgstr "Používateľské meno alebo e-mailová adresa"
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr "Nesprávne používateľské meno alebo e-mailová adresa."
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr "Toto pole neakceptuje e-mailové adresy."
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr "Toto pole vyžaduje e-mailovú adresu."
+
#: mediagoblin/auth/views.py:54
msgid "Sorry, registration is disabled on this instance."
msgstr "PrepáÄ, registrácia na danej inÅ¡tancii nie je povolená."
@@ -64,54 +69,54 @@ msgstr "PrepáÄ, rovnaké používateľské meno už existuje."
msgid "Sorry, a user with that email address already exists."
msgstr "PrepáÄ, rovnaká e-mailová adresa už bola použitá na vytvorenie úÄtu."
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr "Tvoja e-mailová adresa bola overená. Teraz sa môžeš prihlásiť, upravovať profil a vkladať výtvory!"
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr "Overovací kľúÄ, prípadne používateľské meno je nesprávne."
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr "Je potrebné prihlásiť sa, aby sme vedeli kam máme e-mail zaslať!"
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr "Už máš overenú e-mailovú adresu!"
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr "Opätovne zaslať overovací e-mail."
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
msgstr "Pokiaľ daná e-mailová adresa (citlivá na veľkosť písma!) je registrovaná, e-mail z inštrukciami pre zmenu tvojho hesla bol zaslaný."
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
msgstr "Nemožno nájsť nikoho z daným používateľským menom."
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
msgstr "E-mailová správa z inštrukciami na zmenu tvojho hesla bola zaslaná."
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr "Nebolo možné zaslať e-mail na opätovné získanie zabudnutého hesla, nakoľko tvoje používateľské meno je neaktívne, prípadne e-mailová adresa nebola úspešne overená."
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
msgstr "Už môžeš použiť nové heslo pri prihlasovaní."
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -122,7 +127,7 @@ msgid "Description of this work"
msgstr "Popis výtvoru"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -138,11 +143,11 @@ msgstr "Štítky"
msgid "Separate tags by commas."
msgstr "Oddeľ Å¡títky pomocou Äiarky."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "Unikátna ÄasÅ¥ adresy"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "Unikátna ÄasÅ¥ adresy nesmie byÅ¥ prázdna"
@@ -170,45 +175,45 @@ msgid "This address contains errors"
msgstr "Daná adresa obsahuje chybu"
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr "Staré heslo"
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr "Vlož svoje staré heslo na dôkaz toho, že vlastníš daný úÄet."
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr "Nové heslo"
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
msgstr "Preferencia licencie"
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
msgstr "Nasledovná licencia bude použitá ako východzia pre všetky tvoje výtvory."
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr "ZaÅ¡li mi e-mail keÄ ostatní okomentujú môj výtvor"
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr "Titulok nesmie byť prázdny."
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr "Popis danej kolekcie"
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr "Titulná ÄasÅ¥ adresy danej kolekcie. Zmena poľa nepovinná."
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr "Staré heslo"
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr "Vlož svoje staré heslo na dôkaz toho, že vlastníš daný úÄet."
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr "Nové heslo"
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr "Položku s rovnakou unikátnou ÄasÅ¥ou adresy už niekde máš."
@@ -233,44 +238,63 @@ msgstr "Upravuješ profil iného používateľa. Pristupuj zodpovedne. "
msgid "Profile changes saved"
msgstr "Zmeny v profile uložené"
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr "Nesprávne heslo"
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr "Nastavenia úÄtu uložené"
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
msgstr "PotrebujeÅ¡ potvrdiÅ¥ odstránenie svojho úÄtu."
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr "Už máš kolekciu nazvanú ako \"%s\"!"
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr "Kolekcia s týmto štítkom už máš."
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr "Upravuješ kolekciu iného používateľa. Pristupuj zodpovedne. "
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr "Nesprávne heslo"
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr "Tvoje heslo bolo úspešne zmenené"
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr "Nemožno pripojiť tému... téma nenastavená\n"
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr "Žiadny prieÄinok položiek pre túto tému\n"
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr "Odstránené; hoci bol pôvodný symbolický odkaz adresára nájdený.\n"
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr "Nemožno odkazovať na \"%s\": %s existuje a nie je symbolickým odkazom\n"
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr "Preskakujem \"%s\"; opakovane nastavené.\n"
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr "Nájdený starý odkaz pre \"%s\"; odstraňujem.\n"
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
@@ -278,12 +302,16 @@ msgid ""
"domain."
msgstr "CSRF \"cookie\" neprítomný. Toto vidíš najskôr ako výsledok blokovania \"cookie\" súborov a pod.<br/>Uisti sa, že máš povolené ukladanie \"cookies\" pre danú doménu."
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr "PrepáÄ, nepodporujem tento typ súborov =("
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr "beh unoconv zlyhal, preskúmajte log záznam"
+
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr "Konvertovanie videa zlyhalo"
@@ -350,7 +378,7 @@ msgstr "Presmerovacie URI pre aplikácie, toto pole\nje <strong>požadované</st
msgid "This field is required for public clients"
msgstr "Dané pole je požadované pre verejných klientov."
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
msgstr "Klient {0} bol registrovaný!"
@@ -369,7 +397,7 @@ msgstr "Tvoji autorizovaní OAuth klienti"
msgid "Add"
msgstr "Pridať"
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr "Nesprávny typ súboru pre dané médium."
@@ -377,45 +405,45 @@ msgstr "Nesprávny typ súboru pre dané médium."
msgid "File"
msgstr "Súbor"
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr "Musíš poskytnúť súbor."
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr "Skvelé! Pridané!"
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr "Kolekcia \"%s\" pridaná!"
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr "Over si e-mailovú adresu!"
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
msgstr "odhlásiť sa"
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr "Prihlásiť sa"
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr "ÚÄet používateľa <a href=\"%(user_url)s\">%(user_name)s</a>"
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr "ZmeniÅ¥ nastavenia úÄtu"
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -423,72 +451,25 @@ msgstr "ZmeniÅ¥ nastavenia úÄtu"
msgid "Media processing panel"
msgstr "Sekcia spracovania výtvorov"
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
-msgstr ""
+msgstr "Odhlásiť sa"
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr "Pridať výtvor"
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
msgstr "Vytvoriť novú kolekciu"
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr "Poháňa nás <a href=\"http://mediagoblin.org/\" title='Version %(version)s'>MediaGoblin</a>, súÄasÅ¥ projektu <a href=\"http://gnu.org/\">GNU</a>."
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr "Uvoľnené pod <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Zdrojový kód</a> plne dostupný."
-
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
msgstr "Obrázok hysterického goblina"
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr "Preskúmať"
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr "Ahoj, vitaj na tejto MediaGoblin stránke!"
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr "Táto stránka používa <a href=\"http://mediagoblin.org\">MediaGoblin</a>, výnimoÄne skvelý kus softvéru na hostovanie médií."
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr "Pre pridanie vlastných výtvorov, komentárov a viac.. sa prihlás zo svojim MediaGoblin úÄtom."
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr "Har du ikke en endnu? Det er let!"
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">VytvoriÅ¥ úÄet na tejto stránke</a>\n alebo\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">ZaložiÅ¥ MediaGoblin na vlastnom serveri</a>"
-
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr "Aktuálne výtvory"
@@ -594,6 +575,53 @@ msgid ""
"%(verification_url)s"
msgstr "Ahoj %(username)s,\n\npre aktiváciu tvojho GNU MediaGoblin úÄtu, otvor nasledujúci odkaz vo\nsvojom prehliadaÄi:\n\n%(verification_url)s"
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr "Poháňa nás <a href=\"http://mediagoblin.org/\" title='Version %(version)s'>MediaGoblin</a>, súÄasÅ¥ projektu <a href=\"http://gnu.org/\">GNU</a>."
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr "Uvoľnené pod <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Zdrojový kód</a> plne dostupný."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr "Preskúmať"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "Ahoj, vitaj na tejto MediaGoblin stránke!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr "Táto stránka používa <a href=\"http://mediagoblin.org\">MediaGoblin</a>, výnimoÄne skvelý kus softvéru na hostovanie médií."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr "Pre pridanie vlastných výtvorov, komentárov a viac.. sa prihlás zo svojim MediaGoblin úÄtom."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr "Har du ikke en endnu? Det er let!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">VytvoriÅ¥ úÄet na tejto stránke</a>\n alebo\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">NastaviÅ¥ MediaGoblin na vlastnom serveri</a>"
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -606,13 +634,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr "Úprava príloh pre %(media_title)s"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
msgstr "Prílohy"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
msgstr "Pridať prílohu"
@@ -629,12 +657,22 @@ msgstr "Zrušiť"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr "Uložiť zmeny"
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr "Mením heslo používateľa %(username)s"
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr "Uložiť"
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
@@ -645,7 +683,7 @@ msgid "Yes, really delete my account"
msgstr "Ãno, skutoÄne odstrániÅ¥ môj úÄet"
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "Odstráňiť permanentne"
@@ -662,7 +700,11 @@ msgstr "Úprava %(media_title)s"
msgid "Changing %(username)s's account settings"
msgstr "Mením nastavenia úÄtu používateľa %(username)s"
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr "Zmeniť svoje heslo."
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
msgstr "OdstrániÅ¥ môj úÄet"
@@ -687,6 +729,7 @@ msgstr "Výtvory oznaÄené ako: %(tag_name)s"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -711,6 +754,7 @@ msgid ""
msgstr "MôžeÅ¡ získaÅ¥ moderný prehliadaÄ, ktorý\n\ttento zvuk hravo prehrá <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!"
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr "Originálny súbor"
@@ -719,6 +763,7 @@ msgstr "Originálny súbor"
msgid "WebM file (Vorbis codec)"
msgstr "WebM súbor (Vorbis kodek)"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -729,6 +774,10 @@ msgstr "WebM súbor (Vorbis kodek)"
msgid "Image for %(media_title)s"
msgstr "Obrázok pre %(media_title)s"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr "PDF súbor"
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
msgstr "Zapnúť rotáciu"
@@ -827,7 +876,7 @@ msgstr "SkutoÄne odstrániÅ¥ %(title)s?"
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr "SkutoÄne odstrániÅ¥ %(media_title)s z %(collection_title)s?"
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr "Odstrániť"
@@ -870,24 +919,28 @@ msgstr "Výtvory, ktoré vlastní <a href=\"%(user_url)s\">%(username)s</a>"
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr "■Prehliadanie výtvorov od <a href=\"%(user_url)s\">%(username)s</a>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
msgstr "Pridať komentár"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
msgstr "Pridať tento komentár"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
-msgstr "o"
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
-msgstr "<h3>Pridané</h3>\n <p>%(date)s</p>"
+msgid "%(formatted_time)s ago"
+msgstr "pred %(formatted_time)s "
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr "Pridané"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
+msgstr "Vytvorené"
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40
@@ -1043,7 +1096,7 @@ msgstr "staršie"
msgid "Tagged with"
msgstr "OznaÄené ako"
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr "Nemožno preÄítaÅ¥ súbor obrázka."
@@ -1073,6 +1126,30 @@ msgid ""
" deleted."
msgstr "Zdá sa, že na tejto adrese sa niÄ nenachádza. PrepáÄ!</p><p>Pokiaľ si si istý, že adresa je správna, možno bola hľadaná stránka presunutá, respektíve odstránená."
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr "rok"
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr "mesiac"
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr "týždeň"
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr "deň"
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr "hodina"
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr "minúta"
+
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
msgstr "Komentár"
@@ -1104,73 +1181,77 @@ msgstr "-- Vybrať --"
msgid "Include a note"
msgstr "Pridať poznámku"
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
msgstr "okmentoval tvoj príspevok"
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr "PrepáÄ, komentovanie je vypnuté."
+
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr "Hopla, tvoj komentár bol prázdny."
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr "Tvoj komentár bol pridaný!"
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
msgstr "Prosím skontroluj svoje položky a skús znova."
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr "Musíš vybrať, prípadne pridať kolekciu"
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr "\"%s\" sa už nachádza v kolekcii \"%s\""
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr "\"%s pridané do kolekcie \"%s\""
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr "Výtvor bol tebou odstránený."
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr "Výtvor nebol odstránený, nakoľko chýbalo tvoje potvrdenie."
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr "Chystáš sa odstrániť výtvory niekoho iného. Pristupuj zodpovedne. "
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr "Položka bola z kolekcie odstránená."
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr "Položka nebola odstránená, nakoľko políÄko potvrdenia nebolo oznaÄné."
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr "Chystáš sa odstrániť položku z kolekcie iného používateľa. Pristupuj zodpovedne. "
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr "Kolekcia \"%s\" bola úspešne odstránená."
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr "Kolekcia nebola odstránená, nakoľko políÄko potrvdenia nebolo oznaÄené."
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr "Chystáš sa odstrániť kolekciu iného používateľa. Pristupuj zodpovedne. "
diff --git a/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.mo
index dd3de81b..199e761c 100644
--- a/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.po
index 98d62d59..35635acf 100644
--- a/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.po
@@ -3,15 +3,15 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
-# Jure Repinc <jlp@holodeck1.com>, 2011.
+# Jure Repinc <jlp@holodeck1.com>, 2011
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-05 00:04+0000\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-05-27 18:54+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language-Team: Slovenian (http://www.transifex.com/projects/p/mediagoblin/language/sl/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -19,34 +19,39 @@ msgstr ""
"Language: sl\n"
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
+#: mediagoblin/auth/forms.py:26
msgid "Username"
msgstr "Uporabniško ime"
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
msgid "Password"
msgstr "Geslo"
-#: mediagoblin/auth/forms.py:60
+#: mediagoblin/auth/forms.py:34
msgid "Email address"
msgstr "E-poštni naslov"
-#: mediagoblin/auth/forms.py:78
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
+msgstr ""
+
+#: mediagoblin/auth/forms.py:52
msgid "Username or email"
msgstr ""
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr ""
+
#: mediagoblin/auth/views.py:54
msgid "Sorry, registration is disabled on this instance."
msgstr "Oprostite, prijava za ta izvod ni omogoÄena."
@@ -59,54 +64,54 @@ msgstr "Oprostite, uporabnik s tem imenom že obstaja."
msgid "Sorry, a user with that email address already exists."
msgstr ""
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr "Vaš e-poštni naslov je bil potrjen. Sedaj se lahko prijavite, uredite svoj profil in pošljete slike."
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr "Potrditveni kljuÄ ali uporabniÅ¡ka identifikacija je napaÄna"
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr ""
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr ""
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr "Ponovno pošiljanje potrditvene e-pošte."
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
msgstr ""
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
msgstr ""
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
msgstr ""
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr ""
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
msgstr ""
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -117,7 +122,7 @@ msgid "Description of this work"
msgstr ""
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -133,11 +138,11 @@ msgstr "Oznake"
msgid "Separate tags by commas."
msgstr ""
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "Oznaka"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "Oznaka ne sme biti prazna"
@@ -165,45 +170,45 @@ msgid "This address contains errors"
msgstr ""
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr ""
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr ""
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr ""
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
msgstr ""
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
msgstr ""
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr ""
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr ""
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr ""
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr ""
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr ""
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr "Vnos s to oznako za tega uporabnika že obstaja."
@@ -228,44 +233,63 @@ msgstr "Urejate uporabniški profil. Nadaljujte pazljivo."
msgid "Profile changes saved"
msgstr ""
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr ""
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr ""
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
msgstr ""
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr ""
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr ""
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr ""
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr ""
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
@@ -273,12 +297,16 @@ msgid ""
"domain."
msgstr ""
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr ""
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr ""
+
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr ""
@@ -345,7 +373,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
msgstr ""
@@ -364,7 +392,7 @@ msgstr ""
msgid "Add"
msgstr ""
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr "Za vrsto vsebine je bila podana napaÄna datoteka."
@@ -372,45 +400,45 @@ msgstr "Za vrsto vsebine je bila podana napaÄna datoteka."
msgid "File"
msgstr "Datoteka"
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr "Podati morate datoteko."
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr "Juhej! Poslano."
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr "Prijava"
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -418,72 +446,25 @@ msgstr ""
msgid "Media processing panel"
msgstr "Podokno obdelovanja vsebine"
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr "Dodaj vsebino"
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr ""
@@ -589,6 +570,53 @@ msgid ""
"%(verification_url)s"
msgstr "Pozdravljeni, %(username)s\n\nZa aktivacijo svojega raÄuna GNU MediaGoblin odprite\nnaslednji URL v svojem spletnem brskalniku:\n\n%(verification_url)s"
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -601,13 +629,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
msgstr ""
@@ -624,12 +652,22 @@ msgstr "PrekliÄi"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr "Shrani spremembe"
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
@@ -640,7 +678,7 @@ msgid "Yes, really delete my account"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr ""
@@ -657,7 +695,11 @@ msgstr "Urejanje %(media_title)s"
msgid "Changing %(username)s's account settings"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
msgstr ""
@@ -682,6 +724,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -706,6 +749,7 @@ msgid ""
msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr ""
@@ -714,6 +758,7 @@ msgstr ""
msgid "WebM file (Vorbis codec)"
msgstr ""
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -724,6 +769,10 @@ msgstr ""
msgid "Image for %(media_title)s"
msgstr ""
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
msgstr ""
@@ -822,7 +871,7 @@ msgstr ""
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr ""
@@ -865,23 +914,27 @@ msgstr "Vsebina uporabnika <a href=\"%(user_url)s\">%(username)s</a>"
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
+#, python-format
+msgid "%(formatted_time)s ago"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
-#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
@@ -1038,7 +1091,7 @@ msgstr ""
msgid "Tagged with"
msgstr ""
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr ""
@@ -1068,6 +1121,30 @@ msgid ""
" deleted."
msgstr ""
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr ""
+
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
msgstr ""
@@ -1099,73 +1176,77 @@ msgstr ""
msgid "Include a note"
msgstr ""
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
msgstr ""
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr ""
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr ""
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr ""
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr ""
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr ""
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr ""
diff --git a/mediagoblin/i18n/sq/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/sq/LC_MESSAGES/mediagoblin.mo
index 276f1273..0f113dcb 100644
--- a/mediagoblin/i18n/sq/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/sq/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/sq/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/sq/LC_MESSAGES/mediagoblin.po
index 5c965623..aabf18db 100644
--- a/mediagoblin/i18n/sq/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/sq/LC_MESSAGES/mediagoblin.po
@@ -3,14 +3,14 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
-# Besnik Bleta <besnik@programeshqip.org>, 2012.
-# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
+# Besnik <besnik@programeshqip.org>, 2012-2013
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2012
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-05 00:04+0000\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-05-27 18:54+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: Albanian (http://www.transifex.com/projects/p/mediagoblin/language/sq/)\n"
"MIME-Version: 1.0\n"
@@ -20,34 +20,39 @@ msgstr ""
"Language: sq\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
+#: mediagoblin/auth/forms.py:26
msgid "Username"
msgstr "Emër përdoruesi"
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
msgid "Password"
msgstr "Fjalëkalim"
-#: mediagoblin/auth/forms.py:60
+#: mediagoblin/auth/forms.py:34
msgid "Email address"
msgstr "Adresë email"
-#: mediagoblin/auth/forms.py:78
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
+msgstr ""
+
+#: mediagoblin/auth/forms.py:52
msgid "Username or email"
msgstr "Emër përdoruesi ose email"
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr "Emër përdoruesi ose adresë email e pavlefshme."
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr "Kjo fushë nuk është për adresa email."
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr "Kjo fushë lyp një adresë email."
+
#: mediagoblin/auth/views.py:54
msgid "Sorry, registration is disabled on this instance."
msgstr "Na njdeni, regjistrimi në këtë instancë të shërbimit është i çaktivizuar."
@@ -60,54 +65,54 @@ msgstr "Na ndjeni, ka tashmë një përdorues me këtë emër."
msgid "Sorry, a user with that email address already exists."
msgstr "Na ndjeni, ka tashmë një përdorues me këtë adresë email."
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr "Adresa juaj email u verifikua. Tani mund të bëni hyrjen, të përpunoni profilin tuaj, dhe të parashtroni figura!"
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr "Kyçi i verifikimit ose id-ja e përdoruesit është e pasaktë"
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr "Duhet të jeni i futur, që ta dimë kujt t'ia çojmë email-in!"
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr "Thuajse e keni verifikuar adresën tuaj email!"
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr "Ridërgoni email-in tuaj të verifikimit."
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
-msgstr ""
+msgstr "Nëse ajo adresë email (siç është shkruajtur!) është e regjistruar, është dërguar një email me udhëzime se si të ndryshoni fjalëkalimin tuaj."
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
-msgstr ""
+msgstr "S'u gjet dot dikush me atë emër përdoruesi."
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
msgstr "Është dërguar një email me udhëzime se si të ndryshoni fjalëkalimin tuaj."
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr "Email-i i ricaktimit të fjalëkalimit nuk u dërgua dot, ngaqë emri juaj i përdoruesit nuk është aktivizuar ose adresa email e llogarisë suaj nuk është verifikuar."
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
msgstr "Tani mun të hyni duke përdorur fjalëkalimin tuaj të ri."
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -118,7 +123,7 @@ msgid "Description of this work"
msgstr "Përshkrim i kësaj pune"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -134,11 +139,11 @@ msgstr "Etiketa"
msgid "Separate tags by commas."
msgstr "Ndajini etiketat me presje."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "Identifikues"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "Identifikuesi s'mund të jetë i zbrazët"
@@ -166,45 +171,45 @@ msgid "This address contains errors"
msgstr "Kjo adresë përmban gabime"
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr "Fjalëkalimi i vjetër"
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr "Jepni fjalëkalimin tuaj të vjetër që të provohet se këtë llogari e zotëroni ju."
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr "Fjalëkalimi i ri"
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
-msgstr ""
+msgstr "Parapëlqime licence"
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
-msgstr ""
+msgstr "Kjo do të jetë licenca juaj parazgjedhje për forma ngarkimesh."
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr "Dërgomë email kur të tjerët komentojnë te media ime"
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr "Titulli s'mund të jetë i zbrazët"
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr "Përshkrim i këtij koleksioni"
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr "Pjesa titull e adresës së këtij koleksioni. Zakonisht nuk keni pse e ndryshoni këtë."
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr "Fjalëkalimi i vjetër"
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr "Jepni fjalëkalimin tuaj të vjetër që të provohet se këtë llogari e zotëroni ju."
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr "Fjalëkalimi i ri"
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr "Ka tashmë një zë me atë identifikues për këtë përdorues."
@@ -219,7 +224,7 @@ msgstr "Shtuat bashkangjitjen %s!"
#: mediagoblin/edit/views.py:182
msgid "You can only edit your own profile."
-msgstr ""
+msgstr "Mund të përpunoni vetëm profilin tuaj."
#: mediagoblin/edit/views.py:188
msgid "You are editing a user's profile. Proceed with caution."
@@ -229,57 +234,80 @@ msgstr "Po përpunoni profilin e një përdoruesi. Hapni sytë."
msgid "Profile changes saved"
msgstr "Ndryshimet e profilit u ruajtën"
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr "Fjalëkalim i gabuar"
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr "Rregullimet e llogarisë u ruajtën"
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
-msgstr ""
+msgstr "Lypset të ripohoni fshirjen e llogarisë suaj."
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
-msgstr "Keni tashmë një koleksion të quajtur \"%s\"!"
+msgstr "Keni tashmë një koleksion të quajtur \"%s\"!"
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr "Ka tashmë një koleksion me atë identifikues për këtë përdorues."
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr "Po përpunoni koleksionin e një tjetër përdoruesi. Hapni sytë."
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr "Fjalëkalim i gabuar"
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr "Nuk krijohet dot lidhje për te tema... nuk ka temë të caktuar\n"
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr "Nuk ka drejtori asetesh për këtë temë\n"
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr "Sidoqoftë, u gjet simlidhje e vjetër drejtorie lidhjesh; u hoq.\n"
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr ""
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
"or somesuch.<br/>Make sure to permit the settings of cookies for this "
"domain."
-msgstr ""
+msgstr "Pa cookie CSRF të pranishme. Ka shumë të ngjarë që të jetë punë e një bllokuesi cookie-sh ose të tillë.<br/>Sigurohuni që të lejoni depozitim cookie-sh për këtë përkatësi."
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr "Na ndjeni, nuk e mbullojmë këtë lloj kartele :("
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr ""
+
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr "Ndërkodimi i videos dështoi"
@@ -346,17 +374,17 @@ msgstr "URI ridrejtimi për zbatimin, kjo fushë\n është <strong>e
msgid "This field is required for public clients"
msgstr "Kjo fushë është e domosdoshme për klientë publikë"
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
msgstr "Klienti {0} u regjistrua!"
#: mediagoblin/plugins/oauth/templates/oauth/client/connections.html:22
msgid "OAuth client connections"
-msgstr ""
+msgstr "Lidhje klienti OAuth"
#: mediagoblin/plugins/oauth/templates/oauth/client/list.html:22
msgid "Your OAuth clients"
-msgstr ""
+msgstr "Klientët tuaj OAuth"
#: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
@@ -365,7 +393,7 @@ msgstr ""
msgid "Add"
msgstr "Shtoni"
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr "Kartelë e gabuar e dhënë për llojin e medias."
@@ -373,118 +401,71 @@ msgstr "Kartelë e gabuar e dhënë për llojin e medias."
msgid "File"
msgstr "Kartelë"
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr "Duhet të jepni një kartelë."
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr "Yhaaaaaa! U parashtrua!"
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr "U shtua koleksioni \"%s\"!"
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr "Verifikoni email-in tuaj!"
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
msgstr "dilni"
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr "Hyni"
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr "Llogaria e <a href=\"%(user_url)s\">%(user_name)s</a>"
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr "Ndryshoni rregullime llogarie"
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26
msgid "Media processing panel"
-msgstr "Paneli i Përpunimit të Medias"
+msgstr "Paneli i përpunimit të medias"
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
-msgstr ""
+msgstr "Dilni"
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr "Shtoni media"
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
msgstr "Krijoni koleksion të ri"
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr "Hedhur në qarkullim sipas <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL-së</a>. <a href=\"%(source_link)s\">Kodi burim</a> është i passhëm."
-
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr "Eksploroni"
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr "Tungjatjeta juaj, mirë se vini te ky site MediaGoblin!"
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr "Ky site përdor <a href=\"http://mediagoblin.org\">MediaGoblin</a>, një program jashtëzakonisht i shkëlqyer për strehim mediash."
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr "Për të shtuar media tuajën, për të bërë komente, dhe të tjera, mund të hyni përmes llogarisë suaj MediaGoblin."
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr "Nuk keni ende një të tillë? Është e lehtë!"
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">Krijoni një llogarin te ky site</a>\n ose\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Instaloni dhe rregulloni MediaGoblin-in te shërbyesi juaj</a>"
+msgstr "Figurë e gungaçi duke bërë shtriqje"
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr "Mediat më të reja"
@@ -515,7 +496,7 @@ msgstr "Pa zëra të dështuar!"
#: mediagoblin/templates/mediagoblin/admin/panel.html:92
msgid "Last 10 successful uploads"
-msgstr "10 Ngarkimet e Fundit të Suksesshme"
+msgstr "10 ngarkimet e fundit të suksesshme"
#: mediagoblin/templates/mediagoblin/admin/panel.html:112
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107
@@ -590,6 +571,53 @@ msgid ""
"%(verification_url)s"
msgstr "Njatjeta %(username)s,\n\nqë të aktivizoni llogarinë tuaj te GNU MediaGoblin hapeni URL-në vijuese te\nshfletuesi juaj web:\n\n%(verification_url)s"
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr "Bazuar në <a href=\"http://mediagoblin.org/\" title='Version %(version)s'>MediaGoblin</a>, një projekt <a href=\"http://gnu.org/\">GNU</a>."
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr "Hedhur në qarkullim sipas <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL-së</a>. <a href=\"%(source_link)s\">Kodi burim</a> është i passhëm."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr "Eksploroni"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "Tungjatjeta juaj, mirë se vini te ky site MediaGoblin!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr "Ky site përdor <a href=\"http://mediagoblin.org\">MediaGoblin</a>, një program jashtëzakonisht i shkëlqyer për strehim mediash."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr "Për të shtuar media tuajën, për të bërë komente, dhe të tjera, mund të hyni përmes llogarisë suaj MediaGoblin."
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr "Nuk keni ende një të tillë? Është e lehtë!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -602,13 +630,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr "Po përpunohen bashkangjitjet për %(media_title)s"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
msgstr "Bashkangjitje"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
msgstr "Shtoni bashkangjitje"
@@ -625,23 +653,33 @@ msgstr "Anuloje"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr "Ruaji ndryshimet"
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
-msgstr ""
+msgstr "Të fshihet vërtet përdoruesi '%(user_name)s' dhe krejt media/komentet përkatëse?"
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:35
msgid "Yes, really delete my account"
-msgstr ""
+msgstr "Po, fshijeni vërtet llogarinë time"
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "Fshije përgjithmonë"
@@ -658,10 +696,14 @@ msgstr "Po përpunohet %(media_title)s"
msgid "Changing %(username)s's account settings"
msgstr "Po ndryshohen rregullimet e llogarisë %(username)s"
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
-msgid "Delete my account"
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
msgstr ""
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
+msgid "Delete my account"
+msgstr "Fshije llogarinë time"
+
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29
#, python-format
msgid "Editing %(collection_title)s"
@@ -683,6 +725,7 @@ msgstr "Media e etiketuar me:: %(tag_name)s"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -707,6 +750,7 @@ msgid ""
msgstr "Një shfletues web modern që mund të luajë \n\taudion mund ta merrni te <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!"
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr "Kartela origjinale"
@@ -715,6 +759,7 @@ msgstr "Kartela origjinale"
msgid "WebM file (Vorbis codec)"
msgstr "Kartelë WebM (kodek Vorbis)"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -725,9 +770,13 @@ msgstr "Kartelë WebM (kodek Vorbis)"
msgid "Image for %(media_title)s"
msgstr "Figurë për %(media_title)s"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
-msgstr ""
+msgstr "Aktivizoni/Çaktivizoni Rrotullimin"
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113
msgid "Perspective"
@@ -770,14 +819,14 @@ msgid ""
"Sorry, this video will not work because\n"
" your web browser does not support HTML5 \n"
" video."
-msgstr ""
+msgstr "Na ndjeni, kjo video nuk do të punojë ngaqë\n shfletuesi juaj web nuk mbulon videot\n HTML5."
#: mediagoblin/templates/mediagoblin/media_displays/video.html:47
msgid ""
"You can get a modern web browser that \n"
" can play this video at <a href=\"http://getfirefox.com\">\n"
" http://getfirefox.com</a>!"
-msgstr ""
+msgstr "Mund të merrni një shfletues web modern që \n është në gjendje ta shfaqë këtë video, te <a href=\"http://getfirefox.com\">\n http://getfirefox.com</a>!"
#: mediagoblin/templates/mediagoblin/media_displays/video.html:69
msgid "WebM file (640p; VP8/Vorbis)"
@@ -823,19 +872,19 @@ msgstr "Të fshihet vërtet %(title)s?"
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr "Të hiqet vërtet %(media_title)s nga %(collection_title)s?"
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr "Hiqe"
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:21
#, python-format
msgid "%(username)s's collections"
-msgstr ""
+msgstr "Koleksione të %(username)s"
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:28
#, python-format
msgid "<a href=\"%(user_url)s\">%(username)s</a>'s collections"
-msgstr ""
+msgstr "Koleksione të <a href=\"%(user_url)s\">%(username)s</a>"
#: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19
#, python-format
@@ -854,7 +903,7 @@ msgstr "Media nga %(username)s"
msgid ""
"<a href=\"%(user_url)s\">%(username)s</a>'s media with tag <a "
"href=\"%(tag_url)s\">%(tag)s</a>"
-msgstr ""
+msgstr "Media të <a href=\"%(user_url)s\">%(username)s</a> me etiketën <a href=\"%(tag_url)s\">%(tag)s</a>"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48
#, python-format
@@ -866,30 +915,34 @@ msgstr "Media nga <a href=\"%(user_url)s\">%(username)s</a>"
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr "â– Po shfletoni media nga <a href=\"%(user_url)s\">%(username)s</a>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
msgstr "Shtoni një koment"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
msgstr "Shtoje këtë koment"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
-msgstr "te"
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
-msgstr "<h3>Shtuar më</h3>\n <p>%(date)s</p>"
+msgid "%(formatted_time)s ago"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
+msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40
#, python-format
msgid "Add “%(media_title)s†to a collection"
-msgstr ""
+msgstr "Shtojeni “%(media_title)s†te një koleksion"
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:54
msgid "+"
@@ -968,7 +1021,7 @@ msgstr "Ky përdorues nuk e ka plotësuar (ende) profilin e vet."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:124
msgid "Browse collections"
-msgstr ""
+msgstr "Shfletoni koleksionet"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:137
#, python-format
@@ -993,11 +1046,11 @@ msgstr "(hiqe)"
#: mediagoblin/templates/mediagoblin/utils/collections.html:21
msgid "Collected in"
-msgstr ""
+msgstr "Pjesë e koleksionit"
#: mediagoblin/templates/mediagoblin/utils/collections.html:40
msgid "Add to a collection"
-msgstr ""
+msgstr "Shtoje te një koleksion"
#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
#: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:21
@@ -1039,7 +1092,7 @@ msgstr "më të vjetra"
msgid "Tagged with"
msgstr "Etiketuar me"
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr "Nuk lexoi dot kartelën e figurës."
@@ -1069,9 +1122,33 @@ msgid ""
" deleted."
msgstr "Nuk duket se ka ndonjë faqe në këtë adresë. Na ndjeni!</p><p>Nëse jeni i sigurt se kjo adresë është e saktë, ndoshta faqja që po kërkoni është lëvizur ose fshirë."
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr ""
+
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
-msgstr ""
+msgstr "Koment"
#: mediagoblin/user_pages/forms.py:25
msgid ""
@@ -1090,7 +1167,7 @@ msgstr "Jam i sigurt se dua që të hiqet ky objekt prek koleksioni"
#: mediagoblin/user_pages/forms.py:39
msgid "Collection"
-msgstr ""
+msgstr "Koleksion"
#: mediagoblin/user_pages/forms.py:40
msgid "-- Select --"
@@ -1100,73 +1177,77 @@ msgstr "-- Përzgjidhni --"
msgid "Include a note"
msgstr "Përfshini një shënim"
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
msgstr "komentoi te postimi juaj"
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr "Hmmm, komenti juaj qe i zbrazët."
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr "Komenti juaj u postua!"
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
msgstr "Ju lutemi, kontrolloni zërat tuaj dhe riprovoni."
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr "Duhet të përzgjidhni ose shtoni një koleksion"
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr "\"%s\" gjendet tashmë te koleksioni \"%s\""
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr "\"%s\" u shtua te koleksioni \"%s\""
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr "E fshitë median."
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr "Media nuk u fshi ngaqë nuk i vutë shenjë pohimit se jeni i sigurt."
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr "Ju ndan një hap nga fshirja e medias të një tjetër përdoruesi. Hapni sytë."
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr "E fshitë objektin prej koleksionit."
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr "Objekti nuk u fshi ngaqë, nuk pohuat se jeni të sigurt për këtë."
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr "Ju ndan një hap nga fshirja e një objekti prej koleksionit të një përdoruesi tjetër. Hapni sytë."
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr "E fshitë koleksionin \"%s\""
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr "Koleksioni nuk u fshi ngaqë, nuk pohuat se jeni të sigurt për këtë."
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr "Ju ndan një hap nga fshirja e koleksionit të një përdoruesi tjetër. Hapni sytë."
diff --git a/mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.mo
index f6918f71..5564d35d 100644
--- a/mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.po
index d482151d..fcf8a666 100644
--- a/mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-05 00:04+0000\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-05-27 18:54+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: Serbian (http://www.transifex.com/projects/p/mediagoblin/language/sr/)\n"
"MIME-Version: 1.0\n"
@@ -18,32 +18,37 @@ msgstr ""
"Language: sr\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
+#: mediagoblin/auth/forms.py:26
+msgid "Username"
msgstr ""
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
+msgid "Password"
msgstr ""
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
+#: mediagoblin/auth/forms.py:34
+msgid "Email address"
msgstr ""
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
-msgid "Username"
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
msgstr ""
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
-msgid "Password"
+#: mediagoblin/auth/forms.py:52
+msgid "Username or email"
msgstr ""
-#: mediagoblin/auth/forms.py:60
-msgid "Email address"
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
msgstr ""
-#: mediagoblin/auth/forms.py:78
-msgid "Username or email"
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
msgstr ""
#: mediagoblin/auth/views.py:54
@@ -58,54 +63,54 @@ msgstr ""
msgid "Sorry, a user with that email address already exists."
msgstr ""
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr ""
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr ""
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr ""
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr ""
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr ""
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
msgstr ""
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
msgstr ""
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
msgstr ""
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr ""
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
msgstr ""
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -116,7 +121,7 @@ msgid "Description of this work"
msgstr ""
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -132,11 +137,11 @@ msgstr ""
msgid "Separate tags by commas."
msgstr ""
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr ""
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr ""
@@ -164,45 +169,45 @@ msgid "This address contains errors"
msgstr ""
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr ""
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr ""
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr ""
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
msgstr ""
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
msgstr ""
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr ""
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr ""
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr ""
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr ""
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr ""
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr ""
@@ -227,44 +232,63 @@ msgstr ""
msgid "Profile changes saved"
msgstr ""
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr ""
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr ""
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
msgstr ""
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr ""
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr ""
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr ""
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr ""
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
@@ -272,12 +296,16 @@ msgid ""
"domain."
msgstr ""
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr ""
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr ""
+
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr ""
@@ -344,7 +372,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
msgstr ""
@@ -363,7 +391,7 @@ msgstr ""
msgid "Add"
msgstr ""
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr ""
@@ -371,45 +399,45 @@ msgstr ""
msgid "File"
msgstr ""
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr ""
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr ""
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -417,72 +445,25 @@ msgstr ""
msgid "Media processing panel"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr ""
@@ -588,6 +569,53 @@ msgid ""
"%(verification_url)s"
msgstr ""
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -600,13 +628,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
msgstr ""
@@ -623,12 +651,22 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr ""
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
@@ -639,7 +677,7 @@ msgid "Yes, really delete my account"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr ""
@@ -656,7 +694,11 @@ msgstr ""
msgid "Changing %(username)s's account settings"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
msgstr ""
@@ -681,6 +723,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -705,6 +748,7 @@ msgid ""
msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr ""
@@ -713,6 +757,7 @@ msgstr ""
msgid "WebM file (Vorbis codec)"
msgstr ""
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -723,6 +768,10 @@ msgstr ""
msgid "Image for %(media_title)s"
msgstr ""
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
msgstr ""
@@ -821,7 +870,7 @@ msgstr ""
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr ""
@@ -864,23 +913,27 @@ msgstr ""
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
+#, python-format
+msgid "%(formatted_time)s ago"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
-#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
@@ -1037,7 +1090,7 @@ msgstr ""
msgid "Tagged with"
msgstr ""
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr ""
@@ -1067,6 +1120,30 @@ msgid ""
" deleted."
msgstr ""
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr ""
+
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
msgstr ""
@@ -1098,73 +1175,77 @@ msgstr ""
msgid "Include a note"
msgstr ""
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
msgstr ""
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr ""
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr ""
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr ""
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr ""
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr ""
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr ""
diff --git a/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.mo
index 28ea51f8..3b961e60 100644
--- a/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.po
index 76bda505..659de21b 100644
--- a/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.po
@@ -3,14 +3,14 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
-# <simon@ingenmansland.se>, 2011.
-# <transifex@wandborg.se>, 2011, 2012.
+# ingenman <simon@ingenmansland.se>, 2011
+# joar <transifex@wandborg.se>, 2011, 2012
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-05 00:04+0000\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-05-27 18:54+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: Swedish (http://www.transifex.com/projects/p/mediagoblin/language/sv/)\n"
"MIME-Version: 1.0\n"
@@ -20,34 +20,39 @@ msgstr ""
"Language: sv\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
+#: mediagoblin/auth/forms.py:26
msgid "Username"
msgstr "Användarnamn"
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
msgid "Password"
msgstr "Lösenord"
-#: mediagoblin/auth/forms.py:60
+#: mediagoblin/auth/forms.py:34
msgid "Email address"
msgstr "E-postadress"
-#: mediagoblin/auth/forms.py:78
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
+msgstr ""
+
+#: mediagoblin/auth/forms.py:52
msgid "Username or email"
msgstr ""
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr ""
+
#: mediagoblin/auth/views.py:54
msgid "Sorry, registration is disabled on this instance."
msgstr "Vi beklagar, registreringen är avtängd på den här instansen."
@@ -60,54 +65,54 @@ msgstr "En användare med det användarnamnet finns redan."
msgid "Sorry, a user with that email address already exists."
msgstr "Det finns redan en användare med den e-postadressen."
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr "Din e-postadress är verifierad. Du kan nu logga in, redigera din profil och ladda upp filer!"
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr "Verifieringsnyckeln eller användar-IDt är fel."
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr "Du måste vara inloggad för att vi ska kunna skicka meddelandet till dig."
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr "Du har redan verifierat din e-postadress!"
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr "Skickade ett nytt verifierings-email."
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
msgstr ""
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
msgstr ""
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
msgstr ""
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr "Kunde inte skicka e-poståterställning av lösenord eftersom ditt användarnamn är inaktivt eller kontots e-postadress har inte verifierats."
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
msgstr ""
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -118,7 +123,7 @@ msgid "Description of this work"
msgstr "Beskrivning av verket"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -134,11 +139,11 @@ msgstr "Taggar"
msgid "Separate tags by commas."
msgstr ""
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "Sökvägsnamn"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "Sökvägsnamnet kan inte vara tomt"
@@ -166,45 +171,45 @@ msgid "This address contains errors"
msgstr ""
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr "Tidigare lösenord"
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr ""
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr ""
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
msgstr ""
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
msgstr ""
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr ""
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr ""
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr ""
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr "Tidigare lösenord"
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr ""
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr ""
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr "Ett inlägg med det sökvägsnamnet existerar redan."
@@ -229,44 +234,63 @@ msgstr "Var försiktig, du redigerar en annan användares profil."
msgid "Profile changes saved"
msgstr ""
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr "Fel lösenord"
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr ""
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
msgstr ""
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr ""
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr "Fel lösenord"
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr ""
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr ""
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
@@ -274,12 +298,16 @@ msgid ""
"domain."
msgstr ""
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr ""
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr ""
+
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr ""
@@ -346,7 +374,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
msgstr ""
@@ -365,7 +393,7 @@ msgstr ""
msgid "Add"
msgstr ""
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr "Ogiltig fil för mediatypen."
@@ -373,45 +401,45 @@ msgstr "Ogiltig fil för mediatypen."
msgid "File"
msgstr "Fil"
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr "Du måste ange en fil"
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr "Tjohoo! Upladdat!"
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr "Verifiera din e-postadress"
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr "Logga in"
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -419,72 +447,25 @@ msgstr ""
msgid "Media processing panel"
msgstr "Mediabehandlingspanel"
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr "Lägg till media"
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr "Utforska"
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr "Hej, välkommen till den här MediaGoblin-sidan!"
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr "Har du inte ett redan?"
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr "Senast medier"
@@ -590,6 +571,53 @@ msgid ""
"%(verification_url)s"
msgstr "Hej %(username)s,\n\nöppna den följande webbadressen i din webbläsare för att aktivera ditt konto på GNU MediaGoblin:\n\n%(verification_url)s"
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr "Utforska"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "Hej, välkommen till den här MediaGoblin-sidan!"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr "Har du inte ett redan?"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -602,13 +630,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
msgstr ""
@@ -625,12 +653,22 @@ msgstr "Avbryt"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr "Spara ändringar"
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
@@ -641,7 +679,7 @@ msgid "Yes, really delete my account"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr ""
@@ -658,7 +696,11 @@ msgstr "Redigerar %(media_title)s"
msgid "Changing %(username)s's account settings"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
msgstr ""
@@ -683,6 +725,7 @@ msgstr "Media taggat med: %(tag_name)s"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -707,6 +750,7 @@ msgid ""
msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr ""
@@ -715,6 +759,7 @@ msgstr ""
msgid "WebM file (Vorbis codec)"
msgstr ""
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -725,6 +770,10 @@ msgstr ""
msgid "Image for %(media_title)s"
msgstr ""
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
msgstr ""
@@ -823,7 +872,7 @@ msgstr "Vill du verkligen radera %(title)s?"
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr ""
@@ -866,23 +915,27 @@ msgstr "<a href=\"%(user_url)s\">%(username)s</a>s media"
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
+#, python-format
+msgid "%(formatted_time)s ago"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
-#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
@@ -1039,7 +1092,7 @@ msgstr ""
msgid "Tagged with"
msgstr ""
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr ""
@@ -1069,6 +1122,30 @@ msgid ""
" deleted."
msgstr ""
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr ""
+
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
msgstr ""
@@ -1100,73 +1177,77 @@ msgstr ""
msgid "Include a note"
msgstr ""
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
msgstr ""
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr ""
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr ""
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr ""
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr ""
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr "Du tänker radera en annan användares media. Var försiktig."
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr ""
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr ""
diff --git a/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.mo
index 8cef4593..6e7ebd21 100644
--- a/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.po
index 3586ee78..b0bf1aa1 100644
--- a/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.po
@@ -3,15 +3,15 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
-# వీవెనౠ<veeven@gmail.com>, 2011.
+# వీవెనౠ<veeven@gmail.com>, 2011
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-05 00:04+0000\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-05-27 18:54+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language-Team: Telugu (http://www.transifex.com/projects/p/mediagoblin/language/te/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -19,34 +19,39 @@ msgstr ""
"Language: te\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
+#: mediagoblin/auth/forms.py:26
msgid "Username"
msgstr "వాడà±à°•à°°à°¿ పేరà±"
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
msgid "Password"
msgstr "సంకేతపదం"
-#: mediagoblin/auth/forms.py:60
+#: mediagoblin/auth/forms.py:34
msgid "Email address"
msgstr "ఈమెయిలౠచిరà±à°¨à°¾à°®à°¾"
-#: mediagoblin/auth/forms.py:78
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
+msgstr ""
+
+#: mediagoblin/auth/forms.py:52
msgid "Username or email"
msgstr ""
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr ""
+
#: mediagoblin/auth/views.py:54
msgid "Sorry, registration is disabled on this instance."
msgstr ""
@@ -59,54 +64,54 @@ msgstr ""
msgid "Sorry, a user with that email address already exists."
msgstr ""
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr ""
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr ""
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr ""
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr ""
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr ""
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
msgstr ""
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
msgstr ""
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
msgstr ""
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr ""
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
msgstr ""
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -117,7 +122,7 @@ msgid "Description of this work"
msgstr ""
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -133,11 +138,11 @@ msgstr ""
msgid "Separate tags by commas."
msgstr ""
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr ""
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr ""
@@ -165,45 +170,45 @@ msgid "This address contains errors"
msgstr ""
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr ""
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr ""
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr ""
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
msgstr ""
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
msgstr ""
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr ""
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr ""
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr ""
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr ""
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr ""
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr ""
@@ -228,44 +233,63 @@ msgstr ""
msgid "Profile changes saved"
msgstr ""
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr ""
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr ""
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
msgstr ""
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr ""
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr ""
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr ""
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr ""
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
@@ -273,12 +297,16 @@ msgid ""
"domain."
msgstr ""
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr ""
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr ""
+
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr ""
@@ -345,7 +373,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
msgstr ""
@@ -364,7 +392,7 @@ msgstr ""
msgid "Add"
msgstr ""
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr ""
@@ -372,45 +400,45 @@ msgstr ""
msgid "File"
msgstr ""
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr ""
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr ""
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -418,72 +446,25 @@ msgstr ""
msgid "Media processing panel"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr ""
@@ -589,6 +570,53 @@ msgid ""
"%(verification_url)s"
msgstr ""
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -601,13 +629,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
msgstr ""
@@ -624,12 +652,22 @@ msgstr "à°°à°¦à±à°¦à±à°šà±‡à°¯à°¿"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr "మారà±à°ªà±à°²à°¨à± à°­à°¦à±à°°à°ªà°°à°šà±"
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
@@ -640,7 +678,7 @@ msgid "Yes, really delete my account"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr ""
@@ -657,7 +695,11 @@ msgstr ""
msgid "Changing %(username)s's account settings"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
msgstr ""
@@ -682,6 +724,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -706,6 +749,7 @@ msgid ""
msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr ""
@@ -714,6 +758,7 @@ msgstr ""
msgid "WebM file (Vorbis codec)"
msgstr ""
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -724,6 +769,10 @@ msgstr ""
msgid "Image for %(media_title)s"
msgstr ""
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
msgstr ""
@@ -822,7 +871,7 @@ msgstr ""
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr ""
@@ -865,23 +914,27 @@ msgstr ""
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
+#, python-format
+msgid "%(formatted_time)s ago"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
-#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
@@ -1038,7 +1091,7 @@ msgstr ""
msgid "Tagged with"
msgstr ""
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr ""
@@ -1068,6 +1121,30 @@ msgid ""
" deleted."
msgstr ""
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr ""
+
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
msgstr ""
@@ -1099,73 +1176,77 @@ msgstr ""
msgid "Include a note"
msgstr ""
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
msgstr ""
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr ""
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr ""
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr ""
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr ""
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr ""
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr ""
diff --git a/mediagoblin/i18n/tr_TR/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/tr_TR/LC_MESSAGES/mediagoblin.mo
new file mode 100644
index 00000000..4341870b
--- /dev/null
+++ b/mediagoblin/i18n/tr_TR/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/tr_TR/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/tr_TR/LC_MESSAGES/mediagoblin.po
new file mode 100644
index 00000000..4155520f
--- /dev/null
+++ b/mediagoblin/i18n/tr_TR/LC_MESSAGES/mediagoblin.po
@@ -0,0 +1,1252 @@
+# Translations template for PROJECT.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+#
+# Translators:
+# Caner BAÅžARAN <basaran.caner@gmail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: GNU MediaGoblin\n"
+"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-06-06 15:44+0000\n"
+"Last-Translator: Caner BAÅžARAN <basaran.caner@gmail.com>\n"
+"Language-Team: Turkish (Turkey) (http://www.transifex.com/projects/p/mediagoblin/language/tr_TR/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 0.9.6\n"
+"Language: tr_TR\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: mediagoblin/auth/forms.py:26
+msgid "Username"
+msgstr "Kullanıcı adı"
+
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
+msgid "Password"
+msgstr "Parola"
+
+#: mediagoblin/auth/forms.py:34
+msgid "Email address"
+msgstr "E-posta adresi"
+
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
+msgstr "Kullanıcı adı veya E-posta"
+
+#: mediagoblin/auth/forms.py:52
+msgid "Username or email"
+msgstr "Kullanıcı adı ya da e-posta"
+
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr ""
+
+#: mediagoblin/auth/views.py:54
+msgid "Sorry, registration is disabled on this instance."
+msgstr "Üzgünüz, bu durumda kayıt devre dışıdır."
+
+#: mediagoblin/auth/views.py:68
+msgid "Sorry, a user with that name already exists."
+msgstr "Maalesef, bu isimde bir kullanıcı mevcut."
+
+#: mediagoblin/auth/views.py:72
+msgid "Sorry, a user with that email address already exists."
+msgstr "Üzgünüz, bu e-posta adresine sahip bir kullanıcı zaten var."
+
+#: mediagoblin/auth/views.py:182
+msgid ""
+"Your email address has been verified. You may now login, edit your profile, "
+"and submit images!"
+msgstr "E-posta adresiniz doğrulandı. Şimdi giriş yapabilir, profilinizi düzenleyip ve yeni görüntüleri gönderebilirsiniz!"
+
+#: mediagoblin/auth/views.py:188
+msgid "The verification key or user id is incorrect"
+msgstr "Doğrulama anahtarı veya kullanıcı kimliği yanlış"
+
+#: mediagoblin/auth/views.py:206
+msgid "You must be logged in so we know who to send the email to!"
+msgstr ""
+
+#: mediagoblin/auth/views.py:214
+msgid "You've already verified your email address!"
+msgstr "Zaten e-posta adresinizi doğruladınız!"
+
+#: mediagoblin/auth/views.py:227
+msgid "Resent your verification email."
+msgstr "Doğrulama e-postasını tekrar yolla."
+
+#: mediagoblin/auth/views.py:258
+msgid ""
+"If that email address (case sensitive!) is registered an email has been sent"
+" with instructions on how to change your password."
+msgstr ""
+
+#: mediagoblin/auth/views.py:269
+msgid "Couldn't find someone with that username."
+msgstr ""
+
+#: mediagoblin/auth/views.py:272
+msgid ""
+"An email has been sent with instructions on how to change your password."
+msgstr "Parolanızı nasıl değiştireceğinizle ilgili adımları anlatan bir e-posta gönderildi."
+
+#: mediagoblin/auth/views.py:279
+msgid ""
+"Could not send password recovery email as your username is inactive or your "
+"account's email address has not been verified."
+msgstr ""
+
+#: mediagoblin/auth/views.py:336
+msgid "You can now log in using your new password."
+msgstr "Şimdi yeni parolanızı giriş için kullanabilirsiniz."
+
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
+#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
+#: mediagoblin/user_pages/forms.py:45
+msgid "Title"
+msgstr "Başlık"
+
+#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31
+msgid "Description of this work"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
+#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
+msgid ""
+"You can use\n"
+" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n"
+" Markdown</a> for formatting."
+msgstr ""
+
+#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36
+msgid "Tags"
+msgstr "Etiketler"
+
+#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38
+msgid "Separate tags by commas."
+msgstr "Etikerleri virgül ile ayırın."
+
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
+msgid "Slug"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
+msgid "The slug can't be empty"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:40
+msgid ""
+"The title part of this media's address. You usually don't need to change "
+"this."
+msgstr ""
+
+#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41
+#: mediagoblin/templates/mediagoblin/utils/license.html:20
+msgid "License"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:50
+msgid "Bio"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:56
+msgid "Website"
+msgstr "Web sitesi"
+
+#: mediagoblin/edit/forms.py:58
+msgid "This address contains errors"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:63
+msgid "License preference"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:69
+msgid "This will be your default license on upload forms."
+msgstr ""
+
+#: mediagoblin/edit/forms.py:71
+msgid "Email me when others comment on my media"
+msgstr "Medyama birisi yorum yazdığında bana e-posta at"
+
+#: mediagoblin/edit/forms.py:83
+msgid "The title can't be empty"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
+#: mediagoblin/user_pages/forms.py:48
+msgid "Description of this collection"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:92
+msgid ""
+"The title part of this collection's address. You usually don't need to "
+"change this."
+msgstr ""
+
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr "Eski parola"
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr ""
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr "Yeni parola"
+
+#: mediagoblin/edit/views.py:67
+msgid "An entry with that slug already exists for this user."
+msgstr ""
+
+#: mediagoblin/edit/views.py:85
+msgid "You are editing another user's media. Proceed with caution."
+msgstr "Başka bir kullanıcının medyasını düzenlerken dikkatli davranın."
+
+#: mediagoblin/edit/views.py:155
+#, python-format
+msgid "You added the attachment %s!"
+msgstr ""
+
+#: mediagoblin/edit/views.py:182
+msgid "You can only edit your own profile."
+msgstr ""
+
+#: mediagoblin/edit/views.py:188
+msgid "You are editing a user's profile. Proceed with caution."
+msgstr "Başka bir kullanıcının profilini düzenlerken dikkatli davranın."
+
+#: mediagoblin/edit/views.py:204
+msgid "Profile changes saved"
+msgstr "Profil deÄŸiÅŸiklikleri kaydedildi"
+
+#: mediagoblin/edit/views.py:240
+msgid "Account settings saved"
+msgstr "Hesap ayarları kaydedildi"
+
+#: mediagoblin/edit/views.py:274
+msgid "You need to confirm the deletion of your account."
+msgstr ""
+
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
+#, python-format
+msgid "You already have a collection called \"%s\"!"
+msgstr ""
+
+#: mediagoblin/edit/views.py:314
+msgid "A collection with that slug already exists for this user."
+msgstr ""
+
+#: mediagoblin/edit/views.py:329
+msgid "You are editing another user's collection. Proceed with caution."
+msgstr ""
+
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr "Yanlış parola"
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr "Parolanız başarılı bir şekilde değiştirildi"
+
+#: mediagoblin/gmg_commands/assetlink.py:60
+msgid "Cannot link theme... no theme set\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:73
+msgid "No asset directory for this theme\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:76
+msgid "However, old link directory symlink found; removed.\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr ""
+
+#: mediagoblin/meddleware/csrf.py:134
+msgid ""
+"CSRF cookie not present. This is most likely the result of a cookie blocker "
+"or somesuch.<br/>Make sure to permit the settings of cookies for this "
+"domain."
+msgstr ""
+
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
+msgid "Sorry, I don't support that file type :("
+msgstr "Üzgünüz, bu tip dosyaları desteklemiyoruz :("
+
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr ""
+
+#: mediagoblin/media_types/video/processing.py:37
+msgid "Video transcoding failed"
+msgstr ""
+
+#: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24
+msgid "Location"
+msgstr ""
+
+#: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:52
+#, python-format
+msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
+msgstr ""
+
+#: mediagoblin/plugins/oauth/forms.py:29
+msgid "Allow"
+msgstr ""
+
+#: mediagoblin/plugins/oauth/forms.py:30
+msgid "Deny"
+msgstr ""
+
+#: mediagoblin/plugins/oauth/forms.py:34
+msgid "Name"
+msgstr ""
+
+#: mediagoblin/plugins/oauth/forms.py:35
+msgid "The name of the OAuth client"
+msgstr ""
+
+#: mediagoblin/plugins/oauth/forms.py:36
+msgid "Description"
+msgstr ""
+
+#: mediagoblin/plugins/oauth/forms.py:38
+msgid ""
+"This will be visible to users allowing your\n"
+" application to authenticate as them."
+msgstr ""
+
+#: mediagoblin/plugins/oauth/forms.py:40
+msgid "Type"
+msgstr "Tür"
+
+#: mediagoblin/plugins/oauth/forms.py:45
+msgid ""
+"<strong>Confidential</strong> - The client can\n"
+" make requests to the GNU MediaGoblin instance that can not be\n"
+" intercepted by the user agent (e.g. server-side client).<br />\n"
+" <strong>Public</strong> - The client can't make confidential\n"
+" requests to the GNU MediaGoblin instance (e.g. client-side\n"
+" JavaScript client)."
+msgstr ""
+
+#: mediagoblin/plugins/oauth/forms.py:52
+msgid "Redirect URI"
+msgstr ""
+
+#: mediagoblin/plugins/oauth/forms.py:54
+msgid ""
+"The redirect URI for the applications, this field\n"
+" is <strong>required</strong> for public clients."
+msgstr ""
+
+#: mediagoblin/plugins/oauth/forms.py:66
+msgid "This field is required for public clients"
+msgstr ""
+
+#: mediagoblin/plugins/oauth/views.py:56
+msgid "The client {0} has been registered!"
+msgstr ""
+
+#: mediagoblin/plugins/oauth/templates/oauth/client/connections.html:22
+msgid "OAuth client connections"
+msgstr ""
+
+#: mediagoblin/plugins/oauth/templates/oauth/client/list.html:22
+msgid "Your OAuth clients"
+msgstr ""
+
+#: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29
+#: mediagoblin/templates/mediagoblin/submit/collection.html:30
+#: mediagoblin/templates/mediagoblin/submit/start.html:34
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68
+msgid "Add"
+msgstr "Ekle"
+
+#: mediagoblin/processing/__init__.py:193
+msgid "Invalid file given for media type."
+msgstr "Bu medya türü için geçersiz dosya türü."
+
+#: mediagoblin/submit/forms.py:26
+msgid "File"
+msgstr "Dosya"
+
+#: mediagoblin/submit/views.py:49
+msgid "You must provide a file."
+msgstr "Bir dosya sağlamanız gerekir."
+
+#: mediagoblin/submit/views.py:93
+msgid "Woohoo! Submitted!"
+msgstr "Hoooop! Gönderildi!"
+
+#: mediagoblin/submit/views.py:144
+#, python-format
+msgid "Collection \"%s\" added!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/base.html:67
+msgid "Verify your email!"
+msgstr "E-postanızı doğrulayın!"
+
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "log out"
+msgstr "çıkış"
+
+#: mediagoblin/templates/mediagoblin/base.html:73
+#: mediagoblin/templates/mediagoblin/auth/login.html:28
+#: mediagoblin/templates/mediagoblin/auth/login.html:36
+#: mediagoblin/templates/mediagoblin/auth/login.html:54
+msgid "Log in"
+msgstr "GiriÅŸ"
+
+#: mediagoblin/templates/mediagoblin/base.html:82
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/base.html:89
+msgid "Change account settings"
+msgstr "Hesap ayarlarını değiştir"
+
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
+#: mediagoblin/templates/mediagoblin/admin/panel.html:21
+#: mediagoblin/templates/mediagoblin/admin/panel.html:26
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26
+msgid "Media processing panel"
+msgstr "Madya iÅŸlem paneli"
+
+#: mediagoblin/templates/mediagoblin/base.html:96
+msgid "Log out"
+msgstr "Çıkış"
+
+#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
+msgid "Add media"
+msgstr "Medya ekle"
+
+#: mediagoblin/templates/mediagoblin/base.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
+msgid "Create new collection"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/error.html:24
+msgid "Image of goblin stressing out"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:32
+msgid "Most recent media"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/admin/panel.html:29
+msgid ""
+"Here you can track the state of media being processed on this instance."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/admin/panel.html:32
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32
+msgid "Media in-processing"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/admin/panel.html:58
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56
+msgid "No media in-processing"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/admin/panel.html:61
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59
+msgid "These uploads failed to process:"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/admin/panel.html:90
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86
+msgid "No failed entries!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/admin/panel.html:92
+msgid "Last 10 successful uploads"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/admin/panel.html:112
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107
+msgid "No processed entries, yet!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36
+msgid "Set your new password"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39
+msgid "Set password"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31
+msgid "Recover password"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34
+msgid "Send instructions"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19
+#, python-format
+msgid ""
+"Hi %(username)s,\n"
+"\n"
+"to change your GNU MediaGoblin password, open the following URL in \n"
+"your web browser:\n"
+"\n"
+"%(verification_url)s\n"
+"\n"
+"If you think this is an error, just ignore this email and continue being\n"
+"a happy goblin!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:39
+msgid "Logging in failed!"
+msgstr "Giriş başarısız!"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:44
+msgid "Don't have an account yet?"
+msgstr "Hala hesabınız yok mu?"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:45
+msgid "Create one here!"
+msgstr "Åžimdi oluÅŸturun!"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:51
+msgid "Forgot your password?"
+msgstr "Parolanı mı unuttun?"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:28
+#: mediagoblin/templates/mediagoblin/auth/register.html:36
+msgid "Create an account!"
+msgstr "Hesap oluÅŸtur!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:40
+msgid "Create"
+msgstr "OluÅŸtur"
+
+#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19
+#, python-format
+msgid ""
+"Hi %(username)s,\n"
+"\n"
+"to activate your GNU MediaGoblin account, open the following URL in\n"
+"your web browser:\n"
+"\n"
+"%(verification_url)s"
+msgstr "Merhaba %(username)s,\n\nGNU MediaGoblin hesabınızı etkinleştirmek için, lütfen aşağıdaki\nURL(bağlantı)'yı Web tarayıcınızda açın:\n\n%(verification_url)s"
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr "KeÅŸfet"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/logo.html:23
+#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
+msgid "MediaGoblin logo"
+msgstr "MediaGoblin logo"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:23
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:35
+#, python-format
+msgid "Editing attachments for %(media_title)s"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
+msgid "Attachments"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
+msgid "Add attachment"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:61
+#: mediagoblin/templates/mediagoblin/edit/delete_account.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit.html:41
+#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:32
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:46
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:67
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
+msgid "Cancel"
+msgstr "İptal"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
+#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
+msgid "Save changes"
+msgstr "DeÄŸiÅŸiklikleri kaydet"
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr "Kaydet"
+
+#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
+#, python-format
+msgid "Really delete user '%(user_name)s' and all related media/comments?"
+msgstr "Gerçekten '%(user_name)s' kullanıcısını ve ilgili tüm medya/yorumları silmek istiyor musun?"
+
+#: mediagoblin/templates/mediagoblin/edit/delete_account.html:35
+msgid "Yes, really delete my account"
+msgstr "Evet, gerçekten hesabımı silmek istiyorum"
+
+#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+msgid "Delete permanently"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:23
+#: mediagoblin/templates/mediagoblin/edit/edit.html:35
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "%(media_title)s düzenleme"
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
+#, python-format
+msgid "Changing %(username)s's account settings"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr "Parolanızı değiştirin."
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
+msgid "Delete my account"
+msgstr "Hesabımı sil"
+
+#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29
+#, python-format
+msgid "Editing %(collection_title)s"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:23
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:34
+#, python-format
+msgid "Editing %(username)s's profile"
+msgstr "%(username)s profilini düzenleme"
+
+#: mediagoblin/templates/mediagoblin/listings/collection.html:30
+#: mediagoblin/templates/mediagoblin/listings/collection.html:35
+#: mediagoblin/templates/mediagoblin/listings/tag.html:30
+#: mediagoblin/templates/mediagoblin/listings/tag.html:35
+#, python-format
+msgid "Media tagged with: %(tag_name)s"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
+#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
+#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
+msgid "Download"
+msgstr "İndir"
+
+#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
+msgid "Original"
+msgstr "Özgün"
+
+#: mediagoblin/templates/mediagoblin/media_displays/audio.html:44
+msgid ""
+"Sorry, this audio will not work because \n"
+"\tyour web browser does not support HTML5 \n"
+"\taudio."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/media_displays/audio.html:47
+msgid ""
+"You can get a modern web browser that \n"
+"\tcan play the audio at <a href=\"http://getfirefox.com\">\n"
+"\t http://getfirefox.com</a>!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
+#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
+msgid "Original file"
+msgstr "Özgün dosya"
+
+#: mediagoblin/templates/mediagoblin/media_displays/audio.html:63
+msgid "WebM file (Vorbis codec)"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:105
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:59
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:65
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr "PDF dosya"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
+msgid "Toggle Rotate"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113
+msgid "Perspective"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117
+msgid "Front"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121
+msgid "Top"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125
+msgid "Side"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131
+msgid "WebGL"
+msgstr "WebGL"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138
+msgid "Download model"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146
+msgid "File Format"
+msgstr "Dosya Biçimi"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148
+msgid "Object Height"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/media_displays/video.html:44
+msgid ""
+"Sorry, this video will not work because\n"
+" your web browser does not support HTML5 \n"
+" video."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/media_displays/video.html:47
+msgid ""
+"You can get a modern web browser that \n"
+" can play this video at <a href=\"http://getfirefox.com\">\n"
+" http://getfirefox.com</a>!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/media_displays/video.html:69
+msgid "WebM file (640p; VP8/Vorbis)"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/submit/collection.html:26
+msgid "Add a collection"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:23
+#: mediagoblin/templates/mediagoblin/submit/start.html:30
+msgid "Add your media"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection.html:30
+#, python-format
+msgid "%(collection_title)s (%(username)s's collection)"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection.html:39
+#, python-format
+msgid "%(collection_title)s by <a href=\"%(user_url)s\">%(username)s</a>"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:79
+msgid "Edit"
+msgstr "Düzenle"
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:83
+msgid "Delete"
+msgstr "Si"
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
+#, python-format
+msgid "Really delete %(title)s?"
+msgstr "Gerçekten %(title)s silmek istiyor musun?"
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:31
+#, python-format
+msgid "Really remove %(media_title)s from %(collection_title)s?"
+msgstr "Gerçekten %(collection_title)s %(media_title)s kaldırmak istiyor musun?"
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
+msgid "Remove"
+msgstr "Kaldır"
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:21
+#, python-format
+msgid "%(username)s's collections"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:28
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(username)s</a>'s collections"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19
+#, python-format
+msgid ""
+"Hi %(username)s,\n"
+"%(comment_author)s commented on your post (%(comment_url)s) at %(instance_name)s\n"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30
+#, python-format
+msgid "%(username)s's media"
+msgstr "%(username)s medyası"
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:38
+#, python-format
+msgid ""
+"<a href=\"%(user_url)s\">%(username)s</a>'s media with tag <a "
+"href=\"%(tag_url)s\">%(tag)s</a>"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media"
+msgstr "<a href=\"%(user_url)s\">%(username)s</a> medyası"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:38
+#, python-format
+msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
+msgid "Add a comment"
+msgstr "Bir yorum ekle"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
+msgid "Add this comment"
+msgstr "Bu yorumu ekle"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
+#, python-format
+msgid "%(formatted_time)s ago"
+msgstr "%(formatted_time)s önce"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr "Eklendi"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
+msgstr "OluÅŸturuldu"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40
+#, python-format
+msgid "Add “%(media_title)s†to a collection"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:54
+msgid "+"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:58
+msgid "Add a new collection"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:29
+msgid ""
+"You can track the state of media being processed for your gallery here."
+msgstr "Burada galerinizdeki işlenmekte olan medyanın durumunu takip edebilirsiniz."
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:89
+msgid "Your last 10 successful uploads"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:31
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:89
+#, python-format
+msgid "%(username)s's profile"
+msgstr "%(username)s profili"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:43
+msgid "Sorry, no such user found."
+msgstr "Üzgünüz, böyle bir kullanıcı bulunamadı."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:70
+msgid "Email verification needed"
+msgstr "E-posta doğrulaması gerekli"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:53
+msgid "Almost done! Your account still needs to be activated."
+msgstr "Neredeyse bitti! Hesabınızı etkinleştirmeniz gerekiyor."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:58
+msgid ""
+"An email should arrive in a few moments with instructions on how to do so."
+msgstr "Bunun nasıl yapılacağı ile ilgili talimatlar, birkaç dakika içinde size e-posta ulaşacak."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:62
+msgid "In case it doesn't:"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:65
+msgid "Resend verification email"
+msgstr "Doğrulama e-postası tekrar yolla"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:73
+msgid ""
+"Someone has registered an account with this username, but it still has to be"
+" activated."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:79
+#, python-format
+msgid ""
+"If you are that person but you've lost your verification email, you can <a "
+"href=\"%(login_url)s\">log in</a> and resend it."
+msgstr "Doğrulama e-postasını kaybettiyseniz, <a href=\"%(login_url)s\">giriş</a> yapabilir ve yeniden yollayabilirsiniz."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:96
+msgid "Here's a spot to tell others about yourself."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:100
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:117
+msgid "Edit profile"
+msgstr "Profil düzenle"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:105
+msgid "This user hasn't filled in their profile (yet)."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:124
+msgid "Browse collections"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:137
+#, python-format
+msgid "View all of %(username)s's media"
+msgstr "%(username)s tüm medyasını göster"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:150
+msgid ""
+"This is where your media will appear, but you don't seem to have added "
+"anything yet."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:162
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84
+#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70
+msgid "There doesn't seem to be any media here yet..."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
+msgstr "(kaldır)"
+
+#: mediagoblin/templates/mediagoblin/utils/collections.html:21
+msgid "Collected in"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/utils/collections.html:40
+msgid "Add to a collection"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
+#: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:21
+msgid "feed icon"
+msgstr "besleme simgesi"
+
+#: mediagoblin/templates/mediagoblin/utils/feed_link.html:23
+#: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:23
+msgid "Atom feed"
+msgstr "Atom besleme"
+
+#: mediagoblin/templates/mediagoblin/utils/license.html:25
+msgid "All rights reserved"
+msgstr "Tüm hakları saklıdır"
+
+#: mediagoblin/templates/mediagoblin/utils/pagination.html:39
+msgid "↠Newer"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/utils/pagination.html:45
+msgid "Older →"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/utils/pagination.html:48
+msgid "Go to page:"
+msgstr "Sayfaya git:"
+
+#: mediagoblin/templates/mediagoblin/utils/prev_next.html:28
+#: mediagoblin/templates/mediagoblin/utils/prev_next.html:33
+msgid "newer"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/utils/prev_next.html:39
+#: mediagoblin/templates/mediagoblin/utils/prev_next.html:44
+msgid "older"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/utils/tags.html:20
+msgid "Tagged with"
+msgstr ""
+
+#: mediagoblin/tools/exif.py:83
+msgid "Could not read the image file."
+msgstr ""
+
+#: mediagoblin/tools/response.py:35
+msgid "Oops!"
+msgstr "Amaninnn boo!"
+
+#: mediagoblin/tools/response.py:36
+msgid "An error occured"
+msgstr ""
+
+#: mediagoblin/tools/response.py:51
+msgid "Operation not allowed"
+msgstr ""
+
+#: mediagoblin/tools/response.py:52
+msgid ""
+"Sorry Dave, I can't let you do that!</p><p>You have tried to perform a "
+"function that you are not allowed to. Have you been trying to delete all "
+"user accounts again?"
+msgstr ""
+
+#: mediagoblin/tools/response.py:60
+msgid ""
+"There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure"
+" the address is correct, maybe the page you're looking for has been moved or"
+" deleted."
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr "yıl"
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr "ay"
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr "hafta"
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr "gün"
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr "saat"
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr "dakika"
+
+#: mediagoblin/user_pages/forms.py:23
+msgid "Comment"
+msgstr ""
+
+#: mediagoblin/user_pages/forms.py:25
+msgid ""
+"You can use <a "
+"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for"
+" formatting."
+msgstr ""
+
+#: mediagoblin/user_pages/forms.py:31
+msgid "I am sure I want to delete this"
+msgstr "Bunu silmek için eminim"
+
+#: mediagoblin/user_pages/forms.py:35
+msgid "I am sure I want to remove this item from the collection"
+msgstr ""
+
+#: mediagoblin/user_pages/forms.py:39
+msgid "Collection"
+msgstr ""
+
+#: mediagoblin/user_pages/forms.py:40
+msgid "-- Select --"
+msgstr ""
+
+#: mediagoblin/user_pages/forms.py:42
+msgid "Include a note"
+msgstr ""
+
+#: mediagoblin/user_pages/lib.py:58
+msgid "commented on your post"
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr "Maalesef, yorum devre dışı."
+
+#: mediagoblin/user_pages/views.py:174
+msgid "Oops, your comment was empty."
+msgstr "Amaninnn boo, yorumunuz boÅŸtu."
+
+#: mediagoblin/user_pages/views.py:180
+msgid "Your comment has been posted!"
+msgstr "Yorumunuz gönderildi!"
+
+#: mediagoblin/user_pages/views.py:205
+msgid "Please check your entries and try again."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:245
+msgid "You have to select or add a collection"
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:256
+#, python-format
+msgid "\"%s\" already in collection \"%s\""
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:262
+#, python-format
+msgid "\"%s\" added to collection \"%s\""
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:282
+msgid "You deleted the media."
+msgstr "Medyayı sildiniz."
+
+#: mediagoblin/user_pages/views.py:289
+msgid "The media was not deleted because you didn't check that you were sure."
+msgstr "Medya silinmedi çünkü emin olduğunuzu onaylamadınız."
+
+#: mediagoblin/user_pages/views.py:296
+msgid "You are about to delete another user's media. Proceed with caution."
+msgstr "Başka bir kullanıcının medyasını silerken dikkatli davranın."
+
+#: mediagoblin/user_pages/views.py:370
+msgid "You deleted the item from the collection."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:374
+msgid "The item was not removed because you didn't check that you were sure."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:382
+msgid ""
+"You are about to delete an item from another user's collection. Proceed with"
+" caution."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:415
+#, python-format
+msgid "You deleted the collection \"%s\""
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:422
+msgid ""
+"The collection was not deleted because you didn't check that you were sure."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:430
+msgid ""
+"You are about to delete another user's collection. Proceed with caution."
+msgstr ""
diff --git a/mediagoblin/i18n/zh_CN/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/zh_CN/LC_MESSAGES/mediagoblin.mo
new file mode 100644
index 00000000..1ed5a4f1
--- /dev/null
+++ b/mediagoblin/i18n/zh_CN/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/zh_CN/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/zh_CN/LC_MESSAGES/mediagoblin.po
new file mode 100644
index 00000000..4bb714fe
--- /dev/null
+++ b/mediagoblin/i18n/zh_CN/LC_MESSAGES/mediagoblin.po
@@ -0,0 +1,1256 @@
+# Translations template for PROJECT.
+# Copyright (C) 2013 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+#
+# Translators:
+# <chc@citi.sinica.edu.tw>, 2011
+# cwebber <cwebber@dustycloud.org>, 2013
+# m13253 <m13253@hotmail.com>, 2013
+# medicalwei <medicalwei@gmail.com>, 2012
+# m13253 <m13253@hotmail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: GNU MediaGoblin\n"
+"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-06-16 11:06+0000\n"
+"Last-Translator: m13253 <m13253@hotmail.com>\n"
+"Language-Team: Chinese (China) (http://www.transifex.com/projects/p/mediagoblin/language/zh_CN/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 0.9.6\n"
+"Language: zh_CN\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: mediagoblin/auth/forms.py:26
+msgid "Username"
+msgstr "用户å"
+
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
+msgid "Password"
+msgstr "密ç "
+
+#: mediagoblin/auth/forms.py:34
+msgid "Email address"
+msgstr "电å­é‚®ä»¶åœ°å€"
+
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
+msgstr "ç”¨æˆ·åæˆ–电å­é‚®ä»¶"
+
+#: mediagoblin/auth/forms.py:52
+msgid "Username or email"
+msgstr "ç”¨æˆ·åæˆ–电å­é‚®ä»¶"
+
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr "æ— æ•ˆç”¨æˆ·åæˆ–电å­é‚®ä»¶åœ°å€ã€‚"
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr "此字段ä¸èƒ½å¡«å†™ç”µå­é‚®ä»¶åœ°å€ã€‚"
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr "此字段需填写电å­é‚®ä»¶åœ°å€ã€‚"
+
+#: mediagoblin/auth/views.py:54
+msgid "Sorry, registration is disabled on this instance."
+msgstr "æŠ±æ­‰ï¼Œæœ¬ç«™å·²æš‚åœæ³¨å†Œã€‚"
+
+#: mediagoblin/auth/views.py:68
+msgid "Sorry, a user with that name already exists."
+msgstr "抱歉,该用户å已存在。"
+
+#: mediagoblin/auth/views.py:72
+msgid "Sorry, a user with that email address already exists."
+msgstr "抱歉,已有用户用该电å­é‚®ä»¶æ³¨å†Œã€‚"
+
+#: mediagoblin/auth/views.py:182
+msgid ""
+"Your email address has been verified. You may now login, edit your profile, "
+"and submit images!"
+msgstr "您的电å­é‚®ä»¶åœ°å€å·²è®¤è¯ã€‚您现在å¯ä»¥ç™»å½•ã€ä¿®æ”¹ä¸ªäººèµ„料并上传图片了ï¼"
+
+#: mediagoblin/auth/views.py:188
+msgid "The verification key or user id is incorrect"
+msgstr "验è¯ç é”™è¯¯æˆ–用户 ID 错误"
+
+#: mediagoblin/auth/views.py:206
+msgid "You must be logged in so we know who to send the email to!"
+msgstr "您必须登录以便让我们知é“将电å­é‚®ä»¶å‘ç»™è°"
+
+#: mediagoblin/auth/views.py:214
+msgid "You've already verified your email address!"
+msgstr "您已ç»è®¤è¯è¿‡ç”µå­é‚®ä»¶åœ°å€äº†ï¼"
+
+#: mediagoblin/auth/views.py:227
+msgid "Resent your verification email."
+msgstr "é‡å‘认è¯é‚®ä»¶ã€‚"
+
+#: mediagoblin/auth/views.py:258
+msgid ""
+"If that email address (case sensitive!) is registered an email has been sent"
+" with instructions on how to change your password."
+msgstr "若该邮件地å€ï¼ˆåŒºåˆ†å¤§å°å†™ï¼‰å·²è¢«æ³¨å†Œï¼Œåˆ™å¯†ç ä¿®æ”¹è¯´æ˜Žå·²é€šè¿‡ç”µå­é‚®ä»¶é€è¾¾ã€‚"
+
+#: mediagoblin/auth/views.py:269
+msgid "Couldn't find someone with that username."
+msgstr "找ä¸åˆ°æœ‰è¯¥ç”¨æˆ·å的人。"
+
+#: mediagoblin/auth/views.py:272
+msgid ""
+"An email has been sent with instructions on how to change your password."
+msgstr "密ç ä¿®æ”¹è¯´æ˜Žå·²é€šè¿‡ç”µå­é‚®ä»¶é€è¾¾ã€‚"
+
+#: mediagoblin/auth/views.py:279
+msgid ""
+"Could not send password recovery email as your username is inactive or your "
+"account's email address has not been verified."
+msgstr "无法å‘é€å¯†ç æ‰¾å›žé‚®ä»¶ï¼Œå› ä¸ºæ‚¨çš„ç”¨æˆ·åæœªæ¿€æ´»æˆ–者您账户的电å­é‚®ä»¶åœ°å€æœªè®¤è¯ã€‚"
+
+#: mediagoblin/auth/views.py:336
+msgid "You can now log in using your new password."
+msgstr "您现在å¯ä»¥ç”¨æ–°çš„å¯†ç æ¥ç™»å½•了ï¼"
+
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
+#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
+#: mediagoblin/user_pages/forms.py:45
+msgid "Title"
+msgstr "标题"
+
+#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31
+msgid "Description of this work"
+msgstr "该作å“çš„æè¿°"
+
+#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
+#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
+msgid ""
+"You can use\n"
+" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n"
+" Markdown</a> for formatting."
+msgstr "您å¯ä»¥ç”¨ <a href=\"http://wowubuntu.com/markdown/\">Markdown</a> æ¥æŽ’ç‰ˆã€‚"
+
+#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36
+msgid "Tags"
+msgstr "标签"
+
+#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38
+msgid "Separate tags by commas."
+msgstr "用逗å·åˆ†é𔿠‡ç­¾ã€‚"
+
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
+msgid "Slug"
+msgstr "简称"
+
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
+msgid "The slug can't be empty"
+msgstr "简称ä¸èƒ½ä¸ºç©º"
+
+#: mediagoblin/edit/forms.py:40
+msgid ""
+"The title part of this media's address. You usually don't need to change "
+"this."
+msgstr "该媒体网å€çš„æ ‡é¢˜éƒ¨ä»½ã€‚通常ä¸éœ€è¦ä¿®æ”¹ã€‚"
+
+#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41
+#: mediagoblin/templates/mediagoblin/utils/license.html:20
+msgid "License"
+msgstr "许å¯è¯"
+
+#: mediagoblin/edit/forms.py:50
+msgid "Bio"
+msgstr "个性签å"
+
+#: mediagoblin/edit/forms.py:56
+msgid "Website"
+msgstr "网站"
+
+#: mediagoblin/edit/forms.py:58
+msgid "This address contains errors"
+msgstr "本网å€å‡ºé”™äº†"
+
+#: mediagoblin/edit/forms.py:63
+msgid "License preference"
+msgstr "许å¯è¯å好"
+
+#: mediagoblin/edit/forms.py:69
+msgid "This will be your default license on upload forms."
+msgstr "这将是您上传界é¢çš„默认许å¯è¯ã€‚"
+
+#: mediagoblin/edit/forms.py:71
+msgid "Email me when others comment on my media"
+msgstr "当有人对我的媒体评论时给我电å­é‚®ä»¶"
+
+#: mediagoblin/edit/forms.py:83
+msgid "The title can't be empty"
+msgstr "标题ä¸èƒ½æ˜¯ç©ºçš„"
+
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
+#: mediagoblin/user_pages/forms.py:48
+msgid "Description of this collection"
+msgstr "这个åˆé›†çš„æè¿°"
+
+#: mediagoblin/edit/forms.py:92
+msgid ""
+"The title part of this collection's address. You usually don't need to "
+"change this."
+msgstr "æ­¤åˆé›†ç½‘å€çš„æ ‡é¢˜éƒ¨ä»½ï¼Œé€šå¸¸ä¸éœ€è¦ä¿®æ”¹ã€‚"
+
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr "旧的密ç "
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr "è¾“å…¥æ‚¨çš„æ—§å¯†ç æ¥è¯æ˜Žæ‚¨æ‹¥æœ‰è¿™ä¸ªè´¦æˆ·ã€‚"
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr "新密ç "
+
+#: mediagoblin/edit/views.py:67
+msgid "An entry with that slug already exists for this user."
+msgstr "这个简称已ç»è¢«åˆ«äººç”¨äº†"
+
+#: mediagoblin/edit/views.py:85
+msgid "You are editing another user's media. Proceed with caution."
+msgstr "您正在修改别人的媒体,请å°å¿ƒæ“作。"
+
+#: mediagoblin/edit/views.py:155
+#, python-format
+msgid "You added the attachment %s!"
+msgstr "您加上了附件“%sâ€ï¼"
+
+#: mediagoblin/edit/views.py:182
+msgid "You can only edit your own profile."
+msgstr "您åªèƒ½ä¿®æ”¹è‡ªå·±çš„个人资料"
+
+#: mediagoblin/edit/views.py:188
+msgid "You are editing a user's profile. Proceed with caution."
+msgstr "您正在修改别人的个人资料,请å°å¿ƒæ“作。"
+
+#: mediagoblin/edit/views.py:204
+msgid "Profile changes saved"
+msgstr "个人资料已修改"
+
+#: mediagoblin/edit/views.py:240
+msgid "Account settings saved"
+msgstr "账户设置已ä¿å­˜"
+
+#: mediagoblin/edit/views.py:274
+msgid "You need to confirm the deletion of your account."
+msgstr "您需è¦ç¡®è®¤åˆ é™¤æ‚¨çš„账户。"
+
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
+#, python-format
+msgid "You already have a collection called \"%s\"!"
+msgstr "æ‚¨å·²ç»æœ‰ä¸€ä¸ªç§°åšâ€œ%sâ€çš„åˆé›†äº†ï¼"
+
+#: mediagoblin/edit/views.py:314
+msgid "A collection with that slug already exists for this user."
+msgstr "è¯¥ç”¨æˆ·å·²ç»æœ‰ä½¿ç”¨è¯¥ç®€ç§°çš„åˆé›†äº†ã€‚"
+
+#: mediagoblin/edit/views.py:329
+msgid "You are editing another user's collection. Proceed with caution."
+msgstr "您正在修改别人的åˆé›†ï¼Œè¯·å°å¿ƒæ“作。"
+
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr "密ç é”™è¯¯"
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr "您的密ç å·²æˆåŠŸä¿®æ”¹"
+
+#: mediagoblin/gmg_commands/assetlink.py:60
+msgid "Cannot link theme... no theme set\n"
+msgstr "无法链接到主题……未设置主题\n"
+
+#: mediagoblin/gmg_commands/assetlink.py:73
+msgid "No asset directory for this theme\n"
+msgstr "此主题没有素æç›®å½•\n"
+
+#: mediagoblin/gmg_commands/assetlink.py:76
+msgid "However, old link directory symlink found; removed.\n"
+msgstr "ä½†æ˜¯æ—§çš„ç›®å½•é“¾æŽ¥å·²ç»æ‰¾åˆ°å¹¶ç§»é™¤ã€‚\n"
+
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr "无法链接到“%sâ€ï¼šâ€œ%sâ€å·²å­˜åœ¨ä¸”䏿˜¯é“¾æŽ¥\n"
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr "跳过“%sâ€ï¼›å·²è®¾ç½®è¿‡äº†ã€‚\n"
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr "“%sâ€çš„æ—§é“¾æŽ¥å·²ç»æ‰¾åˆ°å¹¶ç§»é™¤ã€‚\n"
+
+#: mediagoblin/meddleware/csrf.py:134
+msgid ""
+"CSRF cookie not present. This is most likely the result of a cookie blocker "
+"or somesuch.<br/>Make sure to permit the settings of cookies for this "
+"domain."
+msgstr "CSRF cookie ä¸å­˜åœ¨ã€‚很å¯èƒ½æ˜¯ç”±ç±»ä¼¼ cookie å±è”½å™¨é€ æˆçš„。<br />请å…许本域åçš„ cookie 设定。"
+
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
+msgid "Sorry, I don't support that file type :("
+msgstr "æŠ±æ­‰ï¼Œæˆ‘ä¸æ”¯æŒè¿™æ ·çš„æ–‡ä»¶æ ¼å¼ :("
+
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr "无法è¿è¡Œ unoconv,请检查日志"
+
+#: mediagoblin/media_types/video/processing.py:37
+msgid "Video transcoding failed"
+msgstr "视频转ç å¤±è´¥"
+
+#: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:24
+msgid "Location"
+msgstr "ä½ç½®"
+
+#: mediagoblin/plugins/geolocation/templates/mediagoblin/plugins/geolocation/map.html:52
+#, python-format
+msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
+msgstr "在 <a href=\"%(osm_url)s\">OpenStreetMap</a> 上观看"
+
+#: mediagoblin/plugins/oauth/forms.py:29
+msgid "Allow"
+msgstr "å…许"
+
+#: mediagoblin/plugins/oauth/forms.py:30
+msgid "Deny"
+msgstr "æ‹’ç»"
+
+#: mediagoblin/plugins/oauth/forms.py:34
+msgid "Name"
+msgstr "åç§°"
+
+#: mediagoblin/plugins/oauth/forms.py:35
+msgid "The name of the OAuth client"
+msgstr "OAuth client çš„åç§°"
+
+#: mediagoblin/plugins/oauth/forms.py:36
+msgid "Description"
+msgstr "æè¿°"
+
+#: mediagoblin/plugins/oauth/forms.py:38
+msgid ""
+"This will be visible to users allowing your\n"
+" application to authenticate as them."
+msgstr "本æè¿°å°†ä¼šè¢«è¿›è¡Œåº”用程åºè®¤è¯çš„用户看到。"
+
+#: mediagoblin/plugins/oauth/forms.py:40
+msgid "Type"
+msgstr "类型"
+
+#: mediagoblin/plugins/oauth/forms.py:45
+msgid ""
+"<strong>Confidential</strong> - The client can\n"
+" make requests to the GNU MediaGoblin instance that can not be\n"
+" intercepted by the user agent (e.g. server-side client).<br />\n"
+" <strong>Public</strong> - The client can't make confidential\n"
+" requests to the GNU MediaGoblin instance (e.g. client-side\n"
+" JavaScript client)."
+msgstr "<strong>秘密</strong> — OAuth client å¯ä»¥å¯¹ GNU MediaGoblin 站点å‘é€ä¸è¢«ç”¨æˆ·ä»£ç†æ‹¦æˆªçš„请求(例如æœåŠ¡ç«¯ä¸Šçš„ client)。\n<strong>公开</strong> — OAuth client 无法对 GNU MediaGoblin 站点å‘é€ç§˜å¯†çš„请求(例如客户端的 JavaScript client)。"
+
+#: mediagoblin/plugins/oauth/forms.py:52
+msgid "Redirect URI"
+msgstr "é‡å®šå‘ URI"
+
+#: mediagoblin/plugins/oauth/forms.py:54
+msgid ""
+"The redirect URI for the applications, this field\n"
+" is <strong>required</strong> for public clients."
+msgstr "此应用程åºçš„é‡å®šå‘ URI,本字段在公开类型的 OAuth client 为<strong>å¿…å¡«</strong>。"
+
+#: mediagoblin/plugins/oauth/forms.py:66
+msgid "This field is required for public clients"
+msgstr "本字段在公开类型的 OAuth client 为必填"
+
+#: mediagoblin/plugins/oauth/views.py:56
+msgid "The client {0} has been registered!"
+msgstr "OAuth client {0} 注册完æˆï¼"
+
+#: mediagoblin/plugins/oauth/templates/oauth/client/connections.html:22
+msgid "OAuth client connections"
+msgstr "OAuth client 连接"
+
+#: mediagoblin/plugins/oauth/templates/oauth/client/list.html:22
+msgid "Your OAuth clients"
+msgstr "您的 OAuth client"
+
+#: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29
+#: mediagoblin/templates/mediagoblin/submit/collection.html:30
+#: mediagoblin/templates/mediagoblin/submit/start.html:34
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:68
+msgid "Add"
+msgstr "增加"
+
+#: mediagoblin/processing/__init__.py:193
+msgid "Invalid file given for media type."
+msgstr "æä¾›æ–‡ä»¶çš„媒体类型错误。"
+
+#: mediagoblin/submit/forms.py:26
+msgid "File"
+msgstr "文件"
+
+#: mediagoblin/submit/views.py:49
+msgid "You must provide a file."
+msgstr "您必须æä¾›ä¸€ä¸ªæ–‡ä»¶"
+
+#: mediagoblin/submit/views.py:93
+msgid "Woohoo! Submitted!"
+msgstr "啊哈ï¼å·²æäº¤ï¼"
+
+#: mediagoblin/submit/views.py:144
+#, python-format
+msgid "Collection \"%s\" added!"
+msgstr "åˆé›†â€œ%sâ€å·²æ–°å¢žï¼"
+
+#: mediagoblin/templates/mediagoblin/base.html:67
+msgid "Verify your email!"
+msgstr "确认您的电å­é‚®ä»¶ï¼"
+
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "log out"
+msgstr "登出"
+
+#: mediagoblin/templates/mediagoblin/base.html:73
+#: mediagoblin/templates/mediagoblin/auth/login.html:28
+#: mediagoblin/templates/mediagoblin/auth/login.html:36
+#: mediagoblin/templates/mediagoblin/auth/login.html:54
+msgid "Log in"
+msgstr "登录"
+
+#: mediagoblin/templates/mediagoblin/base.html:82
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
+msgstr "<a href=\"%(user_url)s\">%(user_name)s</a> 的账户"
+
+#: mediagoblin/templates/mediagoblin/base.html:89
+msgid "Change account settings"
+msgstr "更改账户设置"
+
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
+#: mediagoblin/templates/mediagoblin/admin/panel.html:21
+#: mediagoblin/templates/mediagoblin/admin/panel.html:26
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:26
+msgid "Media processing panel"
+msgstr "媒体处ç†é¢æ¿"
+
+#: mediagoblin/templates/mediagoblin/base.html:96
+msgid "Log out"
+msgstr "登出"
+
+#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
+msgid "Add media"
+msgstr "新增媒体"
+
+#: mediagoblin/templates/mediagoblin/base.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
+msgid "Create new collection"
+msgstr "新增åˆé›†"
+
+#: mediagoblin/templates/mediagoblin/error.html:24
+msgid "Image of goblin stressing out"
+msgstr "满脸问å·çš„哥布林"
+
+#: mediagoblin/templates/mediagoblin/root.html:32
+msgid "Most recent media"
+msgstr "最新的媒体"
+
+#: mediagoblin/templates/mediagoblin/admin/panel.html:29
+msgid ""
+"Here you can track the state of media being processed on this instance."
+msgstr "此处您å¯ä»¥è¿½è¸ªæœ¬ç«™ç‚¹å¤„ç†åª’体的状æ€ã€‚"
+
+#: mediagoblin/templates/mediagoblin/admin/panel.html:32
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32
+msgid "Media in-processing"
+msgstr "媒体处ç†ä¸­"
+
+#: mediagoblin/templates/mediagoblin/admin/panel.html:58
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56
+msgid "No media in-processing"
+msgstr "没有正在处ç†ä¸­çš„媒体"
+
+#: mediagoblin/templates/mediagoblin/admin/panel.html:61
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59
+msgid "These uploads failed to process:"
+msgstr "无法处ç†è¿™äº›ä¸Šä¼ å†…容:"
+
+#: mediagoblin/templates/mediagoblin/admin/panel.html:90
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86
+msgid "No failed entries!"
+msgstr "没有失败的纪录ï¼"
+
+#: mediagoblin/templates/mediagoblin/admin/panel.html:92
+msgid "Last 10 successful uploads"
+msgstr "最近 10 次æˆåŠŸä¸Šä¼ çš„çºªå½•"
+
+#: mediagoblin/templates/mediagoblin/admin/panel.html:112
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107
+msgid "No processed entries, yet!"
+msgstr "现在还没有处ç†çš„纪录ï¼"
+
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36
+msgid "Set your new password"
+msgstr "设置您的新密ç "
+
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39
+msgid "Set password"
+msgstr "设置新密ç "
+
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31
+msgid "Recover password"
+msgstr "找回密ç "
+
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34
+msgid "Send instructions"
+msgstr "å‘逿‰¾å›žå¯†ç è¯´æ˜Ž"
+
+#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19
+#, python-format
+msgid ""
+"Hi %(username)s,\n"
+"\n"
+"to change your GNU MediaGoblin password, open the following URL in \n"
+"your web browser:\n"
+"\n"
+"%(verification_url)s\n"
+"\n"
+"If you think this is an error, just ignore this email and continue being\n"
+"a happy goblin!"
+msgstr "%(username)s 您好:\n\nè¦ä¿®æ”¹ GNU MediaGoblin 的密ç ï¼Œè¯·åœ¨æ‚¨çš„æµè§ˆå™¨ä¸­æ‰“å¼€ä¸‹é¢çš„网å€ï¼š\n\n%(verification_url)s\n\n如果您认为这个是个误会,请忽略此å°ä¿¡ä»¶ï¼Œç»§ç»­å½“个快ä¹çš„哥布林ï¼"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:39
+msgid "Logging in failed!"
+msgstr "登录失败ï¼"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:44
+msgid "Don't have an account yet?"
+msgstr "还没有账户å—?"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:45
+msgid "Create one here!"
+msgstr "在这里建立一个å§ï¼"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:51
+msgid "Forgot your password?"
+msgstr "忘了密ç å—?"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:28
+#: mediagoblin/templates/mediagoblin/auth/register.html:36
+msgid "Create an account!"
+msgstr "建立一个账户ï¼"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:40
+msgid "Create"
+msgstr "建立"
+
+#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19
+#, python-format
+msgid ""
+"Hi %(username)s,\n"
+"\n"
+"to activate your GNU MediaGoblin account, open the following URL in\n"
+"your web browser:\n"
+"\n"
+"%(verification_url)s"
+msgstr "%(username)s 您好:\n\nè¦å¯åЍ GNU MediaGoblin 账户,请在您的æµè§ˆå™¨ä¸­æ‰“开下é¢çš„网å€:\n\n%(verification_url)s"
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr "Powered by <a href=\"http://mediagoblin.org/\" title='Version %(version)s'>MediaGoblin</a>,一个 <a href=\"http://gnu.org/\">GNU</a> 项目。"
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr "以 <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a> 授æƒå‘布。备有<a href=\"%(source_link)s\">æºä»£ç </a>。"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr "探索"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "å˜¿ï¼æ¬¢è¿Žæ¥åˆ° MediaGoblin ç«™ï¼ "
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr "本站使用 <a href=\"http://mediagoblin.org\">MediaGoblin</a>——与众ä¸åŒçš„媒体分享网站。"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr "您å¯ä»¥ç™»å½•您的 MediaGoblin 账户以上传媒体ã€å¼ è´´è¯„论等等。"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr "没有账户å—?开账户很简å•ï¼"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">åœ¨æœ¬ç«™åˆ›å»ºå¸æˆ·</a>\n 或者\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">在您自己的æœåŠ¡å™¨ä¸Šæ­å»º MediaGoblin</a>"
+
+#: mediagoblin/templates/mediagoblin/bits/logo.html:23
+#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
+msgid "MediaGoblin logo"
+msgstr "MediaGoblin 标志"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:23
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:35
+#, python-format
+msgid "Editing attachments for %(media_title)s"
+msgstr "编辑 %(media_title)s 的附件"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
+msgid "Attachments"
+msgstr "附件"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
+msgid "Add attachment"
+msgstr "新增附件"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:61
+#: mediagoblin/templates/mediagoblin/edit/delete_account.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit.html:41
+#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:32
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:46
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:67
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
+msgid "Cancel"
+msgstr "å–æ¶ˆ"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
+#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
+msgid "Save changes"
+msgstr "ä¿å­˜æ›´æ”¹"
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr "修改 %(username)s 的密ç "
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr "ä¿å­˜"
+
+#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
+#, python-format
+msgid "Really delete user '%(user_name)s' and all related media/comments?"
+msgstr "真的è¦åˆ é™¤ç”¨æˆ· %(user_name)s åŠæ‰€æœ‰ç›¸å…³åª’体和评论å—?"
+
+#: mediagoblin/templates/mediagoblin/edit/delete_account.html:35
+msgid "Yes, really delete my account"
+msgstr "是的,真的删除我的账户"
+
+#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+msgid "Delete permanently"
+msgstr "永久删除"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:23
+#: mediagoblin/templates/mediagoblin/edit/edit.html:35
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "编辑 %(media_title)s"
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
+#, python-format
+msgid "Changing %(username)s's account settings"
+msgstr "æ­£åœ¨æ”¹å˜ %(username)s 的账户设置"
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr "修改您的密ç ã€‚"
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
+msgid "Delete my account"
+msgstr "åˆ é™¤æˆ‘çš„å¸æˆ·"
+
+#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29
+#, python-format
+msgid "Editing %(collection_title)s"
+msgstr "编辑 %(collection_title)s"
+
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:23
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:34
+#, python-format
+msgid "Editing %(username)s's profile"
+msgstr "编辑 %(username)s 的个人资料"
+
+#: mediagoblin/templates/mediagoblin/listings/collection.html:30
+#: mediagoblin/templates/mediagoblin/listings/collection.html:35
+#: mediagoblin/templates/mediagoblin/listings/tag.html:30
+#: mediagoblin/templates/mediagoblin/listings/tag.html:35
+#, python-format
+msgid "Media tagged with: %(tag_name)s"
+msgstr "此媒体被标记为:%(tag_name)s"
+
+#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
+#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
+#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
+msgid "Download"
+msgstr "下载"
+
+#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
+msgid "Original"
+msgstr "æºæ–‡ä»¶"
+
+#: mediagoblin/templates/mediagoblin/media_displays/audio.html:44
+msgid ""
+"Sorry, this audio will not work because \n"
+"\tyour web browser does not support HTML5 \n"
+"\taudio."
+msgstr "抱歉,此声音无法播放,因为您的æµè§ˆå™¨ä¸æ”¯æŒ HTML5 音频。"
+
+#: mediagoblin/templates/mediagoblin/media_displays/audio.html:47
+msgid ""
+"You can get a modern web browser that \n"
+"\tcan play the audio at <a href=\"http://getfirefox.com\">\n"
+"\t http://getfirefox.com</a>!"
+msgstr "您å¯ä»¥åœ¨ <a href=\"http://getfirefox.com\">http://getfirefox.com</a> å–å¾—å¯ä»¥æ’­æ”¾æ­¤å£°éŸ³çš„æµè§ˆå™¨ï¼"
+
+#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
+#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
+msgid "Original file"
+msgstr "æºæ–‡ä»¶"
+
+#: mediagoblin/templates/mediagoblin/media_displays/audio.html:63
+msgid "WebM file (Vorbis codec)"
+msgstr "WebM 文件(Vorbis ç¼–ç ï¼‰"
+
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:105
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:59
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:65
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr "%(media_title)s 的照片"
+
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr "PDF 文件"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
+msgid "Toggle Rotate"
+msgstr "åˆ‡æ¢æ—‹è½¬"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113
+msgid "Perspective"
+msgstr "é€è§†"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117
+msgid "Front"
+msgstr "æ­£é¢"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121
+msgid "Top"
+msgstr "é¡¶é¢"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125
+msgid "Side"
+msgstr "ä¾§é¢"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:130
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:131
+msgid "WebGL"
+msgstr "WebGL"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:138
+msgid "Download model"
+msgstr "下载模型"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146
+msgid "File Format"
+msgstr "文件格å¼"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148
+msgid "Object Height"
+msgstr "对象高度"
+
+#: mediagoblin/templates/mediagoblin/media_displays/video.html:44
+msgid ""
+"Sorry, this video will not work because\n"
+" your web browser does not support HTML5 \n"
+" video."
+msgstr "抱歉,此视频无法播放,因为您的æµè§ˆå™¨ä¸æ”¯æŒ HTML5 视频。"
+
+#: mediagoblin/templates/mediagoblin/media_displays/video.html:47
+msgid ""
+"You can get a modern web browser that \n"
+" can play this video at <a href=\"http://getfirefox.com\">\n"
+" http://getfirefox.com</a>!"
+msgstr "您å¯ä»¥åœ¨ <a href=\"http://getfirefox.com\">http://getfirefox.com</a> å–å¾—å¯ä»¥æ’­æ”¾æ­¤è§†é¢‘çš„æµè§ˆå™¨ï¼"
+
+#: mediagoblin/templates/mediagoblin/media_displays/video.html:69
+msgid "WebM file (640p; VP8/Vorbis)"
+msgstr "WebM 文件(640p;VP8/Vorbis)"
+
+#: mediagoblin/templates/mediagoblin/submit/collection.html:26
+msgid "Add a collection"
+msgstr "新增åˆé›†"
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:23
+#: mediagoblin/templates/mediagoblin/submit/start.html:30
+msgid "Add your media"
+msgstr "加入您的媒体"
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection.html:30
+#, python-format
+msgid "%(collection_title)s (%(username)s's collection)"
+msgstr "%(collection_title)s (%(username)s çš„åˆé›†)"
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection.html:39
+#, python-format
+msgid "%(collection_title)s by <a href=\"%(user_url)s\">%(username)s</a>"
+msgstr "%(collection_title)s by <a href=\"%(user_url)s\">%(username)s</a>"
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:79
+msgid "Edit"
+msgstr "编辑"
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:83
+msgid "Delete"
+msgstr "删除"
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
+#, python-format
+msgid "Really delete %(title)s?"
+msgstr "真的è¦åˆ é™¤ %(title)s å—?"
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:31
+#, python-format
+msgid "Really remove %(media_title)s from %(collection_title)s?"
+msgstr "确定è¦ä»Ž %(collection_title)s 移除 %(media_title)s å—?"
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
+msgid "Remove"
+msgstr "移除"
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:21
+#, python-format
+msgid "%(username)s's collections"
+msgstr "%(username)s çš„åˆé›†"
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:28
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(username)s</a>'s collections"
+msgstr "<a href=\"%(user_url)s\">%(username)s</a> çš„åˆé›†"
+
+#: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19
+#, python-format
+msgid ""
+"Hi %(username)s,\n"
+"%(comment_author)s commented on your post (%(comment_url)s) at %(instance_name)s\n"
+msgstr "%(username)s 您好:\n%(comment_author)s 在 %(instance_name)s 对您的内容 (%(comment_url)s) 张贴评论\n"
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30
+#, python-format
+msgid "%(username)s's media"
+msgstr "%(username)s的媒体"
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:38
+#, python-format
+msgid ""
+"<a href=\"%(user_url)s\">%(username)s</a>'s media with tag <a "
+"href=\"%(tag_url)s\">%(tag)s</a>"
+msgstr "<a href=\"%(user_url)s\">%(username)s</a> 的有 <a href=\"%(tag_url)s\">%(tag)s</a> 标签的媒体"
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media"
+msgstr "<a href=\"%(user_url)s\">%(username)s</a> 的媒体"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:38
+#, python-format
+msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
+msgstr "â– æµè§ˆ <a href=\"%(user_url)s\">%(username)s</a> 的媒体"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
+msgid "Add a comment"
+msgstr "新增评论"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
+msgid "Add this comment"
+msgstr "增加评论"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
+#, python-format
+msgid "%(formatted_time)s ago"
+msgstr "%(formatted_time)så‰"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr "已增加"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
+msgstr "已创建"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40
+#, python-format
+msgid "Add “%(media_title)s†to a collection"
+msgstr "把“%(media_title)sâ€åŠ å…¥åˆé›†"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:54
+msgid "+"
+msgstr "+"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:58
+msgid "Add a new collection"
+msgstr "新增新的åˆé›†"
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:29
+msgid ""
+"You can track the state of media being processed for your gallery here."
+msgstr "您å¯ä»¥åœ¨è¿™é‡Œè¿½è¸ªæ‚¨çš„艺廊中媒体处ç†çš„状æ€ã€‚"
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:89
+msgid "Your last 10 successful uploads"
+msgstr "您的最近 10 次æˆåŠŸä¸Šä¼ çš„çºªå½•"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:31
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:89
+#, python-format
+msgid "%(username)s's profile"
+msgstr "%(username)s 的个人资料"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:43
+msgid "Sorry, no such user found."
+msgstr "抱歉,找ä¸åˆ°è¯¥ç”¨æˆ·ã€‚"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:70
+msgid "Email verification needed"
+msgstr "需è¦è®¤è¯ç”µå­é‚®ä»¶åœ°å€"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:53
+msgid "Almost done! Your account still needs to be activated."
+msgstr "快完æˆäº†ï¼ä½†æ‚¨éœ€è¦æ¿€æ´»æ‚¨çš„账户。"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:58
+msgid ""
+"An email should arrive in a few moments with instructions on how to do so."
+msgstr "账户激活说明将在ç¨åŽé€è¾¾ã€‚"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:62
+msgid "In case it doesn't:"
+msgstr "如果ä»ç„¶æ— æ³•认è¯ï¼Œæ‚¨å¯ä»¥ï¼š"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:65
+msgid "Resend verification email"
+msgstr "é‡å‘认è¯é‚®ä»¶"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:73
+msgid ""
+"Someone has registered an account with this username, but it still has to be"
+" activated."
+msgstr "有人用注册了该账户,但是该账户需è¦è¢«å¯ç”¨ã€‚"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:79
+#, python-format
+msgid ""
+"If you are that person but you've lost your verification email, you can <a "
+"href=\"%(login_url)s\">log in</a> and resend it."
+msgstr "如果您就是本人但是未收到认è¯ä¿¡ï¼Œæ‚¨å¯ä»¥<a href=\"%(login_url)s\">登录</a>ç„¶åŽé‡å‘一次。"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:96
+msgid "Here's a spot to tell others about yourself."
+msgstr "这个地方能让您å‘他人介ç»è‡ªå·±ã€‚"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:100
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:117
+msgid "Edit profile"
+msgstr "编辑个人资料"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:105
+msgid "This user hasn't filled in their profile (yet)."
+msgstr "这个用户(还)没有填写个人资料。"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:124
+msgid "Browse collections"
+msgstr "æµè§ˆåˆé›†"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:137
+#, python-format
+msgid "View all of %(username)s's media"
+msgstr "查看 %(username)s 的全部媒体"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:150
+msgid ""
+"This is where your media will appear, but you don't seem to have added "
+"anything yet."
+msgstr "此处是您的媒体会出现的地方,但是似乎还没有加入任何东西。"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:162
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:84
+#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:70
+msgid "There doesn't seem to be any media here yet..."
+msgstr "那里好åƒè¿˜æ²¡æœ‰ä»»ä½•的媒体……"
+
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
+msgstr "(移除)"
+
+#: mediagoblin/templates/mediagoblin/utils/collections.html:21
+msgid "Collected in"
+msgstr "åˆé›†äºŽ"
+
+#: mediagoblin/templates/mediagoblin/utils/collections.html:40
+msgid "Add to a collection"
+msgstr "添加到åˆé›†"
+
+#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
+#: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:21
+msgid "feed icon"
+msgstr "feed 图标"
+
+#: mediagoblin/templates/mediagoblin/utils/feed_link.html:23
+#: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:23
+msgid "Atom feed"
+msgstr "Atom feed"
+
+#: mediagoblin/templates/mediagoblin/utils/license.html:25
+msgid "All rights reserved"
+msgstr "ç‰ˆæƒæ‰€æœ‰"
+
+#: mediagoblin/templates/mediagoblin/utils/pagination.html:39
+msgid "↠Newer"
+msgstr "↠更新的"
+
+#: mediagoblin/templates/mediagoblin/utils/pagination.html:45
+msgid "Older →"
+msgstr "更旧的 →"
+
+#: mediagoblin/templates/mediagoblin/utils/pagination.html:48
+msgid "Go to page:"
+msgstr "跳到页数:"
+
+#: mediagoblin/templates/mediagoblin/utils/prev_next.html:28
+#: mediagoblin/templates/mediagoblin/utils/prev_next.html:33
+msgid "newer"
+msgstr "æ›´æ–°çš„"
+
+#: mediagoblin/templates/mediagoblin/utils/prev_next.html:39
+#: mediagoblin/templates/mediagoblin/utils/prev_next.html:44
+msgid "older"
+msgstr "æ›´æ—§çš„"
+
+#: mediagoblin/templates/mediagoblin/utils/tags.html:20
+msgid "Tagged with"
+msgstr "标签"
+
+#: mediagoblin/tools/exif.py:83
+msgid "Could not read the image file."
+msgstr "无法读å–图片文件。"
+
+#: mediagoblin/tools/response.py:35
+msgid "Oops!"
+msgstr "糟糕ï¼"
+
+#: mediagoblin/tools/response.py:36
+msgid "An error occured"
+msgstr "å‘生错误"
+
+#: mediagoblin/tools/response.py:51
+msgid "Operation not allowed"
+msgstr "æ“作ä¸å…许"
+
+#: mediagoblin/tools/response.py:52
+msgid ""
+"Sorry Dave, I can't let you do that!</p><p>You have tried to perform a "
+"function that you are not allowed to. Have you been trying to delete all "
+"user accounts again?"
+msgstr "对ä¸èµ·è€å…„,我ä¸èƒ½è®©ä½ è¿™æ ·åšï¼</p><p>æ‚¨æ­£åœ¨è¯•ç€æ“作ä¸å…è®¸æ‚¨ä½¿ç”¨çš„åŠŸèƒ½ã€‚æ‚¨éš¾é“æƒ³æ‰“算删除所有用户账户å—?"
+
+#: mediagoblin/tools/response.py:60
+msgid ""
+"There doesn't seem to be a page at this address. Sorry!</p><p>If you're sure"
+" the address is correct, maybe the page you're looking for has been moved or"
+" deleted."
+msgstr "ä¸å¥½æ„æ€ï¼Œçœ‹èµ·æ¥è¿™ä¸ªç½‘å€ä¸Šæ²¡æœ‰ç½‘页。</p><p>å¦‚æžœæ‚¨ç¡®å®šè¿™ä¸ªç½‘å€æ˜¯æ­£ç¡®çš„,您在寻找的页é¢å¯èƒ½å·²ç»ç§»åŠ¨æˆ–æ˜¯è¢«åˆ é™¤äº†ã€‚"
+
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr "å¹´"
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr "月"
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr "周"
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr "æ—¥"
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr "å°æ—¶"
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr "分钟"
+
+#: mediagoblin/user_pages/forms.py:23
+msgid "Comment"
+msgstr "评论"
+
+#: mediagoblin/user_pages/forms.py:25
+msgid ""
+"You can use <a "
+"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for"
+" formatting."
+msgstr "您å¯ä»¥ç”¨ <a href=\"http://wowubuntu.com/markdown/\">Markdown</a> æ¥æŽ’ç‰ˆã€‚"
+
+#: mediagoblin/user_pages/forms.py:31
+msgid "I am sure I want to delete this"
+msgstr "我确定我è¦åˆ é™¤è¿™ä¸ªåª’体"
+
+#: mediagoblin/user_pages/forms.py:35
+msgid "I am sure I want to remove this item from the collection"
+msgstr "我确定我è¦ä»Žåˆé›†ä¸­ç§»é™¤æ­¤é¡¹ç›®"
+
+#: mediagoblin/user_pages/forms.py:39
+msgid "Collection"
+msgstr "åˆé›†"
+
+#: mediagoblin/user_pages/forms.py:40
+msgid "-- Select --"
+msgstr "— 请选择 —"
+
+#: mediagoblin/user_pages/forms.py:42
+msgid "Include a note"
+msgstr "加注"
+
+#: mediagoblin/user_pages/lib.py:58
+msgid "commented on your post"
+msgstr "在您的内容张贴评论"
+
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr "抱歉,ä¸å¼€æ”¾è¯„论。"
+
+#: mediagoblin/user_pages/views.py:174
+msgid "Oops, your comment was empty."
+msgstr "啊,您的评论是空的。"
+
+#: mediagoblin/user_pages/views.py:180
+msgid "Your comment has been posted!"
+msgstr "您的评论已ç»å¼ è´´å®Œæˆï¼"
+
+#: mediagoblin/user_pages/views.py:205
+msgid "Please check your entries and try again."
+msgstr "请检查项目并é‡è¯•。"
+
+#: mediagoblin/user_pages/views.py:245
+msgid "You have to select or add a collection"
+msgstr "您需è¦é€‰æ‹©æˆ–是新增一个åˆé›†"
+
+#: mediagoblin/user_pages/views.py:256
+#, python-format
+msgid "\"%s\" already in collection \"%s\""
+msgstr "“%sâ€å·²ç»åœ¨â€œ%sâ€åˆé›†"
+
+#: mediagoblin/user_pages/views.py:262
+#, python-format
+msgid "\"%s\" added to collection \"%s\""
+msgstr "“%sâ€åŠ å…¥â€œ%sâ€åˆé›†"
+
+#: mediagoblin/user_pages/views.py:282
+msgid "You deleted the media."
+msgstr "您已ç»åˆ é™¤æ­¤åª’体。"
+
+#: mediagoblin/user_pages/views.py:289
+msgid "The media was not deleted because you didn't check that you were sure."
+msgstr "由于您没有勾选确认,该媒体没有被移除。"
+
+#: mediagoblin/user_pages/views.py:296
+msgid "You are about to delete another user's media. Proceed with caution."
+msgstr "您正在删除别人的媒体,请å°å¿ƒæ“作。"
+
+#: mediagoblin/user_pages/views.py:370
+msgid "You deleted the item from the collection."
+msgstr "您已ç»ä»Žè¯¥åˆé›†ä¸­åˆ é™¤è¯¥é¡¹ç›®ã€‚"
+
+#: mediagoblin/user_pages/views.py:374
+msgid "The item was not removed because you didn't check that you were sure."
+msgstr "由于您没有勾选确认,该项目没有被移除。"
+
+#: mediagoblin/user_pages/views.py:382
+msgid ""
+"You are about to delete an item from another user's collection. Proceed with"
+" caution."
+msgstr "您正在从别人的åˆé›†ä¸­åˆ é™¤é¡¹ç›®ï¼Œè¯·å°å¿ƒæ“作。"
+
+#: mediagoblin/user_pages/views.py:415
+#, python-format
+msgid "You deleted the collection \"%s\""
+msgstr "您已ç»åˆ é™¤â€œ%sâ€åˆé›†ã€‚"
+
+#: mediagoblin/user_pages/views.py:422
+msgid ""
+"The collection was not deleted because you didn't check that you were sure."
+msgstr "由于您没有勾选确认,该åˆé›†æ²¡æœ‰è¢«ç§»é™¤ã€‚"
+
+#: mediagoblin/user_pages/views.py:430
+msgid ""
+"You are about to delete another user's collection. Proceed with caution."
+msgstr "您正在删除别人的åˆé›†ï¼Œè¯·å°å¿ƒæ“作。"
diff --git a/mediagoblin/i18n/zh_TW.Big5/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/zh_TW.Big5/LC_MESSAGES/mediagoblin.mo
index d75d2eb2..c234ff00 100644
--- a/mediagoblin/i18n/zh_TW.Big5/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/zh_TW.Big5/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/zh_TW.Big5/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/zh_TW.Big5/LC_MESSAGES/mediagoblin.po
index a5e95640..a7ee8db6 100644
--- a/mediagoblin/i18n/zh_TW.Big5/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/zh_TW.Big5/LC_MESSAGES/mediagoblin.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-05 00:04+0000\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-05-27 18:54+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: Chinese (Taiwan) (Big5) (http://www.transifex.com/projects/p/mediagoblin/language/zh_TW.Big5/)\n"
"MIME-Version: 1.0\n"
@@ -18,32 +18,37 @@ msgstr ""
"Language: zh_TW.Big5\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
+#: mediagoblin/auth/forms.py:26
+msgid "Username"
msgstr ""
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
+msgid "Password"
msgstr ""
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
+#: mediagoblin/auth/forms.py:34
+msgid "Email address"
msgstr ""
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
-msgid "Username"
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
msgstr ""
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
-msgid "Password"
+#: mediagoblin/auth/forms.py:52
+msgid "Username or email"
msgstr ""
-#: mediagoblin/auth/forms.py:60
-msgid "Email address"
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
msgstr ""
-#: mediagoblin/auth/forms.py:78
-msgid "Username or email"
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr ""
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
msgstr ""
#: mediagoblin/auth/views.py:54
@@ -58,54 +63,54 @@ msgstr ""
msgid "Sorry, a user with that email address already exists."
msgstr ""
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr ""
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr ""
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr ""
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr ""
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr ""
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
msgstr ""
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
msgstr ""
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
msgstr ""
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr ""
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
msgstr ""
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -116,7 +121,7 @@ msgid "Description of this work"
msgstr ""
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -132,11 +137,11 @@ msgstr ""
msgid "Separate tags by commas."
msgstr ""
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr ""
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr ""
@@ -164,45 +169,45 @@ msgid "This address contains errors"
msgstr ""
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr ""
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr ""
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr ""
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
msgstr ""
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
msgstr ""
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr ""
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr ""
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr ""
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr ""
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr ""
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr ""
@@ -227,44 +232,63 @@ msgstr ""
msgid "Profile changes saved"
msgstr ""
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr ""
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr ""
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
msgstr ""
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr ""
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr ""
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr ""
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr ""
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr ""
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr ""
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
@@ -272,12 +296,16 @@ msgid ""
"domain."
msgstr ""
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr ""
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr ""
+
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr ""
@@ -344,7 +372,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
msgstr ""
@@ -363,7 +391,7 @@ msgstr ""
msgid "Add"
msgstr ""
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr ""
@@ -371,45 +399,45 @@ msgstr ""
msgid "File"
msgstr ""
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr ""
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr ""
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -417,72 +445,25 @@ msgstr ""
msgid "Media processing panel"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr ""
@@ -588,6 +569,53 @@ msgid ""
"%(verification_url)s"
msgstr ""
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -600,13 +628,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
msgstr ""
@@ -623,12 +651,22 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr ""
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
@@ -639,7 +677,7 @@ msgid "Yes, really delete my account"
msgstr ""
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr ""
@@ -656,7 +694,11 @@ msgstr ""
msgid "Changing %(username)s's account settings"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
msgstr ""
@@ -681,6 +723,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -705,6 +748,7 @@ msgid ""
msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr ""
@@ -713,6 +757,7 @@ msgstr ""
msgid "WebM file (Vorbis codec)"
msgstr ""
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -723,6 +768,10 @@ msgstr ""
msgid "Image for %(media_title)s"
msgstr ""
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
msgstr ""
@@ -821,7 +870,7 @@ msgstr ""
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr ""
@@ -864,23 +913,27 @@ msgstr ""
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
+#, python-format
+msgid "%(formatted_time)s ago"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
-#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
@@ -1037,7 +1090,7 @@ msgstr ""
msgid "Tagged with"
msgstr ""
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr ""
@@ -1067,6 +1120,30 @@ msgid ""
" deleted."
msgstr ""
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr ""
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr ""
+
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
msgstr ""
@@ -1098,73 +1175,77 @@ msgstr ""
msgid "Include a note"
msgstr ""
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
msgstr ""
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr ""
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr ""
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr ""
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr ""
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr ""
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr ""
diff --git a/mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.mo
index 3d267cfc..4b7a2398 100644
--- a/mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.mo
+++ b/mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.mo
Binary files differ
diff --git a/mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.po
index bd50df78..05ecd4b5 100644
--- a/mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.po
@@ -3,17 +3,19 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
-# <chc@citi.sinica.edu.tw>, 2011.
-# Harry Chen <harryhow@gmail.com>, 2011-2012.
-# <medicalwei@gmail.com>, 2012.
+# <chc@citi.sinica.edu.tw>, 2011
+# Harry Chen <harryhow@gmail.com>, 2011-2012
+# medicalwei <medicalwei@gmail.com>, 2013
+# medicalwei <medicalwei@gmail.com>, 2012
+# m13253 <m13253@hotmail.com>, 2013
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2013-03-04 18:04-0600\n"
-"PO-Revision-Date: 2013-03-05 00:04+0000\n"
-"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
+"POT-Creation-Date: 2013-05-27 13:54-0500\n"
+"PO-Revision-Date: 2013-06-16 01:40+0000\n"
+"Last-Translator: m13253 <m13253@hotmail.com>\n"
+"Language-Team: Chinese (Taiwan) (http://www.transifex.com/projects/p/mediagoblin/language/zh_TW/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -21,34 +23,39 @@ msgstr ""
"Language: zh_TW\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-#: mediagoblin/auth/forms.py:28
-msgid "Invalid User name or email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:29
-msgid "This field does not take email addresses."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:30
-msgid "This field requires an email address."
-msgstr ""
-
-#: mediagoblin/auth/forms.py:52 mediagoblin/auth/forms.py:67
+#: mediagoblin/auth/forms.py:26
msgid "Username"
msgstr "使用者å稱"
-#: mediagoblin/auth/forms.py:56 mediagoblin/auth/forms.py:71
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+#: mediagoblin/tests/test_util.py:110
msgid "Password"
msgstr "密碼"
-#: mediagoblin/auth/forms.py:60
+#: mediagoblin/auth/forms.py:34
msgid "Email address"
msgstr "Email ä½å€"
-#: mediagoblin/auth/forms.py:78
+#: mediagoblin/auth/forms.py:41
+msgid "Username or Email"
+msgstr "使用者å稱或 email"
+
+#: mediagoblin/auth/forms.py:52
msgid "Username or email"
msgstr "使用者å稱或 email"
+#: mediagoblin/auth/tools.py:31
+msgid "Invalid User name or email address."
+msgstr "無效的使用者å稱或 email ä½ç½®ã€‚"
+
+#: mediagoblin/auth/tools.py:32
+msgid "This field does not take email addresses."
+msgstr "本欄ä½ä¸æŽ¥å— email ä½ç½®ã€‚"
+
+#: mediagoblin/auth/tools.py:33
+msgid "This field requires an email address."
+msgstr "本欄ä½éœ€è¦ email ä½ç½®ã€‚"
+
#: mediagoblin/auth/views.py:54
msgid "Sorry, registration is disabled on this instance."
msgstr "抱歉,本站已經暫åœè¨»å†Šã€‚"
@@ -61,54 +68,54 @@ msgstr "抱歉,這個使用者å稱已經存在。"
msgid "Sorry, a user with that email address already exists."
msgstr "抱歉,此 email ä½ç½®å·²ç¶“被註冊了。"
-#: mediagoblin/auth/views.py:174
+#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr "您的 email ä½å€å·²è¢«èªè­‰ã€‚您已經å¯ä»¥ç™»å…¥ï¼Œç·¨è¼¯æ‚¨çš„個人檔案並上傳圖片ï¼"
-#: mediagoblin/auth/views.py:180
+#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
msgstr "èªè­‰ç¢¼æˆ–是使用者 ID 錯誤"
-#: mediagoblin/auth/views.py:198
+#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
msgstr "您必須登入,我們æ‰çŸ¥é“ä¿¡è¦é€çµ¦èª°ï¼"
-#: mediagoblin/auth/views.py:206
+#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
msgstr "您的電å­éƒµä»¶å·²ç¶“確èªäº†ï¼"
-#: mediagoblin/auth/views.py:219
+#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
msgstr "é‡é€èªè­‰ä¿¡ã€‚"
-#: mediagoblin/auth/views.py:250
+#: mediagoblin/auth/views.py:258
msgid ""
"If that email address (case sensitive!) is registered an email has been sent"
" with instructions on how to change your password."
-msgstr ""
+msgstr "如果那 email ä½ç½® (請注æ„大å°å¯«) 已經註冊,寫有修改密碼步驟的 email 已經é€å‡ºã€‚"
-#: mediagoblin/auth/views.py:261
+#: mediagoblin/auth/views.py:269
msgid "Couldn't find someone with that username."
-msgstr ""
+msgstr "找ä¸åˆ°ç›¸é—œçš„使用者å稱。"
-#: mediagoblin/auth/views.py:264
+#: mediagoblin/auth/views.py:272
msgid ""
"An email has been sent with instructions on how to change your password."
msgstr "修改密碼的指示已經由電å­éƒµä»¶å¯„é€åˆ°æ‚¨çš„信箱。"
-#: mediagoblin/auth/views.py:271
+#: mediagoblin/auth/views.py:279
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr "無法傳é€å¯†ç¢¼å›žå¾©ä¿¡ä»¶ï¼Œå› ç‚ºæ‚¨çš„使用者å稱已失效或是帳號尚未èªè­‰ã€‚"
-#: mediagoblin/auth/views.py:328
+#: mediagoblin/auth/views.py:336
msgid "You can now log in using your new password."
msgstr "您ç¾åœ¨å¯ä»¥ç”¨æ–°çš„密碼登入了ï¼"
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:82
#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
#: mediagoblin/user_pages/forms.py:45
msgid "Title"
@@ -119,7 +126,7 @@ msgid "Description of this work"
msgstr "這個作å“çš„æè¿°"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:97 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:32
#: mediagoblin/submit/forms.py:51 mediagoblin/user_pages/forms.py:49
msgid ""
"You can use\n"
@@ -135,11 +142,11 @@ msgstr "標籤"
msgid "Separate tags by commas."
msgstr "用逗號分隔標籤。"
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:101
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "簡稱"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:102
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "簡稱ä¸èƒ½ç‚ºç©ºç™½"
@@ -167,45 +174,45 @@ msgid "This address contains errors"
msgstr "本網å€å‡ºéŒ¯äº†"
#: mediagoblin/edit/forms.py:63
-msgid "Old password"
-msgstr "舊的密碼"
-
-#: mediagoblin/edit/forms.py:64
-msgid "Enter your old password to prove you own this account."
-msgstr "è¼¸å…¥æ‚¨çš„èˆŠå¯†ç¢¼ä¾†è­‰æ˜Žæ‚¨æ“æœ‰é€™å€‹å¸³è™Ÿã€‚"
-
-#: mediagoblin/edit/forms.py:67
-msgid "New password"
-msgstr "新密碼"
-
-#: mediagoblin/edit/forms.py:74
msgid "License preference"
-msgstr ""
+msgstr "授權å好"
-#: mediagoblin/edit/forms.py:80
+#: mediagoblin/edit/forms.py:69
msgid "This will be your default license on upload forms."
-msgstr ""
+msgstr "在上傳é é¢ï¼Œé€™å°‡æœƒæ˜¯æ‚¨é è¨­çš„æŽˆæ¬Šæ¨¡å¼ã€‚"
-#: mediagoblin/edit/forms.py:82
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
-msgstr "ç•¶æœ‰äººå°æˆ‘的媒體評論時寄信給我"
+msgstr "ç•¶æœ‰äººå°æˆ‘的媒體留言時寄信給我"
-#: mediagoblin/edit/forms.py:94
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr "標題ä¸èƒ½æ˜¯ç©ºçš„"
-#: mediagoblin/edit/forms.py:96 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:48
msgid "Description of this collection"
msgstr "這個è’è—çš„æè¿°"
-#: mediagoblin/edit/forms.py:103
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
msgstr "æ­¤è’è—ç¶²å€çš„æ¨™é¡Œéƒ¨ä»½ï¼Œé€šå¸¸ä¸éœ€è¦ä¿®æ”¹ã€‚"
-#: mediagoblin/edit/views.py:66
+#: mediagoblin/edit/forms.py:99
+msgid "Old password"
+msgstr "舊的密碼"
+
+#: mediagoblin/edit/forms.py:101
+msgid "Enter your old password to prove you own this account."
+msgstr "è¼¸å…¥æ‚¨çš„èˆŠå¯†ç¢¼ä¾†è­‰æ˜Žæ‚¨æ“æœ‰é€™å€‹å¸³è™Ÿã€‚"
+
+#: mediagoblin/edit/forms.py:104
+msgid "New password"
+msgstr "新密碼"
+
+#: mediagoblin/edit/views.py:67
msgid "An entry with that slug already exists for this user."
msgstr "這個簡稱已經被其他人用了"
@@ -220,7 +227,7 @@ msgstr "您加上了附件「%sã€ï¼"
#: mediagoblin/edit/views.py:182
msgid "You can only edit your own profile."
-msgstr ""
+msgstr "您åªèƒ½ä¿®æ”¹æ‚¨è‡ªå·±çš„個人檔案。"
#: mediagoblin/edit/views.py:188
msgid "You are editing a user's profile. Proceed with caution."
@@ -230,57 +237,80 @@ msgstr "您正在修改別人的個人檔案,請å°å¿ƒæ“作。"
msgid "Profile changes saved"
msgstr "個人檔案修改已儲存"
-#: mediagoblin/edit/views.py:241
-msgid "Wrong password"
-msgstr "密碼錯誤"
-
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:240
msgid "Account settings saved"
msgstr "帳號設定已儲存"
-#: mediagoblin/edit/views.py:286
+#: mediagoblin/edit/views.py:274
msgid "You need to confirm the deletion of your account."
-msgstr ""
+msgstr "您必須è¦ç¢ºèªæ˜¯å¦åˆªé™¤æ‚¨çš„帳號。"
-#: mediagoblin/edit/views.py:322 mediagoblin/submit/views.py:142
-#: mediagoblin/user_pages/views.py:214
+#: mediagoblin/edit/views.py:310 mediagoblin/submit/views.py:138
+#: mediagoblin/user_pages/views.py:222
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr "您已經有一個稱åšã€Œ%sã€çš„è’è—了ï¼"
-#: mediagoblin/edit/views.py:326
+#: mediagoblin/edit/views.py:314
msgid "A collection with that slug already exists for this user."
msgstr "這個使用者已經有使用該簡稱的è’è—了。"
-#: mediagoblin/edit/views.py:343
+#: mediagoblin/edit/views.py:329
msgid "You are editing another user's collection. Proceed with caution."
msgstr "您正在修改別人的è’è—,請å°å¿ƒæ“作。"
-#: mediagoblin/gmg_commands/theme.py:58
+#: mediagoblin/edit/views.py:348
+msgid "Wrong password"
+msgstr "密碼錯誤"
+
+#: mediagoblin/edit/views.py:363
+msgid "Your password was changed successfully"
+msgstr "您的密碼已經æˆåŠŸä¿®æ”¹"
+
+#: mediagoblin/gmg_commands/assetlink.py:60
msgid "Cannot link theme... no theme set\n"
msgstr "無法連çµä½ˆæ™¯â€¦æ²’有此佈景\n"
-#: mediagoblin/gmg_commands/theme.py:71
+#: mediagoblin/gmg_commands/assetlink.py:73
msgid "No asset directory for this theme\n"
msgstr "此佈景沒有素æç›®éŒ„\n"
-#: mediagoblin/gmg_commands/theme.py:74
+#: mediagoblin/gmg_commands/assetlink.py:76
msgid "However, old link directory symlink found; removed.\n"
msgstr "但是舊的目錄連çµå·²ç¶“找到並移除。\n"
+#: mediagoblin/gmg_commands/assetlink.py:112
+#, python-format
+msgid "Could not link \"%s\": %s exists and is not a symlink\n"
+msgstr "無法連çµã€Œ%sã€ï¼š%s å­˜åœ¨ï¼Œä¸”ä¸æ˜¯ç¬¦è™Ÿé€£çµ\n"
+
+#: mediagoblin/gmg_commands/assetlink.py:119
+#, python-format
+msgid "Skipping \"%s\"; already set up.\n"
+msgstr "è·³éŽã€Œ%sã€ï¼Œå·²ç¶“建置完æˆã€‚\n"
+
+#: mediagoblin/gmg_commands/assetlink.py:124
+#, python-format
+msgid "Old link found for \"%s\"; removing.\n"
+msgstr "找到「%sã€èˆŠçš„連çµï¼Œåˆªé™¤ä¸­ã€‚\n"
+
#: mediagoblin/meddleware/csrf.py:134
msgid ""
"CSRF cookie not present. This is most likely the result of a cookie blocker "
"or somesuch.<br/>Make sure to permit the settings of cookies for this "
"domain."
-msgstr ""
+msgstr "è·¨ç¶²ç«™å­˜å– (CSRF) çš„ cookie ä¸å­˜åœ¨ï¼Œæœ‰å¯èƒ½æ˜¯ cookie 阻擋程å¼ä¹‹é¡žçš„程å¼å°Žè‡´çš„。<br/>è«‹å…許此網域的 cookie 設定。"
-#: mediagoblin/media_types/__init__.py:61
-#: mediagoblin/media_types/__init__.py:102
+#: mediagoblin/media_types/__init__.py:111
+#: mediagoblin/media_types/__init__.py:155
msgid "Sorry, I don't support that file type :("
msgstr "æŠ±æ­‰ï¼Œæˆ‘ä¸æ”¯æ´é€™æ¨£çš„æª”æ¡ˆæ ¼å¼ :("
-#: mediagoblin/media_types/video/processing.py:36
+#: mediagoblin/media_types/pdf/processing.py:136
+msgid "unoconv failing to run, check log file"
+msgstr "unoconv 無法執行,請檢查紀錄檔"
+
+#: mediagoblin/media_types/video/processing.py:37
msgid "Video transcoding failed"
msgstr "å½±åƒè½‰ç¢¼å¤±æ•—"
@@ -307,7 +337,7 @@ msgstr "å稱"
#: mediagoblin/plugins/oauth/forms.py:35
msgid "The name of the OAuth client"
-msgstr "OAuth client çš„å稱"
+msgstr "OAuth 用戶程å¼çš„å稱"
#: mediagoblin/plugins/oauth/forms.py:36
msgid "Description"
@@ -331,7 +361,7 @@ msgid ""
" <strong>Public</strong> - The client can't make confidential\n"
" requests to the GNU MediaGoblin instance (e.g. client-side\n"
" JavaScript client)."
-msgstr "<strong>秘密</strong> — OAuth client å¯ä»¥å° GNU MediaGoblin ç«™å°ç™¼é€ä¸è¢«ä½¿ç”¨è€…ä»£ç†æ””截的請求 (例如伺æœç«¯çš„ client)。\n<strong>公開</strong> — OAuth client ç„¡æ³•å° GNU MediaGoblin ç«™å°ç™¼é€ç§˜å¯†çš„請求 (例如客戶端的 JavaScript client)。"
+msgstr "<strong>秘密</strong> — OAuth 用戶程å¼å¯ä»¥å° GNU MediaGoblin ç«™å°ç™¼é€ä¸è¢«ä½¿ç”¨è€…ä»£ç†æ””截的請求 (例如伺æœç«¯çš„用戶程å¼)。\n<strong>公開</strong> — OAuth 用戶程å¼ç„¡æ³•å° GNU MediaGoblin ç«™å°ç™¼é€ç§˜å¯†çš„請求 (例如客戶端的 JavaScript 用戶程å¼)。"
#: mediagoblin/plugins/oauth/forms.py:52
msgid "Redirect URI"
@@ -341,23 +371,23 @@ msgstr "é‡å®šå‘ URI"
msgid ""
"The redirect URI for the applications, this field\n"
" is <strong>required</strong> for public clients."
-msgstr "此應用程å¼çš„é‡å®šå‘ URI,本欄ä½åœ¨å…¬é–‹é¡žåž‹çš„ OAuth client 為必填。"
+msgstr "此應用程å¼çš„é‡å®šå‘ URI,本欄ä½åœ¨å…¬é–‹é¡žåž‹çš„ OAuth 用戶程å¼ç‚ºå¿…填。"
#: mediagoblin/plugins/oauth/forms.py:66
msgid "This field is required for public clients"
-msgstr "本欄ä½åœ¨å…¬é–‹é¡žåž‹çš„ OAuth client 為必填"
+msgstr "本欄ä½åœ¨å…¬é–‹é¡žåž‹çš„用戶程å¼ç‚ºå¿…å¡«"
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:56
msgid "The client {0} has been registered!"
-msgstr "OAuth client {0} 註冊完æˆï¼"
+msgstr "OAuth ç”¨æˆ¶ç¨‹å¼ {0} 註冊完æˆï¼"
#: mediagoblin/plugins/oauth/templates/oauth/client/connections.html:22
msgid "OAuth client connections"
-msgstr ""
+msgstr "OAuth 用戶程å¼é€£ç·š"
#: mediagoblin/plugins/oauth/templates/oauth/client/list.html:22
msgid "Your OAuth clients"
-msgstr ""
+msgstr "您的 OAuth 用戶程å¼"
#: mediagoblin/plugins/oauth/templates/oauth/client/register.html:29
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
@@ -366,7 +396,7 @@ msgstr ""
msgid "Add"
msgstr "增加"
-#: mediagoblin/processing/__init__.py:172
+#: mediagoblin/processing/__init__.py:193
msgid "Invalid file given for media type."
msgstr "指定錯誤的媒體類別ï¼"
@@ -374,45 +404,45 @@ msgstr "指定錯誤的媒體類別ï¼"
msgid "File"
msgstr "檔案"
-#: mediagoblin/submit/views.py:51
+#: mediagoblin/submit/views.py:49
msgid "You must provide a file."
msgstr "您必須æä¾›ä¸€å€‹æª”案"
-#: mediagoblin/submit/views.py:97
+#: mediagoblin/submit/views.py:93
msgid "Woohoo! Submitted!"
msgstr "啊哈ï¼PO 上去啦ï¼"
-#: mediagoblin/submit/views.py:146
+#: mediagoblin/submit/views.py:144
#, python-format
msgid "Collection \"%s\" added!"
msgstr "è’è—「%sã€æ–°å¢žå®Œæˆï¼"
-#: mediagoblin/templates/mediagoblin/base.html:64
+#: mediagoblin/templates/mediagoblin/base.html:67
msgid "Verify your email!"
msgstr "ç¢ºèªæ‚¨çš„é›»å­éƒµä»¶"
-#: mediagoblin/templates/mediagoblin/base.html:65
+#: mediagoblin/templates/mediagoblin/base.html:68
msgid "log out"
msgstr "登出"
-#: mediagoblin/templates/mediagoblin/base.html:70
+#: mediagoblin/templates/mediagoblin/base.html:73
#: mediagoblin/templates/mediagoblin/auth/login.html:28
#: mediagoblin/templates/mediagoblin/auth/login.html:36
#: mediagoblin/templates/mediagoblin/auth/login.html:54
msgid "Log in"
msgstr "登入"
-#: mediagoblin/templates/mediagoblin/base.html:79
+#: mediagoblin/templates/mediagoblin/base.html:82
#, python-format
msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr "<a href=\"%(user_url)s\">%(user_name)s</a> 的帳號"
-#: mediagoblin/templates/mediagoblin/base.html:86
+#: mediagoblin/templates/mediagoblin/base.html:89
msgid "Change account settings"
msgstr "更改帳號設定"
-#: mediagoblin/templates/mediagoblin/base.html:90
-#: mediagoblin/templates/mediagoblin/base.html:105
+#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:108
#: mediagoblin/templates/mediagoblin/admin/panel.html:21
#: mediagoblin/templates/mediagoblin/admin/panel.html:26
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:21
@@ -420,72 +450,25 @@ msgstr "更改帳號設定"
msgid "Media processing panel"
msgstr "媒體處ç†é¢æ¿"
-#: mediagoblin/templates/mediagoblin/base.html:93
+#: mediagoblin/templates/mediagoblin/base.html:96
msgid "Log out"
-msgstr ""
+msgstr "登出"
-#: mediagoblin/templates/mediagoblin/base.html:96
+#: mediagoblin/templates/mediagoblin/base.html:99
#: mediagoblin/templates/mediagoblin/user_pages/user.html:156
msgid "Add media"
msgstr "新增媒體"
-#: mediagoblin/templates/mediagoblin/base.html:99
+#: mediagoblin/templates/mediagoblin/base.html:102
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:41
msgid "Create new collection"
msgstr "新增新的è’è—"
-#: mediagoblin/templates/mediagoblin/base.html:122
-#, python-format
-msgid ""
-"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
-"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:125
-#, python-format
-msgid ""
-"Released under the <a "
-"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
-"href=\"%(source_link)s\">Source code</a> available."
-msgstr "以 <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a> 授權釋出。備有<a href=\"%(source_link)s\">原始碼</a>。"
-
#: mediagoblin/templates/mediagoblin/error.html:24
msgid "Image of goblin stressing out"
msgstr "滿臉å•號的哥布林"
-#: mediagoblin/templates/mediagoblin/root.html:31
-msgid "Explore"
-msgstr "探索"
-
-#: mediagoblin/templates/mediagoblin/root.html:33
-msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr "å˜¿ï¼æ­¡è¿Žä¾†åˆ° MediaGoblin ç«™å°ï¼ "
-
-#: mediagoblin/templates/mediagoblin/root.html:35
-msgid ""
-"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
-"extraordinarily great piece of media hosting software."
-msgstr "本站使用 <a href=\"http://mediagoblin.org\">MediaGoblin</a> — 與眾ä¸åŒçš„媒體分享網站。"
-
-#: mediagoblin/templates/mediagoblin/root.html:36
-msgid ""
-"To add your own media, place comments, and more, you can log in with your "
-"MediaGoblin account."
-msgstr "您å¯ä»¥ç™»å…¥æ‚¨çš„ MediaGoblin 帳號以進行上傳媒體ã€å¼µè²¼è©•論等等。"
-
-#: mediagoblin/templates/mediagoblin/root.html:38
-msgid "Don't have one yet? It's easy!"
-msgstr "沒有帳號嗎?開帳號很簡單ï¼"
-
-#: mediagoblin/templates/mediagoblin/root.html:39
-#, python-format
-msgid ""
-"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
-" or\n"
-" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
-msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">在這個網站上建立帳號</a>\n 或是\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">在自己的伺æœå™¨ä¸Šå»ºç«‹ MediaGoblin</a>"
-
-#: mediagoblin/templates/mediagoblin/root.html:47
+#: mediagoblin/templates/mediagoblin/root.html:32
msgid "Most recent media"
msgstr "最新的媒體"
@@ -591,6 +574,53 @@ msgid ""
"%(verification_url)s"
msgstr "%(username)s 您好:\n\nè¦å•Ÿå‹• GNU MediaGoblin 帳號,請在您的ç€è¦½å™¨ä¸­æ‰“開下é¢çš„ç¶²å€:\n\n%(verification_url)s"
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:21
+#, python-format
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org/\" title='Version "
+"%(version)s'>MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+msgstr "本站使用 <a href=\"http://mediagoblin.org/\" title='Version %(version)s'>MediaGoblin</a>,這是一個 <a href=\"http://gnu.org/\">GNU</a> 專案。"
+
+#: mediagoblin/templates/mediagoblin/bits/base_footer.html:24
+#, python-format
+msgid ""
+"Released under the <a "
+"href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a "
+"href=\"%(source_link)s\">Source code</a> available."
+msgstr "以 <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a> 授權釋出。備有<a href=\"%(source_link)s\">原始碼</a>。"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:20
+msgid "Explore"
+msgstr "探索"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:22
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "å˜¿ï¼æ­¡è¿Žä¾†åˆ° MediaGoblin ç«™å°ï¼ "
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:24
+msgid ""
+"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
+"extraordinarily great piece of media hosting software."
+msgstr "本站使用 <a href=\"http://mediagoblin.org\">MediaGoblin</a> — 與眾ä¸åŒçš„媒體分享網站。"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:25
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr "您å¯ä»¥ç™»å…¥æ‚¨çš„ MediaGoblin 帳號以進行上傳媒體ã€å¼µè²¼è©•論等等。"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:27
+msgid "Don't have one yet? It's easy!"
+msgstr "沒有帳號嗎?開帳號很簡單ï¼"
+
+#: mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html:28
+#, python-format
+msgid ""
+"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
+" or\n"
+" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr "<a class=\"button_action_highlight\" href=\"%(register_url)s\">在本站建立您的帳號</a>\n 或是\n <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">在您自己的伺æœå™¨ä¸Šå®‰è£ MediaGoblin</a>"
+
#: mediagoblin/templates/mediagoblin/bits/logo.html:23
#: mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html:23
msgid "MediaGoblin logo"
@@ -603,13 +633,13 @@ msgid "Editing attachments for %(media_title)s"
msgstr "編輯 %(media_title)s 的附件"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:159
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:175
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:182
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:198
msgid "Attachments"
msgstr "附件"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:57
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:181
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:204
msgid "Add attachment"
msgstr "新增附件"
@@ -626,23 +656,33 @@ msgstr "å–æ¶ˆ"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:63
#: mediagoblin/templates/mediagoblin/edit/edit.html:42
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:52
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:55
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:40
msgid "Save changes"
msgstr "儲存變更"
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:28
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:38
+#, python-format
+msgid "Changing %(username)s's password"
+msgstr "更改 %(username)s 的密碼"
+
+#: mediagoblin/templates/mediagoblin/edit/change_pass.html:45
+msgid "Save"
+msgstr "儲存"
+
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:28
#, python-format
msgid "Really delete user '%(user_name)s' and all related media/comments?"
-msgstr ""
+msgstr "真的è¦åˆªé™¤ä½¿ç”¨è€…「%(user_name)sã€ä»¥åŠç›¸é—œçš„媒體與留言?"
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:35
msgid "Yes, really delete my account"
-msgstr ""
+msgstr "æ˜¯çš„ï¼Œæˆ‘çœŸçš„è¦æŠŠæˆ‘çš„å¸³è™Ÿåˆªé™¤"
#: mediagoblin/templates/mediagoblin/edit/delete_account.html:44
-#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:48
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "永久刪除"
@@ -659,9 +699,13 @@ msgstr "編輯 %(media_title)s"
msgid "Changing %(username)s's account settings"
msgstr "正在改變 %(username)s 的帳號設定"
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:59
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:46
+msgid "Change your password."
+msgstr "更改您的密碼。"
+
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:62
msgid "Delete my account"
-msgstr ""
+msgstr "刪除我的帳號"
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29
#, python-format
@@ -680,10 +724,11 @@ msgstr "編輯 %(username)s 的個人檔案"
#: mediagoblin/templates/mediagoblin/listings/tag.html:35
#, python-format
msgid "Media tagged with: %(tag_name)s"
-msgstr "此媒體被 tag æˆï¼š%(tag_name)s"
+msgstr "這個媒體具有以下標籤:%(tag_name)s"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:65
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:55
msgid "Download"
@@ -708,6 +753,7 @@ msgid ""
msgstr "您å¯ä»¥åœ¨ <a href=\"http://getfirefox.com\">http://getfirefox.com</a> å–å¾—å¯ä»¥æ’­æ”¾æ­¤è²éŸ³çš„ç€è¦½å™¨ï¼"
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:71
#: mediagoblin/templates/mediagoblin/media_displays/video.html:61
msgid "Original file"
msgstr "原始檔案"
@@ -716,6 +762,7 @@ msgstr "原始檔案"
msgid "WebM file (Vorbis codec)"
msgstr "WebM 檔案 (Vorbis 編碼)"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:59
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:87
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:93
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:99
@@ -726,13 +773,17 @@ msgstr "WebM 檔案 (Vorbis 編碼)"
msgid "Image for %(media_title)s"
msgstr " %(media_title)s 的照片"
+#: mediagoblin/templates/mediagoblin/media_displays/pdf.html:79
+msgid "PDF file"
+msgstr "PDF 檔"
+
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
msgid "Toggle Rotate"
msgstr "åˆ‡æ›æ—‹è½‰"
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113
msgid "Perspective"
-msgstr "視角"
+msgstr "é€è¦–"
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116
#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117
@@ -771,14 +822,14 @@ msgid ""
"Sorry, this video will not work because\n"
" your web browser does not support HTML5 \n"
" video."
-msgstr ""
+msgstr "抱歉,由於您的ç€è¦½å™¨ä¸æ”¯æ´ HTML5 影片,本影片無法播放"
#: mediagoblin/templates/mediagoblin/media_displays/video.html:47
msgid ""
"You can get a modern web browser that \n"
" can play this video at <a href=\"http://getfirefox.com\">\n"
" http://getfirefox.com</a>!"
-msgstr ""
+msgstr "您å¯ä»¥åœ¨ <a href=\"http://getfirefox.com\">http://getfirefox.com</a> å–å¾—å¯ä»¥æ’­æ”¾æ­¤å½±ç‰‡çš„先進ç€è¦½å™¨ã€‚"
#: mediagoblin/templates/mediagoblin/media_displays/video.html:69
msgid "WebM file (640p; VP8/Vorbis)"
@@ -824,26 +875,26 @@ msgstr "真的è¦åˆªé™¤ %(title)s?"
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr "確定è¦å¾ž %(collection_title)s 移除 %(media_title)s 嗎?"
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
msgid "Remove"
msgstr "移除"
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:21
#, python-format
msgid "%(username)s's collections"
-msgstr ""
+msgstr "%(username)s çš„è’è—"
#: mediagoblin/templates/mediagoblin/user_pages/collection_list.html:28
#, python-format
msgid "<a href=\"%(user_url)s\">%(username)s</a>'s collections"
-msgstr ""
+msgstr "<a href=\"%(user_url)s\">%(username)s</a> çš„è’è—"
#: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19
#, python-format
msgid ""
"Hi %(username)s,\n"
"%(comment_author)s commented on your post (%(comment_url)s) at %(instance_name)s\n"
-msgstr "%(username)s 您好:\n%(comment_author)s 在 %(instance_name)s å°æ‚¨çš„內容 (%(comment_url)s) 張貼評論\n"
+msgstr "%(username)s 您好:\n%(comment_author)s 在 %(instance_name)s å°æ‚¨çš„內容 (%(comment_url)s) 張貼留言\n"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30
#, python-format
@@ -855,7 +906,7 @@ msgstr "%(username)s的媒體"
msgid ""
"<a href=\"%(user_url)s\">%(username)s</a>'s media with tag <a "
"href=\"%(tag_url)s\">%(tag)s</a>"
-msgstr ""
+msgstr "標籤為 <a href=\"%(tag_url)s\">%(tag)s</a> 的 <a href=\"%(user_url)s\">%(username)s</a> 的媒體"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48
#, python-format
@@ -867,30 +918,34 @@ msgstr "<a href=\"%(user_url)s\">%(username)s</a> 的媒體"
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr "â– ç€è¦½ <a href=\"%(user_url)s\">%(username)s</a> 的媒體"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:94
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:95
msgid "Add a comment"
-msgstr "新增評論"
+msgstr "新增留言"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:104
msgid "Add this comment"
-msgstr "增加評論"
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:123
-msgid "at"
-msgstr "在"
+msgstr "增加留言"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:144
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:164
#, python-format
-msgid ""
-"<h3>Added on</h3>\n"
-" <p>%(date)s</p>"
-msgstr "<h3>加入日期</h3>\n <p>%(date)s</p>"
+msgid "%(formatted_time)s ago"
+msgstr "%(formatted_time)s å‰"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:150
+msgid "Added"
+msgstr "新增於"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:161
+msgid "Created"
+msgstr "建立於"
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:28
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:40
#, python-format
msgid "Add “%(media_title)s†to a collection"
-msgstr ""
+msgstr "加入 “%(media_title)s†至è’è—"
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:54
msgid "+"
@@ -969,7 +1024,7 @@ msgstr "這個使用者(還)沒有填寫個人檔案。"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:124
msgid "Browse collections"
-msgstr ""
+msgstr "ç€è¦½è’è—"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:137
#, python-format
@@ -994,11 +1049,11 @@ msgstr " (移除)"
#: mediagoblin/templates/mediagoblin/utils/collections.html:21
msgid "Collected in"
-msgstr ""
+msgstr "è’集了"
#: mediagoblin/templates/mediagoblin/utils/collections.html:40
msgid "Add to a collection"
-msgstr ""
+msgstr "加入至è’è—"
#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
#: mediagoblin/themes/airy/templates/mediagoblin/utils/feed_link.html:21
@@ -1040,7 +1095,7 @@ msgstr "更舊的"
msgid "Tagged with"
msgstr "標籤"
-#: mediagoblin/tools/exif.py:80
+#: mediagoblin/tools/exif.py:83
msgid "Could not read the image file."
msgstr "無法讀å–圖片檔案。"
@@ -1070,9 +1125,33 @@ msgid ""
" deleted."
msgstr "ä¸å¥½æ„æ€ï¼Œçœ‹èµ·ä¾†é€™å€‹ç¶²å€ä¸Šæ²’有網é ã€‚</p><p>å¦‚æžœæ‚¨ç¢ºå®šé€™å€‹ç¶²å€æ˜¯æ­£ç¢ºçš„,您在尋找的é é¢å¯èƒ½å·²ç¶“移動或是被刪除了。"
+#: mediagoblin/tools/timesince.py:62
+msgid "year"
+msgstr "å¹´"
+
+#: mediagoblin/tools/timesince.py:63
+msgid "month"
+msgstr "月"
+
+#: mediagoblin/tools/timesince.py:64
+msgid "week"
+msgstr "週"
+
+#: mediagoblin/tools/timesince.py:65
+msgid "day"
+msgstr "æ—¥"
+
+#: mediagoblin/tools/timesince.py:66
+msgid "hour"
+msgstr "å°æ™‚"
+
+#: mediagoblin/tools/timesince.py:67
+msgid "minute"
+msgstr "分"
+
#: mediagoblin/user_pages/forms.py:23
msgid "Comment"
-msgstr ""
+msgstr "留言"
#: mediagoblin/user_pages/forms.py:25
msgid ""
@@ -1091,7 +1170,7 @@ msgstr "我確定我è¦å¾žè’è—中移除此項目"
#: mediagoblin/user_pages/forms.py:39
msgid "Collection"
-msgstr ""
+msgstr "è’è—"
#: mediagoblin/user_pages/forms.py:40
msgid "-- Select --"
@@ -1101,73 +1180,77 @@ msgstr "— è«‹é¸æ“‡ —"
msgid "Include a note"
msgstr "加註"
-#: mediagoblin/user_pages/lib.py:56
+#: mediagoblin/user_pages/lib.py:58
msgid "commented on your post"
-msgstr "在您的內容張貼評論"
+msgstr "在您的內容張貼留言"
+
+#: mediagoblin/user_pages/views.py:169
+msgid "Sorry, comments are disabled."
+msgstr "抱歉,留言被關閉。"
-#: mediagoblin/user_pages/views.py:166
+#: mediagoblin/user_pages/views.py:174
msgid "Oops, your comment was empty."
msgstr "啊,您的留言是空的。"
-#: mediagoblin/user_pages/views.py:172
+#: mediagoblin/user_pages/views.py:180
msgid "Your comment has been posted!"
msgstr "您的留言已經張貼完æˆï¼"
-#: mediagoblin/user_pages/views.py:197
+#: mediagoblin/user_pages/views.py:205
msgid "Please check your entries and try again."
msgstr "請檢查項目並é‡è©¦ã€‚"
-#: mediagoblin/user_pages/views.py:237
+#: mediagoblin/user_pages/views.py:245
msgid "You have to select or add a collection"
msgstr "您需è¦é¸æ“‡æˆ–是新增一個è’è—"
-#: mediagoblin/user_pages/views.py:248
+#: mediagoblin/user_pages/views.py:256
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr "「%sã€å·²ç¶“在「%sã€è’è—"
-#: mediagoblin/user_pages/views.py:264
+#: mediagoblin/user_pages/views.py:262
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr "「%sã€åŠ å…¥ã€Œ%sã€è’è—"
-#: mediagoblin/user_pages/views.py:286
+#: mediagoblin/user_pages/views.py:282
msgid "You deleted the media."
msgstr "您已經刪除此媒體。"
-#: mediagoblin/user_pages/views.py:293
+#: mediagoblin/user_pages/views.py:289
msgid "The media was not deleted because you didn't check that you were sure."
msgstr "由於您沒有勾é¸ç¢ºèªï¼Œè©²åª’體沒有被移除。"
-#: mediagoblin/user_pages/views.py:301
+#: mediagoblin/user_pages/views.py:296
msgid "You are about to delete another user's media. Proceed with caution."
msgstr "您正在刪除別人的媒體,請å°å¿ƒæ“作。"
-#: mediagoblin/user_pages/views.py:375
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr "您已經從該è’è—中刪除該項目。"
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
msgstr "由於您沒有勾é¸ç¢ºèªï¼Œè©²é …目沒有被移除。"
-#: mediagoblin/user_pages/views.py:389
+#: mediagoblin/user_pages/views.py:382
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr "您正在從別人的è’è—中刪除項目,請å°å¿ƒæ“作。"
-#: mediagoblin/user_pages/views.py:422
+#: mediagoblin/user_pages/views.py:415
#, python-format
msgid "You deleted the collection \"%s\""
msgstr "您已經刪除「%sã€è’è—。"
-#: mediagoblin/user_pages/views.py:429
+#: mediagoblin/user_pages/views.py:422
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr "由於您沒有勾é¸ç¢ºèªï¼Œè©²è’è—æ²’有被移除。"
-#: mediagoblin/user_pages/views.py:439
+#: mediagoblin/user_pages/views.py:430
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr "您正在刪除別人的è’è—,請å°å¿ƒæ“作。"
diff --git a/mediagoblin/init/__init__.py b/mediagoblin/init/__init__.py
index d16027db..e0711416 100644
--- a/mediagoblin/init/__init__.py
+++ b/mediagoblin/init/__init__.py
@@ -24,6 +24,7 @@ from mediagoblin import mg_globals
from mediagoblin.mg_globals import setup_globals
from mediagoblin.db.open import setup_connection_and_db_from_config, \
check_db_migrations_current, load_models
+from mediagoblin.tools.pluginapi import hook_runall
from mediagoblin.tools.workbench import WorkbenchManager
from mediagoblin.storage import storage_system_from_config
@@ -57,16 +58,20 @@ def setup_global_and_app_config(config_path):
return global_config, app_config
-def setup_database():
+def setup_database(run_migrations=False):
app_config = mg_globals.app_config
+ global_config = mg_globals.global_config
# Load all models for media types (plugins, ...)
load_models(app_config)
-
# Set up the database
- db = setup_connection_and_db_from_config(app_config)
-
- check_db_migrations_current(db)
+ db = setup_connection_and_db_from_config(app_config, run_migrations)
+ if run_migrations:
+ #Run the migrations to initialize/update the database.
+ from mediagoblin.gmg_commands.dbupdate import run_all_migrations
+ run_all_migrations(db, app_config, global_config)
+ else:
+ check_db_migrations_current(db)
setup_globals(database=db)
@@ -116,6 +121,12 @@ def get_staticdirector(app_config):
direct_domains = {None: app_config['direct_remote_path'].strip()}
direct_domains['theme'] = app_config['theme_web_path'].strip()
+ # Let plugins load additional paths
+ for plugin_static in hook_runall("static_setup"):
+ direct_domains[plugin_static.name] = "%s/%s" % (
+ app_config['plugin_web_path'].rstrip('/'),
+ plugin_static.name)
+
return staticdirect.StaticDirect(
direct_domains)
diff --git a/mediagoblin/init/celery/__init__.py b/mediagoblin/init/celery/__init__.py
index 169cc935..57242bf6 100644
--- a/mediagoblin/init/celery/__init__.py
+++ b/mediagoblin/init/celery/__init__.py
@@ -16,12 +16,18 @@
import os
import sys
+import logging
from celery import Celery
from mediagoblin.tools.pluginapi import hook_runall
-MANDATORY_CELERY_IMPORTS = ['mediagoblin.processing.task']
+_log = logging.getLogger(__name__)
+
+
+MANDATORY_CELERY_IMPORTS = [
+ 'mediagoblin.processing.task',
+ 'mediagoblin.notifications.task']
DEFAULT_SETTINGS_MODULE = 'mediagoblin.init.celery.dummy_settings_module'
@@ -97,3 +103,13 @@ def setup_celery_from_config(app_config, global_config,
if set_environ:
os.environ['CELERY_CONFIG_MODULE'] = settings_module
+
+ # Replace the default celery.current_app.conf if celery has already been
+ # initiated
+ from celery import current_app
+
+ _log.info('Setting celery configuration from object "{0}"'.format(
+ settings_module))
+ current_app.config_from_object(this_module)
+
+ _log.debug('Celery broker host: {0}'.format(current_app.conf['BROKER_HOST']))
diff --git a/mediagoblin/listings/views.py b/mediagoblin/listings/views.py
index 35af7148..07dbb3d5 100644
--- a/mediagoblin/listings/views.py
+++ b/mediagoblin/listings/views.py
@@ -14,6 +14,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+from mediagoblin import mg_globals
from mediagoblin.db.models import MediaEntry
from mediagoblin.db.util import media_entries_for_tag_slug
from mediagoblin.tools.pagination import Pagination
@@ -80,6 +81,17 @@ def atom_feed(request):
link = request.urlgen('index', qualified=True)
feed_title += "for all recent items"
+ atomlinks = [
+ {'href': link,
+ 'rel': 'alternate',
+ 'type': 'text/html'}]
+
+ if mg_globals.app_config["push_urls"]:
+ for push_url in mg_globals.app_config["push_urls"]:
+ atomlinks.append({
+ 'rel': 'hub',
+ 'href': push_url})
+
cursor = cursor.order_by(MediaEntry.created.desc())
cursor = cursor.limit(ATOM_DEFAULT_NR_OF_UPDATED_ITEMS)
@@ -87,9 +99,8 @@ def atom_feed(request):
feed_title,
feed_url=request.url,
id=link,
- links=[{'href': link,
- 'rel': 'alternate',
- 'type': 'text/html'}])
+ links=atomlinks)
+
for entry in cursor:
feed.add(entry.get('title'),
entry.description_html,
diff --git a/mediagoblin/meddleware/csrf.py b/mediagoblin/meddleware/csrf.py
index 661f0ba2..44d42d75 100644
--- a/mediagoblin/meddleware/csrf.py
+++ b/mediagoblin/meddleware/csrf.py
@@ -111,7 +111,7 @@ class CsrfMeddleware(BaseMeddleware):
httponly=True)
# update the Vary header
- response.vary = (getattr(response, 'vary', None) or []) + ['Cookie']
+ response.vary = list(getattr(response, 'vary', None) or []) + ['Cookie']
def _make_token(self, request):
"""Generate a new token to use for CSRF protection."""
diff --git a/mediagoblin/media_types/__init__.py b/mediagoblin/media_types/__init__.py
index 20e1918e..134157dc 100644
--- a/mediagoblin/media_types/__init__.py
+++ b/mediagoblin/media_types/__init__.py
@@ -15,12 +15,10 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
-import sys
import logging
import tempfile
-from mediagoblin import mg_globals
-from mediagoblin.tools.common import import_component
+from mediagoblin.tools.pluginapi import hook_handle
from mediagoblin.tools.translate import lazy_pass_to_ugettext as _
_log = logging.getLogger(__name__)
@@ -52,36 +50,6 @@ class MediaManagerBase(object):
return hasattr(self, i)
-class CompatMediaManager(object):
- def __init__(self, mm_dict, entry=None):
- self.mm_dict = mm_dict
- self.entry = entry
-
- def __call__(self, entry):
- "So this object can look like a class too, somehow"
- assert self.entry is None
- return self.__class__(self.mm_dict, entry)
-
- def __getitem__(self, i):
- return self.mm_dict[i]
-
- def __contains__(self, i):
- return (i in self.mm_dict)
-
- @property
- def media_fetch_order(self):
- return self.mm_dict.get('media_fetch_order')
-
- def sniff_handler(self, *args, **kwargs):
- func = self.mm_dict.get("sniff_handler", None)
- if func is not None:
- return func(*args, **kwargs)
- return False
-
- def __getattr__(self, i):
- return self.mm_dict[i]
-
-
def sniff_media(media):
'''
Iterate through the enabled media types and find those suited
@@ -98,40 +66,18 @@ def sniff_media(media):
media_file.write(media.stream.read())
media.stream.seek(0)
- for media_type, manager in get_media_managers():
- _log.info('Sniffing {0}'.format(media_type))
- if manager.sniff_handler(media_file, media=media):
- _log.info('{0} accepts the file'.format(media_type))
- return media_type, manager
- else:
- _log.debug('{0} did not accept the file'.format(media_type))
+ media_type = hook_handle('sniff_handler', media_file, media=media)
+ if media_type:
+ _log.info('{0} accepts the file'.format(media_type))
+ return media_type, hook_handle(('media_manager', media_type))
+ else:
+ _log.debug('{0} did not accept the file'.format(media_type))
raise FileTypeNotSupported(
# TODO: Provide information on which file types are supported
_(u'Sorry, I don\'t support that file type :('))
-def get_media_types():
- """
- Generator, yields the available media types
- """
- for media_type in mg_globals.app_config['media_types']:
- yield media_type
-
-
-def get_media_managers():
- '''
- Generator, yields all enabled media managers
- '''
- for media_type in get_media_types():
- mm = import_component(media_type + ":MEDIA_MANAGER")
-
- if isinstance(mm, dict):
- mm = CompatMediaManager(mm)
-
- yield media_type, mm
-
-
def get_media_type_and_manager(filename):
'''
Try to find the media type based on the file name, extension
@@ -142,11 +88,10 @@ def get_media_type_and_manager(filename):
# Get the file extension
ext = os.path.splitext(filename)[1].lower()
- for media_type, manager in get_media_managers():
- # Omit the dot from the extension and match it against
- # the media manager
- if ext[1:] in manager.accepted_extensions:
- return media_type, manager
+ # Omit the dot from the extension and match it against
+ # the media manager
+ if hook_handle('get_media_type_and_manager', ext[1:]):
+ return hook_handle('get_media_type_and_manager', ext[1:])
else:
_log.info('File {0} has no file extension, let\'s hope the sniffers get it.'.format(
filename))
diff --git a/mediagoblin/media_types/ascii/__init__.py b/mediagoblin/media_types/ascii/__init__.py
index 0931e83a..4baf8dd3 100644
--- a/mediagoblin/media_types/ascii/__init__.py
+++ b/mediagoblin/media_types/ascii/__init__.py
@@ -17,15 +17,31 @@
from mediagoblin.media_types import MediaManagerBase
from mediagoblin.media_types.ascii.processing import process_ascii, \
sniff_handler
+from mediagoblin.tools import pluginapi
+
+ACCEPTED_EXTENSIONS = ["txt", "asc", "nfo"]
+MEDIA_TYPE = 'mediagoblin.media_types.ascii'
+
+
+def setup_plugin():
+ config = pluginapi.get_config(MEDIA_TYPE)
class ASCIIMediaManager(MediaManagerBase):
human_readable = "ASCII"
processor = staticmethod(process_ascii)
- sniff_handler = staticmethod(sniff_handler)
display_template = "mediagoblin/media_displays/ascii.html"
default_thumb = "images/media_thumbs/ascii.jpg"
- accepted_extensions = ["txt", "asc", "nfo"]
-
-MEDIA_MANAGER = ASCIIMediaManager
+
+def get_media_type_and_manager(ext):
+ if ext in ACCEPTED_EXTENSIONS:
+ return MEDIA_TYPE, ASCIIMediaManager
+
+
+hooks = {
+ 'setup': setup_plugin,
+ 'get_media_type_and_manager': get_media_type_and_manager,
+ ('media_manager', MEDIA_TYPE): lambda: ASCIIMediaManager,
+ 'sniff_handler': sniff_handler,
+}
diff --git a/mediagoblin/media_types/ascii/processing.py b/mediagoblin/media_types/ascii/processing.py
index 2f6079be..aca784e8 100644
--- a/mediagoblin/media_types/ascii/processing.py
+++ b/mediagoblin/media_types/ascii/processing.py
@@ -28,17 +28,19 @@ from mediagoblin.media_types.ascii import asciitoimage
_log = logging.getLogger(__name__)
SUPPORTED_EXTENSIONS = ['txt', 'asc', 'nfo']
+MEDIA_TYPE = 'mediagoblin.media_types.ascii'
def sniff_handler(media_file, **kw):
+ _log.info('Sniffing {0}'.format(MEDIA_TYPE))
if kw.get('media') is not None:
name, ext = os.path.splitext(kw['media'].filename)
clean_ext = ext[1:].lower()
if clean_ext in SUPPORTED_EXTENSIONS:
- return True
+ return MEDIA_TYPE
- return False
+ return None
def process_ascii(proc_state):
diff --git a/mediagoblin/media_types/audio/__init__.py b/mediagoblin/media_types/audio/__init__.py
index 2eb7300e..c7ed8d2d 100644
--- a/mediagoblin/media_types/audio/__init__.py
+++ b/mediagoblin/media_types/audio/__init__.py
@@ -17,14 +17,32 @@
from mediagoblin.media_types import MediaManagerBase
from mediagoblin.media_types.audio.processing import process_audio, \
sniff_handler
+from mediagoblin.tools import pluginapi
+
+# Why isn't .ogg in this list? It's still detected, but via sniffing,
+# .ogg files could be either video or audio... sniffing determines which.
+
+ACCEPTED_EXTENSIONS = ["mp3", "flac", "wav", "m4a"]
+MEDIA_TYPE = 'mediagoblin.media_types.audio'
+
+
+def setup_plugin():
+ config = pluginapi.get_config(MEDIA_TYPE)
class AudioMediaManager(MediaManagerBase):
human_readable = "Audio"
processor = staticmethod(process_audio)
- sniff_handler = staticmethod(sniff_handler)
display_template = "mediagoblin/media_displays/audio.html"
- accepted_extensions = ["mp3", "flac", "wav", "m4a"]
-MEDIA_MANAGER = AudioMediaManager
+def get_media_type_and_manager(ext):
+ if ext in ACCEPTED_EXTENSIONS:
+ return MEDIA_TYPE, AudioMediaManager
+
+hooks = {
+ 'setup': setup_plugin,
+ 'get_media_type_and_manager': get_media_type_and_manager,
+ 'sniff_handler': sniff_handler,
+ ('media_manager', MEDIA_TYPE): lambda: AudioMediaManager,
+}
diff --git a/mediagoblin/media_types/audio/processing.py b/mediagoblin/media_types/audio/processing.py
index 101b83e5..22383bc1 100644
--- a/mediagoblin/media_types/audio/processing.py
+++ b/mediagoblin/media_types/audio/processing.py
@@ -27,19 +27,22 @@ from mediagoblin.media_types.audio.transcoders import (AudioTranscoder,
_log = logging.getLogger(__name__)
+MEDIA_TYPE = 'mediagoblin.media_types.audio'
+
def sniff_handler(media_file, **kw):
+ _log.info('Sniffing {0}'.format(MEDIA_TYPE))
try:
transcoder = AudioTranscoder()
data = transcoder.discover(media_file.name)
except BadMediaFail:
_log.debug('Audio discovery raised BadMediaFail')
- return False
+ return None
if data.is_audio == True and data.is_video == False:
- return True
+ return MEDIA_TYPE
- return False
+ return None
def process_audio(proc_state):
diff --git a/mediagoblin/media_types/image/__init__.py b/mediagoblin/media_types/image/__init__.py
index 5130ef48..1bb9c6f3 100644
--- a/mediagoblin/media_types/image/__init__.py
+++ b/mediagoblin/media_types/image/__init__.py
@@ -13,23 +13,30 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
import datetime
from mediagoblin.media_types import MediaManagerBase
from mediagoblin.media_types.image.processing import process_image, \
sniff_handler
+from mediagoblin.tools import pluginapi
+
+
+ACCEPTED_EXTENSIONS = ["jpg", "jpeg", "png", "gif", "tiff"]
+MEDIA_TYPE = 'mediagoblin.media_types.image'
+
+
+def setup_plugin():
+ config = pluginapi.get_config('mediagoblin.media_types.image')
class ImageMediaManager(MediaManagerBase):
human_readable = "Image"
processor = staticmethod(process_image)
- sniff_handler = staticmethod(sniff_handler)
display_template = "mediagoblin/media_displays/image.html"
default_thumb = "images/media_thumbs/image.png"
- accepted_extensions = ["jpg", "jpeg", "png", "gif", "tiff"]
+
media_fetch_order = [u'medium', u'original', u'thumb']
-
+
def get_original_date(self):
"""
Get the original date and time from the EXIF information. Returns
@@ -52,4 +59,14 @@ class ImageMediaManager(MediaManagerBase):
return None
-MEDIA_MANAGER = ImageMediaManager
+def get_media_type_and_manager(ext):
+ if ext in ACCEPTED_EXTENSIONS:
+ return MEDIA_TYPE, ImageMediaManager
+
+
+hooks = {
+ 'setup': setup_plugin,
+ 'get_media_type_and_manager': get_media_type_and_manager,
+ 'sniff_handler': sniff_handler,
+ ('media_manager', MEDIA_TYPE): lambda: ImageMediaManager,
+}
diff --git a/mediagoblin/media_types/image/processing.py b/mediagoblin/media_types/image/processing.py
index bc0ce3f8..baf2ac7e 100644
--- a/mediagoblin/media_types/image/processing.py
+++ b/mediagoblin/media_types/image/processing.py
@@ -35,6 +35,8 @@ PIL_FILTERS = {
'BICUBIC': Image.BICUBIC,
'ANTIALIAS': Image.ANTIALIAS}
+MEDIA_TYPE = 'mediagoblin.media_types.image'
+
def resize_image(proc_state, resized, keyname, target_name, new_size,
exif_tags, workdir):
@@ -95,17 +97,18 @@ def resize_tool(proc_state, force, keyname, target_name,
exif_tags, conversions_subdir)
-SUPPORTED_FILETYPES = ['png', 'gif', 'jpg', 'jpeg']
+SUPPORTED_FILETYPES = ['png', 'gif', 'jpg', 'jpeg', 'tiff']
def sniff_handler(media_file, **kw):
+ _log.info('Sniffing {0}'.format(MEDIA_TYPE))
if kw.get('media') is not None: # That's a double negative!
name, ext = os.path.splitext(kw['media'].filename)
clean_ext = ext[1:].lower() # Strip the . from ext and make lowercase
if clean_ext in SUPPORTED_FILETYPES:
_log.info('Found file extension in supported filetypes')
- return True
+ return MEDIA_TYPE
else:
_log.debug('Media present, extension not found in {0}'.format(
SUPPORTED_FILETYPES))
@@ -113,7 +116,7 @@ def sniff_handler(media_file, **kw):
_log.warning('Need additional information (keyword argument \'media\')'
' to be able to handle sniffing')
- return False
+ return None
def process_image(proc_state):
diff --git a/mediagoblin/media_types/pdf/__init__.py b/mediagoblin/media_types/pdf/__init__.py
index f0ba7867..67509ddc 100644
--- a/mediagoblin/media_types/pdf/__init__.py
+++ b/mediagoblin/media_types/pdf/__init__.py
@@ -17,15 +17,31 @@
from mediagoblin.media_types import MediaManagerBase
from mediagoblin.media_types.pdf.processing import process_pdf, \
sniff_handler
+from mediagoblin.tools import pluginapi
+
+ACCEPTED_EXTENSIONS = ['pdf']
+MEDIA_TYPE = 'mediagoblin.media_types.pdf'
+
+
+def setup_plugin():
+ config = pluginapi.get_config(MEDIA_TYPE)
class PDFMediaManager(MediaManagerBase):
human_readable = "PDF"
processor = staticmethod(process_pdf)
- sniff_handler = staticmethod(sniff_handler)
display_template = "mediagoblin/media_displays/pdf.html"
default_thumb = "images/media_thumbs/pdf.jpg"
- accepted_extensions = ["pdf"]
-MEDIA_MANAGER = PDFMediaManager
+def get_media_type_and_manager(ext):
+ if ext in ACCEPTED_EXTENSIONS:
+ return MEDIA_TYPE, PDFMediaManager
+
+
+hooks = {
+ 'setup': setup_plugin,
+ 'get_media_type_and_manager': get_media_type_and_manager,
+ 'sniff_handler': sniff_handler,
+ ('media_manager', MEDIA_TYPE): lambda: PDFMediaManager,
+}
diff --git a/mediagoblin/media_types/pdf/processing.py b/mediagoblin/media_types/pdf/processing.py
index 49742fd7..f35b4376 100644
--- a/mediagoblin/media_types/pdf/processing.py
+++ b/mediagoblin/media_types/pdf/processing.py
@@ -25,6 +25,8 @@ from mediagoblin.tools.translate import fake_ugettext_passthrough as _
_log = logging.getLogger(__name__)
+MEDIA_TYPE = 'mediagoblin.media_types.pdf'
+
# TODO - cache (memoize) util
# This is a list created via uniconv --show and hand removing some types that
@@ -163,16 +165,17 @@ def check_prerequisites():
return True
def sniff_handler(media_file, **kw):
+ _log.info('Sniffing {0}'.format(MEDIA_TYPE))
if not check_prerequisites():
- return False
+ return None
if kw.get('media') is not None:
name, ext = os.path.splitext(kw['media'].filename)
clean_ext = ext[1:].lower()
if clean_ext in supported_extensions():
- return True
+ return MEDIA_TYPE
- return False
+ return None
def create_pdf_thumb(original, thumb_filename, width, height):
# Note: pdftocairo adds '.png', remove it
@@ -250,8 +253,8 @@ def process_pdf(proc_state):
else:
pdf_filename = queued_filename.rsplit('.', 1)[0] + '.pdf'
unoconv = where('unoconv')
- call(executable=unoconv,
- args=[unoconv, '-v', '-f', 'pdf', queued_filename])
+ Popen(executable=unoconv,
+ args=[unoconv, '-v', '-f', 'pdf', queued_filename]).wait()
if not os.path.exists(pdf_filename):
_log.debug('unoconv failed to convert file to pdf')
raise BadMediaFail()
diff --git a/mediagoblin/media_types/stl/__init__.py b/mediagoblin/media_types/stl/__init__.py
index 6ae8a8b9..1d2a8478 100644
--- a/mediagoblin/media_types/stl/__init__.py
+++ b/mediagoblin/media_types/stl/__init__.py
@@ -17,15 +17,30 @@
from mediagoblin.media_types import MediaManagerBase
from mediagoblin.media_types.stl.processing import process_stl, \
sniff_handler
+from mediagoblin.tools import pluginapi
+
+MEDIA_TYPE = 'mediagoblin.media_types.stl'
+ACCEPTED_EXTENSIONS = ["obj", "stl"]
+
+
+def setup_plugin():
+ config = pluginapi.get_config(MEDIA_TYPE)
class STLMediaManager(MediaManagerBase):
human_readable = "stereo lithographics"
processor = staticmethod(process_stl)
- sniff_handler = staticmethod(sniff_handler)
display_template = "mediagoblin/media_displays/stl.html"
default_thumb = "images/media_thumbs/video.jpg"
- accepted_extensions = ["obj", "stl"]
-MEDIA_MANAGER = STLMediaManager
+def get_media_type_and_manager(ext):
+ if ext in ACCEPTED_EXTENSIONS:
+ return MEDIA_TYPE, STLMediaManager
+
+hooks = {
+ 'setup': setup_plugin,
+ 'get_media_type_and_manager': get_media_type_and_manager,
+ 'sniff_handler': sniff_handler,
+ ('media_manager', MEDIA_TYPE): lambda: STLMediaManager,
+}
diff --git a/mediagoblin/media_types/stl/processing.py b/mediagoblin/media_types/stl/processing.py
index 49382495..53751416 100644
--- a/mediagoblin/media_types/stl/processing.py
+++ b/mediagoblin/media_types/stl/processing.py
@@ -29,6 +29,7 @@ from mediagoblin.media_types.stl import model_loader
_log = logging.getLogger(__name__)
SUPPORTED_FILETYPES = ['stl', 'obj']
+MEDIA_TYPE = 'mediagoblin.media_types.stl'
BLEND_FILE = pkg_resources.resource_filename(
'mediagoblin.media_types.stl',
@@ -43,13 +44,14 @@ BLEND_SCRIPT = pkg_resources.resource_filename(
def sniff_handler(media_file, **kw):
+ _log.info('Sniffing {0}'.format(MEDIA_TYPE))
if kw.get('media') is not None:
name, ext = os.path.splitext(kw['media'].filename)
clean_ext = ext[1:].lower()
-
+
if clean_ext in SUPPORTED_FILETYPES:
_log.info('Found file extension in supported filetypes')
- return True
+ return MEDIA_TYPE
else:
_log.debug('Media present, extension not found in {0}'.format(
SUPPORTED_FILETYPES))
@@ -57,7 +59,7 @@ def sniff_handler(media_file, **kw):
_log.warning('Need additional information (keyword argument \'media\')'
' to be able to handle sniffing')
- return False
+ return None
def blender_render(config):
diff --git a/mediagoblin/media_types/tools.py b/mediagoblin/media_types/tools.py
new file mode 100644
index 00000000..fe7b3772
--- /dev/null
+++ b/mediagoblin/media_types/tools.py
@@ -0,0 +1,27 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import logging
+
+from mediagoblin import mg_globals
+
+_log = logging.getLogger(__name__)
+
+
+def media_type_warning():
+ if mg_globals.app_config.get('media_types'):
+ _log.warning('Media_types have been converted to plugins. Old'
+ ' media_types will no longer work. Please convert them'
+ ' to plugins to continue using them.')
diff --git a/mediagoblin/media_types/video/__init__.py b/mediagoblin/media_types/video/__init__.py
index 569cf11a..e8a4308b 100644
--- a/mediagoblin/media_types/video/__init__.py
+++ b/mediagoblin/media_types/video/__init__.py
@@ -17,20 +17,35 @@
from mediagoblin.media_types import MediaManagerBase
from mediagoblin.media_types.video.processing import process_video, \
sniff_handler
+from mediagoblin.tools import pluginapi
+
+MEDIA_TYPE = 'mediagoblin.media_types.video'
+ACCEPTED_EXTENSIONS = [
+ "mp4", "mov", "webm", "avi", "3gp", "3gpp", "mkv", "ogv", "m4v"]
+
+
+def setup_plugin():
+ config = pluginapi.get_config(MEDIA_TYPE)
class VideoMediaManager(MediaManagerBase):
human_readable = "Video"
processor = staticmethod(process_video)
- sniff_handler = staticmethod(sniff_handler)
display_template = "mediagoblin/media_displays/video.html"
default_thumb = "images/media_thumbs/video.jpg"
- accepted_extensions = [
- "mp4", "mov", "webm", "avi", "3gp", "3gpp", "mkv", "ogv", "m4v"]
-
+
# Used by the media_entry.get_display_media method
media_fetch_order = [u'webm_640', u'original']
default_webm_type = 'video/webm; codecs="vp8, vorbis"'
-MEDIA_MANAGER = VideoMediaManager
+def get_media_type_and_manager(ext):
+ if ext in ACCEPTED_EXTENSIONS:
+ return MEDIA_TYPE, VideoMediaManager
+
+hooks = {
+ 'setup': setup_plugin,
+ 'get_media_type_and_manager': get_media_type_and_manager,
+ 'sniff_handler': sniff_handler,
+ ('media_manager', MEDIA_TYPE): lambda: VideoMediaManager,
+}
diff --git a/mediagoblin/media_types/video/processing.py b/mediagoblin/media_types/video/processing.py
index ff2c94a0..5386ba60 100644
--- a/mediagoblin/media_types/video/processing.py
+++ b/mediagoblin/media_types/video/processing.py
@@ -29,6 +29,8 @@ from .util import skip_transcode
_log = logging.getLogger(__name__)
_log.setLevel(logging.DEBUG)
+MEDIA_TYPE = 'mediagoblin.media_types.video'
+
class VideoTranscodingFail(BaseProcessingFail):
'''
@@ -41,17 +43,18 @@ def sniff_handler(media_file, **kw):
transcoder = transcoders.VideoTranscoder()
data = transcoder.discover(media_file.name)
+ _log.info('Sniffing {0}'.format(MEDIA_TYPE))
_log.debug('Discovered: {0}'.format(data))
if not data:
_log.error('Could not discover {0}'.format(
kw.get('media')))
- return False
+ return None
if data['is_video'] == True:
- return True
+ return MEDIA_TYPE
- return False
+ return None
def process_video(proc_state):
@@ -186,7 +189,7 @@ def store_metadata(media_entry, metadata):
[(key, tags_metadata[key])
for key in [
"application-name", "artist", "audio-codec", "bitrate",
- "container-format", "copyright", "encoder",
+ "container-format", "copyright", "encoder",
"encoder-version", "license", "nominal-bitrate", "title",
"video-codec"]
if key in tags_metadata])
@@ -203,7 +206,7 @@ def store_metadata(media_entry, metadata):
dt.get_year(), dt.get_month(), dt.get_day(), dt.get_hour(),
dt.get_minute(), dt.get_second(),
dt.get_microsecond()).isoformat()
-
+
metadata['tags'] = tags
# Only save this field if there's something to save
diff --git a/mediagoblin/media_types/video/transcoders.py b/mediagoblin/media_types/video/transcoders.py
index 90a767dd..9d6b7655 100644
--- a/mediagoblin/media_types/video/transcoders.py
+++ b/mediagoblin/media_types/video/transcoders.py
@@ -22,9 +22,15 @@ import logging
import urllib
import multiprocessing
import gobject
+
+old_argv = sys.argv
+sys.argv = []
+
import pygst
pygst.require('0.10')
import gst
+
+sys.argv = old_argv
import struct
try:
from PIL import Image
diff --git a/mediagoblin/notifications/__init__.py b/mediagoblin/notifications/__init__.py
new file mode 100644
index 00000000..4b7fbb8c
--- /dev/null
+++ b/mediagoblin/notifications/__init__.py
@@ -0,0 +1,141 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import logging
+
+from mediagoblin.db.models import Notification, \
+ CommentNotification, CommentSubscription
+from mediagoblin.notifications.task import email_notification_task
+from mediagoblin.notifications.tools import generate_comment_message
+
+_log = logging.getLogger(__name__)
+
+def trigger_notification(comment, media_entry, request):
+ '''
+ Send out notifications about a new comment.
+ '''
+ subscriptions = CommentSubscription.query.filter_by(
+ media_entry_id=media_entry.id).all()
+
+ for subscription in subscriptions:
+ if not subscription.notify:
+ continue
+
+ if comment.get_author == subscription.user:
+ continue
+
+ cn = CommentNotification(
+ user_id=subscription.user_id,
+ subject_id=comment.id)
+
+ cn.save()
+
+ if subscription.send_email:
+ message = generate_comment_message(
+ subscription.user,
+ comment,
+ media_entry,
+ request)
+
+ email_notification_task.apply_async([cn.id, message])
+
+
+def mark_notification_seen(notification):
+ if notification:
+ notification.seen = True
+ notification.save()
+
+
+def mark_comment_notification_seen(comment_id, user):
+ notification = CommentNotification.query.filter_by(
+ user_id=user.id,
+ subject_id=comment_id).first()
+
+ _log.debug('Marking {0} as seen.'.format(notification))
+
+ mark_notification_seen(notification)
+
+
+def get_comment_subscription(user_id, media_entry_id):
+ return CommentSubscription.query.filter_by(
+ user_id=user_id,
+ media_entry_id=media_entry_id).first()
+
+def add_comment_subscription(user, media_entry):
+ '''
+ Create a comment subscription for a User on a MediaEntry.
+
+ Uses the User's wants_comment_notification to set email notifications for
+ the subscription to enabled/disabled.
+ '''
+ cn = get_comment_subscription(user.id, media_entry.id)
+
+ if not cn:
+ cn = CommentSubscription(
+ user_id=user.id,
+ media_entry_id=media_entry.id)
+
+ cn.notify = True
+
+ if not user.wants_comment_notification:
+ cn.send_email = False
+
+ cn.save()
+
+
+def silence_comment_subscription(user, media_entry):
+ '''
+ Silence a subscription so that the user is never notified in any way about
+ new comments on an entry
+ '''
+ cn = get_comment_subscription(user.id, media_entry.id)
+
+ if cn:
+ cn.notify = False
+ cn.send_email = False
+ cn.save()
+
+
+def remove_comment_subscription(user, media_entry):
+ cn = get_comment_subscription(user.id, media_entry.id)
+
+ if cn:
+ cn.delete()
+
+
+NOTIFICATION_FETCH_LIMIT = 100
+
+
+def get_notifications(user_id, only_unseen=True):
+ query = Notification.query.filter_by(user_id=user_id)
+
+ if only_unseen:
+ query = query.filter_by(seen=False)
+
+ notifications = query.limit(
+ NOTIFICATION_FETCH_LIMIT).all()
+
+ return notifications
+
+def get_notification_count(user_id, only_unseen=True):
+ query = Notification.query.filter_by(user_id=user_id)
+
+ if only_unseen:
+ query = query.filter_by(seen=False)
+
+ count = query.count()
+
+ return count
diff --git a/mediagoblin/notifications/routing.py b/mediagoblin/notifications/routing.py
new file mode 100644
index 00000000..e57956d3
--- /dev/null
+++ b/mediagoblin/notifications/routing.py
@@ -0,0 +1,25 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+from mediagoblin.tools.routing import add_route
+
+add_route('mediagoblin.notifications.subscribe_comments',
+ '/u/<string:user>/m/<string:media>/notifications/subscribe/comments/',
+ 'mediagoblin.notifications.views:subscribe_comments')
+
+add_route('mediagoblin.notifications.silence_comments',
+ '/u/<string:user>/m/<string:media>/notifications/silence/',
+ 'mediagoblin.notifications.views:silence_comments')
diff --git a/mediagoblin/notifications/task.py b/mediagoblin/notifications/task.py
new file mode 100644
index 00000000..52573b57
--- /dev/null
+++ b/mediagoblin/notifications/task.py
@@ -0,0 +1,46 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import logging
+
+from celery import registry
+from celery.task import Task
+
+from mediagoblin.tools.mail import send_email
+from mediagoblin.db.models import CommentNotification
+
+
+_log = logging.getLogger(__name__)
+
+
+class EmailNotificationTask(Task):
+ '''
+ Celery notification task.
+
+ This task is executed by celeryd to offload long-running operations from
+ the web server.
+ '''
+ def run(self, notification_id, message):
+ cn = CommentNotification.query.filter_by(id=notification_id).first()
+ _log.info('Sending notification email about {0}'.format(cn))
+
+ return send_email(
+ message['from'],
+ [message['to']],
+ message['subject'],
+ message['body'])
+
+email_notification_task = registry.tasks[EmailNotificationTask.name]
diff --git a/mediagoblin/notifications/tools.py b/mediagoblin/notifications/tools.py
new file mode 100644
index 00000000..25432780
--- /dev/null
+++ b/mediagoblin/notifications/tools.py
@@ -0,0 +1,55 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+from mediagoblin.tools.template import render_template
+from mediagoblin.tools.translate import pass_to_ugettext as _
+from mediagoblin import mg_globals
+
+def generate_comment_message(user, comment, media, request):
+ """
+ Sends comment email to user when a comment is made on their media.
+
+ Args:
+ - user: the user object to whom the email is sent
+ - comment: the comment object referencing user's media
+ - media: the media object the comment is about
+ - request: the request
+ """
+
+ comment_url = request.urlgen(
+ 'mediagoblin.user_pages.media_home.view_comment',
+ comment=comment.id,
+ user=media.get_uploader.username,
+ media=media.slug_or_id,
+ qualified=True) + '#comment'
+
+ comment_author = comment.get_author.username
+
+ rendered_email = render_template(
+ request, 'mediagoblin/user_pages/comment_email.txt',
+ {'username': user.username,
+ 'comment_author': comment_author,
+ 'comment_content': comment.content,
+ 'comment_url': comment_url})
+
+ return {
+ 'from': mg_globals.app_config['email_sender_address'],
+ 'to': user.email,
+ 'subject': '{instance_title} - {comment_author} '.format(
+ comment_author=comment_author,
+ instance_title=mg_globals.app_config['html_title']) \
+ + _('commented on your post'),
+ 'body': rendered_email}
diff --git a/mediagoblin/notifications/views.py b/mediagoblin/notifications/views.py
new file mode 100644
index 00000000..d275bc92
--- /dev/null
+++ b/mediagoblin/notifications/views.py
@@ -0,0 +1,54 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+from mediagoblin.tools.response import render_to_response, render_404, redirect
+from mediagoblin.tools.translate import pass_to_ugettext as _
+from mediagoblin.decorators import (uses_pagination, get_user_media_entry,
+ get_media_entry_by_id,
+ require_active_login, user_may_delete_media, user_may_alter_collection,
+ get_user_collection, get_user_collection_item, active_user_from_url)
+
+from mediagoblin import messages
+
+from mediagoblin.notifications import add_comment_subscription, \
+ silence_comment_subscription
+
+from werkzeug.exceptions import BadRequest
+
+@get_user_media_entry
+@require_active_login
+def subscribe_comments(request, media):
+
+ add_comment_subscription(request.user, media)
+
+ messages.add_message(request,
+ messages.SUCCESS,
+ _('Subscribed to comments on %s!')
+ % media.title)
+
+ return redirect(request, location=media.url_for_self(request.urlgen))
+
+@get_user_media_entry
+@require_active_login
+def silence_comments(request, media):
+ silence_comment_subscription(request.user, media)
+
+ messages.add_message(request,
+ messages.SUCCESS,
+ _('You will not receive notifications for comments on'
+ ' %s.') % media.title)
+
+ return redirect(request, location=media.url_for_self(request.urlgen))
diff --git a/mediagoblin/plugins/api/views.py b/mediagoblin/plugins/api/views.py
index fde76fe4..9159fe65 100644
--- a/mediagoblin/plugins/api/views.py
+++ b/mediagoblin/plugins/api/views.py
@@ -27,7 +27,7 @@ from mediagoblin.media_types import sniff_media
from mediagoblin.plugins.api.tools import api_auth, get_entry_serializable, \
json_response
from mediagoblin.submit.lib import check_file_field, prepare_queue_task, \
- run_process_media
+ run_process_media, new_upload_entry
_log = logging.getLogger(__name__)
@@ -53,7 +53,7 @@ def post_entry(request):
media_type, media_manager = sniff_media(media_file)
- entry = request.db.MediaEntry()
+ entry = new_upload_entry(request.user)
entry.media_type = unicode(media_type)
entry.title = unicode(request.form.get('title')
or splitext(media_file.filename)[0])
@@ -61,8 +61,6 @@ def post_entry(request):
entry.description = unicode(request.form.get('description'))
entry.license = unicode(request.form.get('license', ''))
- entry.uploader = request.user.id
-
entry.generate_slug()
# queue appropriately
diff --git a/mediagoblin/plugins/basic_auth/__init__.py b/mediagoblin/plugins/basic_auth/__init__.py
new file mode 100644
index 00000000..33a554b0
--- /dev/null
+++ b/mediagoblin/plugins/basic_auth/__init__.py
@@ -0,0 +1,88 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+from mediagoblin.plugins.basic_auth import forms as auth_forms
+from mediagoblin.plugins.basic_auth import tools as auth_tools
+from mediagoblin.auth.tools import create_basic_user
+from mediagoblin.db.models import User
+from mediagoblin.tools import pluginapi
+from sqlalchemy import or_
+
+
+def setup_plugin():
+ config = pluginapi.get_config('mediagoblin.plugins.basic_auth')
+
+
+def get_user(**kwargs):
+ username = kwargs.pop('username', None)
+ if username:
+ user = User.query.filter(
+ or_(
+ User.username == username,
+ User.email == username,
+ )).first()
+ return user
+
+
+def create_user(registration_form):
+ user = get_user(username=registration_form.username.data)
+ if not user and 'password' in registration_form:
+ user = create_basic_user(registration_form)
+ user.pw_hash = gen_password_hash(
+ registration_form.password.data)
+ user.save()
+ return user
+
+
+def get_login_form(request):
+ return auth_forms.LoginForm(request.form)
+
+
+def get_registration_form(request):
+ return auth_forms.RegistrationForm(request.form)
+
+
+def gen_password_hash(raw_pass, extra_salt=None):
+ return auth_tools.bcrypt_gen_password_hash(raw_pass, extra_salt)
+
+
+def check_password(raw_pass, stored_hash, extra_salt=None):
+ if stored_hash:
+ return auth_tools.bcrypt_check_password(raw_pass,
+ stored_hash, extra_salt)
+ return None
+
+
+def auth():
+ return True
+
+
+def append_to_global_context(context):
+ context['pass_auth'] = True
+ return context
+
+
+hooks = {
+ 'setup': setup_plugin,
+ 'authentication': auth,
+ 'auth_get_user': get_user,
+ 'auth_create_user': create_user,
+ 'auth_get_login_form': get_login_form,
+ 'auth_get_registration_form': get_registration_form,
+ 'auth_gen_password_hash': gen_password_hash,
+ 'auth_check_password': check_password,
+ 'auth_fake_login_attempt': auth_tools.fake_login_attempt,
+ 'template_global_context': append_to_global_context,
+}
diff --git a/mediagoblin/plugins/basic_auth/forms.py b/mediagoblin/plugins/basic_auth/forms.py
new file mode 100644
index 00000000..6cf01b38
--- /dev/null
+++ b/mediagoblin/plugins/basic_auth/forms.py
@@ -0,0 +1,46 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import wtforms
+
+from mediagoblin.tools.translate import lazy_pass_to_ugettext as _
+from mediagoblin.auth.tools import normalize_user_or_email_field
+
+
+class RegistrationForm(wtforms.Form):
+ username = wtforms.TextField(
+ _('Username'),
+ [wtforms.validators.Required(),
+ normalize_user_or_email_field(allow_email=False)])
+ password = wtforms.PasswordField(
+ _('Password'),
+ [wtforms.validators.Required(),
+ wtforms.validators.Length(min=5, max=1024)])
+ email = wtforms.TextField(
+ _('Email address'),
+ [wtforms.validators.Required(),
+ normalize_user_or_email_field(allow_user=False)])
+
+
+class LoginForm(wtforms.Form):
+ username = wtforms.TextField(
+ _('Username or Email'),
+ [wtforms.validators.Required(),
+ normalize_user_or_email_field()])
+ password = wtforms.PasswordField(
+ _('Password'))
+ stay_logged_in = wtforms.BooleanField(
+ label='',
+ description=_('Stay logged in'))
diff --git a/mediagoblin/auth/lib.py b/mediagoblin/plugins/basic_auth/tools.py
index 8829995a..1300bb9a 100644
--- a/mediagoblin/auth/lib.py
+++ b/mediagoblin/plugins/basic_auth/tools.py
@@ -13,14 +13,8 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-import random
-
import bcrypt
-
-from mediagoblin.tools.mail import send_email
-from mediagoblin.tools.template import render_template
-from mediagoblin import mg_globals
+import random
def bcrypt_check_password(raw_pass, stored_hash, extra_salt=None):
@@ -88,68 +82,3 @@ def fake_login_attempt():
randplus_hashed_pass = bcrypt.hashpw(hashed_pass, rand_salt)
randplus_stored_hash == randplus_hashed_pass
-
-
-EMAIL_VERIFICATION_TEMPLATE = (
- u"http://{host}{uri}?"
- u"userid={userid}&token={verification_key}")
-
-
-def send_verification_email(user, request):
- """
- Send the verification email to users to activate their accounts.
-
- Args:
- - user: a user object
- - request: the request
- """
- rendered_email = render_template(
- request, 'mediagoblin/auth/verification_email.txt',
- {'username': user.username,
- 'verification_url': EMAIL_VERIFICATION_TEMPLATE.format(
- host=request.host,
- uri=request.urlgen('mediagoblin.auth.verify_email'),
- userid=unicode(user.id),
- verification_key=user.verification_key)})
-
- # TODO: There is no error handling in place
- send_email(
- mg_globals.app_config['email_sender_address'],
- [user.email],
- # TODO
- # Due to the distributed nature of GNU MediaGoblin, we should
- # find a way to send some additional information about the
- # specific GNU MediaGoblin instance in the subject line. For
- # example "GNU MediaGoblin @ Wandborg - [...]".
- 'GNU MediaGoblin - Verify your email!',
- rendered_email)
-
-
-EMAIL_FP_VERIFICATION_TEMPLATE = (
- u"http://{host}{uri}?"
- u"userid={userid}&token={fp_verification_key}")
-
-
-def send_fp_verification_email(user, request):
- """
- Send the verification email to users to change their password.
-
- Args:
- - user: a user object
- - request: the request
- """
- rendered_email = render_template(
- request, 'mediagoblin/auth/fp_verification_email.txt',
- {'username': user.username,
- 'verification_url': EMAIL_FP_VERIFICATION_TEMPLATE.format(
- host=request.host,
- uri=request.urlgen('mediagoblin.auth.verify_forgot_password'),
- userid=unicode(user.id),
- fp_verification_key=user.fp_verification_key)})
-
- # TODO: There is no error handling in place
- send_email(
- mg_globals.app_config['email_sender_address'],
- [user.email],
- 'GNU MediaGoblin - Change forgotten password!',
- rendered_email)
diff --git a/mediagoblin/plugins/httpapiauth/__init__.py b/mediagoblin/plugins/httpapiauth/__init__.py
index 99b6a4b0..2b2d593c 100644
--- a/mediagoblin/plugins/httpapiauth/__init__.py
+++ b/mediagoblin/plugins/httpapiauth/__init__.py
@@ -18,6 +18,7 @@ import logging
from werkzeug.exceptions import Unauthorized
+from mediagoblin.auth.tools import check_login_simple
from mediagoblin.plugins.api.tools import Auth
_log = logging.getLogger(__name__)
@@ -39,10 +40,10 @@ class HTTPAuth(Auth):
if not request.authorization:
return False
- user = request.db.User.query.filter_by(
- username=unicode(request.authorization['username'])).first()
+ user = check_login_simple(unicode(request.authorization['username']),
+ request.authorization['password'])
- if user.check_login(request.authorization['password']):
+ if user:
request.user = user
return True
else:
diff --git a/mediagoblin/plugins/openid/__init__.py b/mediagoblin/plugins/openid/__init__.py
new file mode 100644
index 00000000..ee88808c
--- /dev/null
+++ b/mediagoblin/plugins/openid/__init__.py
@@ -0,0 +1,123 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import os
+import uuid
+
+from sqlalchemy import or_
+
+from mediagoblin.auth.tools import create_basic_user
+from mediagoblin.db.models import User
+from mediagoblin.plugins.openid.models import OpenIDUserURL
+from mediagoblin.tools import pluginapi
+from mediagoblin.tools.translate import lazy_pass_to_ugettext as _
+
+PLUGIN_DIR = os.path.dirname(__file__)
+
+
+def setup_plugin():
+ config = pluginapi.get_config('mediagoblin.plugins.openid')
+
+ routes = [
+ ('mediagoblin.plugins.openid.register',
+ '/auth/openid/register/',
+ 'mediagoblin.plugins.openid.views:register'),
+ ('mediagoblin.plugins.openid.login',
+ '/auth/openid/login/',
+ 'mediagoblin.plugins.openid.views:login'),
+ ('mediagoblin.plugins.openid.finish_login',
+ '/auth/openid/login/finish/',
+ 'mediagoblin.plugins.openid.views:finish_login'),
+ ('mediagoblin.plugins.openid.edit',
+ '/edit/openid/',
+ 'mediagoblin.plugins.openid.views:start_edit'),
+ ('mediagoblin.plugins.openid.finish_edit',
+ '/edit/openid/finish/',
+ 'mediagoblin.plugins.openid.views:finish_edit'),
+ ('mediagoblin.plugins.openid.delete',
+ '/edit/openid/delete/',
+ 'mediagoblin.plugins.openid.views:delete_openid'),
+ ('mediagoblin.plugins.openid.finish_delete',
+ '/edit/openid/delete/finish/',
+ 'mediagoblin.plugins.openid.views:finish_delete')]
+
+ pluginapi.register_routes(routes)
+ pluginapi.register_template_path(os.path.join(PLUGIN_DIR, 'templates'))
+
+ pluginapi.register_template_hooks(
+ {'register_link': 'mediagoblin/plugins/openid/register_link.html',
+ 'login_link': 'mediagoblin/plugins/openid/login_link.html',
+ 'edit_link': 'mediagoblin/plugins/openid/edit_link.html'})
+
+
+def create_user(register_form):
+ if 'openid' in register_form:
+ username = register_form.username.data
+ user = User.query.filter(
+ or_(
+ User.username == username,
+ User.email == username,
+ )).first()
+
+ if not user:
+ user = create_basic_user(register_form)
+
+ new_entry = OpenIDUserURL()
+ new_entry.openid_url = register_form.openid.data
+ new_entry.user_id = user.id
+ new_entry.save()
+
+ return user
+
+
+def extra_validation(register_form):
+ openid = register_form.openid.data if 'openid' in \
+ register_form else None
+ if openid:
+ openid_url_exists = OpenIDUserURL.query.filter_by(
+ openid_url=openid
+ ).count()
+
+ extra_validation_passes = True
+
+ if openid_url_exists:
+ register_form.openid.errors.append(
+ _('Sorry, an account is already registered to that OpenID.'))
+ extra_validation_passes = False
+
+ return extra_validation_passes
+
+
+def no_pass_redirect():
+ return 'openid'
+
+
+def add_to_form_context(context):
+ context['openid_link'] = True
+ return context
+
+
+def Auth():
+ return True
+
+hooks = {
+ 'setup': setup_plugin,
+ 'authentication': Auth,
+ 'auth_extra_validation': extra_validation,
+ 'auth_create_user': create_user,
+ 'auth_no_pass_redirect': no_pass_redirect,
+ ('mediagoblin.auth.register',
+ 'mediagoblin/auth/register.html'): add_to_form_context,
+}
diff --git a/mediagoblin/plugins/openid/forms.py b/mediagoblin/plugins/openid/forms.py
new file mode 100644
index 00000000..f26024bd
--- /dev/null
+++ b/mediagoblin/plugins/openid/forms.py
@@ -0,0 +1,41 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import wtforms
+
+from mediagoblin.tools.translate import lazy_pass_to_ugettext as _
+from mediagoblin.auth.tools import normalize_user_or_email_field
+
+
+class RegistrationForm(wtforms.Form):
+ openid = wtforms.HiddenField(
+ '',
+ [wtforms.validators.Required()])
+ username = wtforms.TextField(
+ _('Username'),
+ [wtforms.validators.Required(),
+ normalize_user_or_email_field(allow_email=False)])
+ email = wtforms.TextField(
+ _('Email address'),
+ [wtforms.validators.Required(),
+ normalize_user_or_email_field(allow_user=False)])
+
+
+class LoginForm(wtforms.Form):
+ openid = wtforms.TextField(
+ _('OpenID'),
+ [wtforms.validators.Required(),
+ # Can openid's only be urls?
+ wtforms.validators.URL(message='Please enter a valid url.')])
diff --git a/mediagoblin/plugins/openid/models.py b/mediagoblin/plugins/openid/models.py
new file mode 100644
index 00000000..6773f0ad
--- /dev/null
+++ b/mediagoblin/plugins/openid/models.py
@@ -0,0 +1,65 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+from sqlalchemy import Column, Integer, Unicode, ForeignKey
+from sqlalchemy.orm import relationship, backref
+
+from mediagoblin.db.models import User
+from mediagoblin.db.base import Base
+
+
+class OpenIDUserURL(Base):
+ __tablename__ = "openid__user_urls"
+
+ id = Column(Integer, primary_key=True)
+ openid_url = Column(Unicode, nullable=False)
+ user_id = Column(Integer, ForeignKey(User.id), nullable=False)
+
+ # OpenID's are owned by their user, so do the full thing.
+ user = relationship(User, backref=backref('openid_urls',
+ cascade='all, delete-orphan'))
+
+
+# OpenID Store Models
+class Nonce(Base):
+ __tablename__ = "openid__nonce"
+
+ server_url = Column(Unicode, primary_key=True)
+ timestamp = Column(Integer, primary_key=True)
+ salt = Column(Unicode, primary_key=True)
+
+ def __unicode__(self):
+ return u'Nonce: %r, %r' % (self.server_url, self.salt)
+
+
+class Association(Base):
+ __tablename__ = "openid__association"
+
+ server_url = Column(Unicode, primary_key=True)
+ handle = Column(Unicode, primary_key=True)
+ secret = Column(Unicode)
+ issued = Column(Integer)
+ lifetime = Column(Integer)
+ assoc_type = Column(Unicode)
+
+ def __unicode__(self):
+ return u'Association: %r, %r' % (self.server_url, self.handle)
+
+
+MODELS = [
+ OpenIDUserURL,
+ Nonce,
+ Association
+]
diff --git a/mediagoblin/plugins/openid/store.py b/mediagoblin/plugins/openid/store.py
new file mode 100644
index 00000000..8f9a7012
--- /dev/null
+++ b/mediagoblin/plugins/openid/store.py
@@ -0,0 +1,127 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import base64
+import time
+
+from openid.association import Association as OIDAssociation
+from openid.store.interface import OpenIDStore
+from openid.store import nonce
+
+from mediagoblin.plugins.openid.models import Association, Nonce
+
+
+class SQLAlchemyOpenIDStore(OpenIDStore):
+ def __init__(self):
+ self.max_nonce_age = 6 * 60 * 60
+
+ def storeAssociation(self, server_url, association):
+ assoc = Association.query.filter_by(
+ server_url=server_url, handle=association.handle
+ ).first()
+
+ if not assoc:
+ assoc = Association()
+ assoc.server_url = unicode(server_url)
+ assoc.handle = association.handle
+
+ # django uses base64 encoding, python-openid uses a blob field for
+ # secret
+ assoc.secret = unicode(base64.encodestring(association.secret))
+ assoc.issued = association.issued
+ assoc.lifetime = association.lifetime
+ assoc.assoc_type = association.assoc_type
+ assoc.save()
+
+ def getAssociation(self, server_url, handle=None):
+ assocs = []
+ if handle is not None:
+ assocs = Association.query.filter_by(
+ server_url=server_url, handle=handle
+ )
+ else:
+ assocs = Association.query.filter_by(
+ server_url=server_url
+ )
+
+ if assocs.count() == 0:
+ return None
+ else:
+ associations = []
+ for assoc in assocs:
+ association = OIDAssociation(
+ assoc.handle, base64.decodestring(assoc.secret),
+ assoc.issued, assoc.lifetime, assoc.assoc_type
+ )
+ if association.getExpiresIn() == 0:
+ assoc.delete()
+ else:
+ associations.append((association.issued, association))
+
+ if not associations:
+ return None
+ associations.sort()
+ return associations[-1][1]
+
+ def removeAssociation(self, server_url, handle):
+ assocs = Association.query.filter_by(
+ server_url=server_url, handle=handle
+ ).first()
+
+ assoc_exists = True if assocs else False
+ for assoc in assocs:
+ assoc.delete()
+ return assoc_exists
+
+ def useNonce(self, server_url, timestamp, salt):
+ if abs(timestamp - time.time()) > nonce.SKEW:
+ return False
+
+ ononce = Nonce.query.filter_by(
+ server_url=server_url,
+ timestamp=timestamp,
+ salt=salt
+ ).first()
+
+ if ononce:
+ return False
+ else:
+ ononce = Nonce()
+ ononce.server_url = server_url
+ ononce.timestamp = timestamp
+ ononce.salt = salt
+ ononce.save()
+ return True
+
+ def cleanupNonces(self, _now=None):
+ if _now is None:
+ _now = int(time.time())
+ expired = Nonce.query.filter(
+ Nonce.timestamp < (_now - nonce.SKEW)
+ )
+ count = expired.count()
+ for each in expired:
+ each.delete()
+ return count
+
+ def cleanupAssociations(self):
+ now = int(time.time())
+ assoc = Association.query.all()
+ count = 0
+ for each in assoc:
+ if (each.lifetime + each.issued) <= now:
+ each.delete()
+ count = count + 1
+ return count
diff --git a/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html
new file mode 100644
index 00000000..8d308c81
--- /dev/null
+++ b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/add.html
@@ -0,0 +1,44 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#}
+{% extends "mediagoblin/base.html" %}
+
+{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
+
+{% block title -%}
+ {% trans %}Add an OpenID{% endtrans %} &mdash; {{ super() }}
+{%- endblock %}
+
+{% block mediagoblin_content %}
+ <form action="{{ request.urlgen('mediagoblin.plugins.openid.edit') }}"
+ method="POST" enctype="multipart/form-data">
+ {{ csrf_token }}
+ <div class="form_box">
+ <h1>{% trans %}Add an OpenID{% endtrans %}</h1>
+ <p>
+ <a href="{{ request.urlgen('mediagoblin.plugins.openid.delete') }}">
+ {% trans %}Delete an OpenID{% endtrans %}
+ </a>
+ </p>
+ {{ wtforms_util.render_divs(form, True) }}
+ <div class="form_submit_buttons">
+ <input type="submit" value="{% trans %}Add{% endtrans %}" class="button_form"/>
+ </div>
+ </div>
+ </form>
+{% endblock %}
+
diff --git a/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html
new file mode 100644
index 00000000..84301b9e
--- /dev/null
+++ b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/delete.html
@@ -0,0 +1,43 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#}
+{% extends "mediagoblin/base.html" %}
+
+{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
+
+{% block title -%}
+ {% trans %}Delete an OpenID{% endtrans %} &mdash; {{ super() }}
+{%- endblock %}
+
+{% block mediagoblin_content %}
+ <form action="{{ request.urlgen('mediagoblin.plugins.openid.delete') }}"
+ method="POST" enctype="multipart/form-data">
+ {{ csrf_token }}
+ <div class="form_box">
+ <h1>{% trans %}Delete an OpenID{% endtrans %}</h1>
+ <p>
+ <a href="{{ request.urlgen('mediagoblin.plugins.openid.edit') }}">
+ {% trans %}Add an OpenID{% endtrans %}
+ </a>
+ </p>
+ {{ wtforms_util.render_divs(form, True) }}
+ <div class="form_submit_buttons">
+ <input type="submit" value="{% trans %}Delete{% endtrans %}" class="button_form"/>
+ </div>
+ </div>
+ </form>
+{% endblock %}
diff --git a/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html
new file mode 100644
index 00000000..2e63e1f8
--- /dev/null
+++ b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/edit_link.html
@@ -0,0 +1,25 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#}
+
+{% block openid_edit_link %}
+ <p>
+ <a href="{{ request.urlgen('mediagoblin.plugins.openid.edit') }}">
+ {% trans %}Edit your OpenID's{% endtrans %}
+ </a>
+ </p>
+{% endblock %}
diff --git a/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html
new file mode 100644
index 00000000..33df7200
--- /dev/null
+++ b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login.html
@@ -0,0 +1,65 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#}
+{% extends "mediagoblin/base.html" %}
+
+{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
+
+{% block mediagoblin_head %}
+ <script type="text/javascript"
+ src="{{ request.staticdirect('/js/autofilledin_password.js') }}"></script>
+{% endblock %}
+
+{% block title -%}
+ {% trans %}Log in{% endtrans %} &mdash; {{ super() }}
+{%- endblock %}
+
+{% block mediagoblin_content %}
+ <form action="{{ post_url }}"
+ method="POST" enctype="multipart/form-data">
+ {{ csrf_token }}
+ <div class="form_box">
+ <h1>{% trans %}Log in{% endtrans %}</h1>
+ {% if login_failed %}
+ <div class="form_field_error">
+ {% trans %}Logging in failed!{% endtrans %}
+ </div>
+ {% endif %}
+ {% if allow_registration %}
+ <p>
+ {% trans %}Log in to create an account!{% endtrans %}
+ </p>
+ {% endif %}
+ {% if pass_auth is defined %}
+ <p>
+ <a href="{{ request.urlgen('mediagoblin.auth.login') }}?{{ request.query_string }}">
+ {%- trans %}Or login with a password!{% endtrans %}
+ </a>
+ </p>
+ {% endif %}
+ {{ wtforms_util.render_divs(login_form, True) }}
+ <div class="form_submit_buttons">
+ <input type="submit" value="{% trans %}Log in{% endtrans %}" class="button_form"/>
+ </div>
+ {% if next %}
+ <input type="hidden" name="next" value="{{ next }}" class="button_form"
+ style="display: none;"/>
+ {% endif %}
+ </div>
+ </form>
+{% endblock %}
+
diff --git a/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html
new file mode 100644
index 00000000..e5e77d01
--- /dev/null
+++ b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/login_link.html
@@ -0,0 +1,25 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#}
+
+{% block openid_login_link %}
+ <p>
+ <a href="{{ request.urlgen('mediagoblin.plugins.openid.login') }}?{{ request.query_string }}">
+ {%- trans %}Or login with OpenID!{% endtrans %}
+ </a>
+ </p>
+{% endblock %}
diff --git a/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html
new file mode 100644
index 00000000..9bccb4d8
--- /dev/null
+++ b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/register_link.html
@@ -0,0 +1,27 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#}
+
+{% block openid_register_link %}
+ {% if openid_link is defined %}
+ <p>
+ <a href="{{ request.urlgen('mediagoblin.plugins.openid.login') }}">
+ {%- trans %}Or register with OpenID!{% endtrans %}
+ </a>
+ </p>
+ {% endif %}
+{% endblock %}
diff --git a/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/request_form.html b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/request_form.html
new file mode 100644
index 00000000..68d028d0
--- /dev/null
+++ b/mediagoblin/plugins/openid/templates/mediagoblin/plugins/openid/request_form.html
@@ -0,0 +1,24 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#}
+{% extends "mediagoblin/base.html" %}
+
+{% block mediagoblin_content %}
+ <div onload="document.getElementById('openid_message').submit()">
+ {{ html|safe }}
+ </div>
+{% endblock %}
diff --git a/mediagoblin/plugins/openid/views.py b/mediagoblin/plugins/openid/views.py
new file mode 100644
index 00000000..b639a4cb
--- /dev/null
+++ b/mediagoblin/plugins/openid/views.py
@@ -0,0 +1,404 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+from openid.consumer import consumer
+from openid.consumer.discover import DiscoveryFailure
+from openid.extensions.sreg import SRegRequest, SRegResponse
+
+from mediagoblin import mg_globals, messages
+from mediagoblin.db.models import User
+from mediagoblin.decorators import (auth_enabled, allow_registration,
+ require_active_login)
+from mediagoblin.tools.response import redirect, render_to_response
+from mediagoblin.tools.translate import pass_to_ugettext as _
+from mediagoblin.plugins.openid import forms as auth_forms
+from mediagoblin.plugins.openid.models import OpenIDUserURL
+from mediagoblin.plugins.openid.store import SQLAlchemyOpenIDStore
+from mediagoblin.auth.tools import register_user
+
+
+def _start_verification(request, form, return_to, sreg=True):
+ """
+ Start OpenID Verification.
+
+ Returns False if verification fails, otherwise, will return either a
+ redirect or render_to_response object
+ """
+ openid_url = form.openid.data
+ c = consumer.Consumer(request.session, SQLAlchemyOpenIDStore())
+
+ # Try to discover provider
+ try:
+ auth_request = c.begin(openid_url)
+ except DiscoveryFailure:
+ # Discovery failed, return to login page
+ form.openid.errors.append(
+ _('Sorry, the OpenID server could not be found'))
+
+ return False
+
+ host = 'http://' + request.host
+
+ if sreg:
+ # Ask provider for email and nickname
+ auth_request.addExtension(SRegRequest(required=['email', 'nickname']))
+
+ # Do we even need this?
+ if auth_request is None:
+ form.openid.errors.append(
+ _('No OpenID service was found for %s' % openid_url))
+
+ elif auth_request.shouldSendRedirect():
+ # Begin the authentication process as a HTTP redirect
+ redirect_url = auth_request.redirectURL(
+ host, return_to)
+
+ return redirect(
+ request, location=redirect_url)
+
+ else:
+ # Send request as POST
+ form_html = auth_request.htmlMarkup(
+ host, host + return_to,
+ # Is this necessary?
+ form_tag_attrs={'id': 'openid_message'})
+
+ # Beware: this renders a template whose content is a form
+ # and some javascript to submit it upon page load. Non-JS
+ # users will have to click the form submit button to
+ # initiate OpenID authentication.
+ return render_to_response(
+ request,
+ 'mediagoblin/plugins/openid/request_form.html',
+ {'html': form_html})
+
+ return False
+
+
+def _finish_verification(request):
+ """
+ Complete OpenID Verification Process.
+
+ If the verification failed, will return false, otherwise, will return
+ the response
+ """
+ c = consumer.Consumer(request.session, SQLAlchemyOpenIDStore())
+
+ # Check the response from the provider
+ response = c.complete(request.args, request.base_url)
+ if response.status == consumer.FAILURE:
+ messages.add_message(
+ request,
+ messages.WARNING,
+ _('Verification of %s failed: %s' %
+ (response.getDisplayIdentifier(), response.message)))
+
+ elif response.status == consumer.SUCCESS:
+ # Verification was successfull
+ return response
+
+ elif response.status == consumer.CANCEL:
+ # Verification canceled
+ messages.add_message(
+ request,
+ messages.WARNING,
+ _('Verification cancelled'))
+
+ return False
+
+
+def _response_email(response):
+ """ Gets the email from the OpenID providers response"""
+ sreg_response = SRegResponse.fromSuccessResponse(response)
+ if sreg_response and 'email' in sreg_response:
+ return sreg_response.data['email']
+ return None
+
+
+def _response_nickname(response):
+ """ Gets the nickname from the OpenID providers response"""
+ sreg_response = SRegResponse.fromSuccessResponse(response)
+ if sreg_response and 'nickname' in sreg_response:
+ return sreg_response.data['nickname']
+ return None
+
+
+@auth_enabled
+def login(request):
+ """OpenID Login View"""
+ login_form = auth_forms.LoginForm(request.form)
+ allow_registration = mg_globals.app_config["allow_registration"]
+
+ # Can't store next in request.GET because of redirects to OpenID provider
+ # Store it in the session
+ next = request.GET.get('next')
+ request.session['next'] = next
+
+ login_failed = False
+
+ if request.method == 'POST' and login_form.validate():
+ return_to = request.urlgen(
+ 'mediagoblin.plugins.openid.finish_login')
+
+ success = _start_verification(request, login_form, return_to)
+
+ if success:
+ return success
+
+ login_failed = True
+
+ return render_to_response(
+ request,
+ 'mediagoblin/plugins/openid/login.html',
+ {'login_form': login_form,
+ 'next': request.session.get('next'),
+ 'login_failed': login_failed,
+ 'post_url': request.urlgen('mediagoblin.plugins.openid.login'),
+ 'allow_registration': allow_registration})
+
+
+@auth_enabled
+def finish_login(request):
+ """Complete OpenID Login Process"""
+ response = _finish_verification(request)
+
+ if not response:
+ # Verification failed, redirect to login page.
+ return redirect(request, 'mediagoblin.plugins.openid.login')
+
+ # Verification was successfull
+ query = OpenIDUserURL.query.filter_by(
+ openid_url=response.identity_url,
+ ).first()
+ user = query.user if query else None
+
+ if user:
+ # Set up login in session
+ request.session['user_id'] = unicode(user.id)
+ request.session.save()
+
+ if request.session.get('next'):
+ return redirect(request, location=request.session.pop('next'))
+ else:
+ return redirect(request, "index")
+ else:
+ # No user, need to register
+ if not mg_globals.app.auth:
+ messages.add_message(
+ request,
+ messages.WARNING,
+ _('Sorry, authentication is disabled on this instance.'))
+ return redirect(request, 'index')
+
+ # Get email and nickname from response
+ email = _response_email(response)
+ username = _response_nickname(response)
+
+ register_form = auth_forms.RegistrationForm(request.form,
+ openid=response.identity_url,
+ email=email,
+ username=username)
+ return render_to_response(
+ request,
+ 'mediagoblin/auth/register.html',
+ {'register_form': register_form,
+ 'post_url': request.urlgen('mediagoblin.plugins.openid.register')})
+
+
+@allow_registration
+@auth_enabled
+def register(request):
+ """OpenID Registration View"""
+ if request.method == 'GET':
+ # Need to connect to openid provider before registering a user to
+ # get the users openid url. If method is 'GET', then this page was
+ # acessed without logging in first.
+ return redirect(request, 'mediagoblin.plugins.openid.login')
+
+ register_form = auth_forms.RegistrationForm(request.form)
+
+ if register_form.validate():
+ user = register_user(request, register_form)
+
+ if user:
+ # redirect the user to their homepage... there will be a
+ # message waiting for them to verify their email
+ return redirect(
+ request, 'mediagoblin.user_pages.user_home',
+ user=user.username)
+
+ return render_to_response(
+ request,
+ 'mediagoblin/auth/register.html',
+ {'register_form': register_form,
+ 'post_url': request.urlgen('mediagoblin.plugins.openid.register')})
+
+
+@require_active_login
+def start_edit(request):
+ """Starts the process of adding an openid url to a users account"""
+ form = auth_forms.LoginForm(request.form)
+
+ if request.method == 'POST' and form.validate():
+ query = OpenIDUserURL.query.filter_by(
+ openid_url=form.openid.data
+ ).first()
+ user = query.user if query else None
+
+ if not user:
+ return_to = request.urlgen('mediagoblin.plugins.openid.finish_edit')
+ success = _start_verification(request, form, return_to, False)
+
+ if success:
+ return success
+ else:
+ form.openid.errors.append(
+ _('Sorry, an account is already registered to that OpenID.'))
+
+ return render_to_response(
+ request,
+ 'mediagoblin/plugins/openid/add.html',
+ {'form': form,
+ 'post_url': request.urlgen('mediagoblin.plugins.openid.edit')})
+
+
+@require_active_login
+def finish_edit(request):
+ """Finishes the process of adding an openid url to a user"""
+ response = _finish_verification(request)
+
+ if not response:
+ # Verification failed, redirect to add openid page.
+ return redirect(request, 'mediagoblin.plugins.openid.edit')
+
+ # Verification was successfull
+ query = OpenIDUserURL.query.filter_by(
+ openid_url=response.identity_url,
+ ).first()
+ user_exists = query.user if query else None
+
+ if user_exists:
+ # user exists with that openid url, redirect back to edit page
+ messages.add_message(
+ request,
+ messages.WARNING,
+ _('Sorry, an account is already registered to that OpenID.'))
+ return redirect(request, 'mediagoblin.plugins.openid.edit')
+
+ else:
+ # Save openid to user
+ user = User.query.filter_by(
+ id=request.session['user_id']
+ ).first()
+
+ new_entry = OpenIDUserURL()
+ new_entry.openid_url = response.identity_url
+ new_entry.user_id = user.id
+ new_entry.save()
+
+ messages.add_message(
+ request,
+ messages.SUCCESS,
+ _('Your OpenID url was saved successfully.'))
+
+ return redirect(request, 'mediagoblin.edit.account')
+
+
+@require_active_login
+def delete_openid(request):
+ """View to remove an openid from a users account"""
+ form = auth_forms.LoginForm(request.form)
+
+ if request.method == 'POST' and form.validate():
+ # Check if a user has this openid
+ query = OpenIDUserURL.query.filter_by(
+ openid_url=form.openid.data
+ )
+ user = query.first().user if query.first() else None
+
+ if user and user.id == int(request.session['user_id']):
+ count = len(user.openid_urls)
+ if not count > 1 and not user.pw_hash:
+ # Make sure the user has a pw or another OpenID
+ messages.add_message(
+ request,
+ messages.WARNING,
+ _("You can't delete your only OpenID URL unless you"
+ " have a password set"))
+ elif user:
+ # There is a user, but not the same user who is logged in
+ form.openid.errors.append(
+ _('That OpenID is not registered to this account.'))
+
+ if not form.errors and not request.session.get('messages'):
+ # Okay to continue with deleting openid
+ return_to = request.urlgen(
+ 'mediagoblin.plugins.openid.finish_delete')
+ success = _start_verification(request, form, return_to, False)
+
+ if success:
+ return success
+
+ return render_to_response(
+ request,
+ 'mediagoblin/plugins/openid/delete.html',
+ {'form': form,
+ 'post_url': request.urlgen('mediagoblin.plugins.openid.delete')})
+
+
+@require_active_login
+def finish_delete(request):
+ """Finishes the deletion of an OpenID from an user's account"""
+ response = _finish_verification(request)
+
+ if not response:
+ # Verification failed, redirect to delete openid page.
+ return redirect(request, 'mediagoblin.plugins.openid.delete')
+
+ query = OpenIDUserURL.query.filter_by(
+ openid_url=response.identity_url
+ )
+ user = query.first().user if query.first() else None
+
+ # Need to check this again because of generic openid urls such as google's
+ if user and user.id == int(request.session['user_id']):
+ count = len(user.openid_urls)
+ if count > 1 or user.pw_hash:
+ # User has more then one openid or also has a password.
+ query.first().delete()
+
+ messages.add_message(
+ request,
+ messages.SUCCESS,
+ _('OpenID was successfully removed.'))
+
+ return redirect(request, 'mediagoblin.edit.account')
+
+ elif not count > 1:
+ messages.add_message(
+ request,
+ messages.WARNING,
+ _("You can't delete your only OpenID URL unless you have a "
+ "password set"))
+
+ return redirect(request, 'mediagoblin.plugins.openid.delete')
+
+ else:
+ messages.add_message(
+ request,
+ messages.WARNING,
+ _('That OpenID is not registered to this account.'))
+
+ return redirect(request, 'mediagoblin.plugins.openid.delete')
diff --git a/mediagoblin/plugins/piwigo/tools.py b/mediagoblin/plugins/piwigo/tools.py
index 400be615..484ea531 100644
--- a/mediagoblin/plugins/piwigo/tools.py
+++ b/mediagoblin/plugins/piwigo/tools.py
@@ -14,6 +14,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+from collections import namedtuple
import logging
import six
@@ -27,6 +28,9 @@ from mediagoblin.tools.response import Response
_log = logging.getLogger(__name__)
+PwgError = namedtuple("PwgError", ["code", "msg"])
+
+
class PwgNamedArray(list):
def __init__(self, l, item_name, as_attrib=()):
self.item_name = item_name
@@ -74,9 +78,18 @@ def _fill_element(el, data):
def response_xml(result):
r = ET.Element("rsp")
r.set("stat", "ok")
- _fill_element(r, result)
+ status = None
+ if isinstance(result, PwgError):
+ r.set("stat", "fail")
+ err = ET.SubElement(r, "err")
+ err.set("code", str(result.code))
+ err.set("msg", result.msg)
+ if result.code >= 100 and result.code < 600:
+ status = result.code
+ else:
+ _fill_element(r, result)
return Response(ET.tostring(r, encoding="utf-8", xml_declaration=True),
- mimetype='text/xml')
+ mimetype='text/xml', status=status)
class CmdTable(object):
@@ -113,7 +126,7 @@ def check_form(form):
if not form.validate():
_log.error("form validation failed for form %r", form)
for f in form:
- if len(f.error):
+ if len(f.errors):
_log.error("Errors for %s: %r", f.name, f.errors)
raise BadRequest()
dump = []
@@ -140,7 +153,7 @@ class PWGSession(object):
self.in_pwg_session = True
return self
- def __exit__(self, *args):
+ def __exit__(self, *args):
# Restore state
self.request.session = self.old_session
self.request.user = self.old_user
diff --git a/mediagoblin/plugins/piwigo/views.py b/mediagoblin/plugins/piwigo/views.py
index b59247ad..ca723189 100644
--- a/mediagoblin/plugins/piwigo/views.py
+++ b/mediagoblin/plugins/piwigo/views.py
@@ -16,15 +16,23 @@
import logging
import re
+from os.path import splitext
+import shutil
from werkzeug.exceptions import MethodNotAllowed, BadRequest, NotImplemented
from werkzeug.wrappers import BaseResponse
from mediagoblin.meddleware.csrf import csrf_exempt
-from mediagoblin.submit.lib import check_file_field
-from mediagoblin.auth.lib import fake_login_attempt
-from .tools import CmdTable, PwgNamedArray, response_xml, check_form, \
- PWGSession
+from mediagoblin.auth.tools import check_login_simple
+from mediagoblin.media_types import sniff_media
+from mediagoblin.submit.lib import check_file_field, prepare_queue_task, \
+ run_process_media, new_upload_entry
+
+from mediagoblin.user_pages.lib import add_media_to_collection
+from mediagoblin.db.models import Collection
+
+from .tools import CmdTable, response_xml, check_form, \
+ PWGSession, PwgNamedArray, PwgError
from .forms import AddSimpleForm, AddForm
@@ -35,16 +43,9 @@ _log = logging.getLogger(__name__)
def pwg_login(request):
username = request.form.get("username")
password = request.form.get("password")
- _log.debug("Login for %r/%r...", username, password)
- user = request.db.User.query.filter_by(username=username).first()
+ user = check_login_simple(username, password)
if not user:
- _log.info("User %r not found", username)
- fake_login_attempt()
- return False
- if not user.check_login(password):
- _log.warn("Wrong password for %r", username)
- return False
- _log.info("Logging %r in", username)
+ return PwgError(999, 'Invalid username/password')
request.session["user_id"] = user.id
request.session.save()
return True
@@ -73,9 +74,21 @@ def pwg_session_getStatus(request):
@CmdTable("pwg.categories.getList")
def pwg_categories_getList(request):
- catlist = ({'id': -29711,
+ catlist = [{'id': -29711,
'uppercats': "-29711",
- 'name': "All my images"},)
+ 'name': "All my images"}]
+
+ if request.user:
+ collections = Collection.query.filter_by(
+ get_creator=request.user).order_by(Collection.title)
+
+ for c in collections:
+ catlist.append({'id': c.id,
+ 'uppercats': str(c.id),
+ 'name': c.title,
+ 'comment': c.description
+ })
+
return {
'categories': PwgNamedArray(
catlist,
@@ -107,16 +120,69 @@ def pwg_images_addSimple(request):
dump = []
for f in form:
dump.append("%s=%r" % (f.name, f.data))
- _log.info("addimple: %r %s %r", request.form, " ".join(dump), request.files)
+ _log.info("addSimple: %r %s %r", request.form, " ".join(dump),
+ request.files)
if not check_file_field(request, 'image'):
raise BadRequest()
- return {'image_id': 123456, 'url': ''}
+ filename = request.files['image'].filename
+
+ # Sniff the submitted media to determine which
+ # media plugin should handle processing
+ media_type, media_manager = sniff_media(
+ request.files['image'])
+
+ # create entry and save in database
+ entry = new_upload_entry(request.user)
+ entry.media_type = unicode(media_type)
+ entry.title = (
+ unicode(form.name.data)
+ or unicode(splitext(filename)[0]))
+
+ entry.description = unicode(form.comment.data)
+
+ '''
+ # Process the user's folksonomy "tags"
+ entry.tags = convert_to_tag_list_of_dicts(
+ form.tags.data)
+ '''
+
+ # Generate a slug from the title
+ entry.generate_slug()
+
+ queue_file = prepare_queue_task(request.app, entry, filename)
+
+ with queue_file:
+ shutil.copyfileobj(request.files['image'].stream,
+ queue_file,
+ length=4 * 1048576)
+
+ # Save now so we have this data before kicking off processing
+ entry.save()
+
+ # Pass off to processing
+ #
+ # (... don't change entry after this point to avoid race
+ # conditions with changes to the document via processing code)
+ feed_url = request.urlgen(
+ 'mediagoblin.user_pages.atom_feed',
+ qualified=True, user=request.user.username)
+ run_process_media(entry, feed_url)
+
+ collection_id = form.category.data
+ if collection_id > 0:
+ collection = Collection.query.get(collection_id)
+ if collection is not None and collection.creator == request.user.id:
+ add_media_to_collection(collection, entry, "")
+
+ return {'image_id': entry.id, 'url': entry.url_for_self(request.urlgen,
+ qualified=True)}
+
-
md5sum_matcher = re.compile(r"^[0-9a-fA-F]{32}$")
+
def fetch_md5(request, parm_name, optional_parm=False):
val = request.form.get(parm_name)
if (val is None) and (not optional_parm):
diff --git a/mediagoblin/routing.py b/mediagoblin/routing.py
index a650f22f..986eb2ed 100644
--- a/mediagoblin/routing.py
+++ b/mediagoblin/routing.py
@@ -35,6 +35,7 @@ def get_url_map():
import mediagoblin.edit.routing
import mediagoblin.webfinger.routing
import mediagoblin.listings.routing
+ import mediagoblin.notifications.routing
for route in PluginManager().get_routes():
add_route(*route)
diff --git a/mediagoblin/static/css/base.css b/mediagoblin/static/css/base.css
index 0cb36753..84d274d1 100644
--- a/mediagoblin/static/css/base.css
+++ b/mediagoblin/static/css/base.css
@@ -129,6 +129,7 @@ header {
.header_dropdown {
margin-bottom: 20px;
+ padding: 0px 10px 0px 10px;
}
.header_dropdown li {
@@ -333,6 +334,10 @@ text-align: center;
width: 20px;
}
+.boolean {
+ margin-bottom: 8px;
+ }
+
textarea#description, textarea#bio {
resize: vertical;
height: 100px;
@@ -384,6 +389,12 @@ a.comment_whenlink:hover {
margin-top: 8px;
}
+.comment_active {
+ box-shadow: 0px 0px 15px 15px #378566;
+ background: #378566;
+ color: #f7f7f7;
+}
+
textarea#comment_content {
resize: vertical;
width: 100%;
@@ -433,9 +444,12 @@ a.thumb_entry_title {
padding: 8px;
}
-.media_thumbnail img {
- max-height: 135px;
-}
+/* For now, this is commented out since our thumbnails are actually 180px high.
+ *
+ * .media_thumbnail img {
+ * max-height: 135px;
+ * }
+ */
.thumb_entry_last {
margin-right: 0px;
@@ -481,6 +495,38 @@ img.media_icon {
vertical-align: sub;
}
+/* EXIF information */
+
+#exif_content h3 {
+ border-bottom: 1px solid #333;
+}
+
+#exif_camera_information {
+ margin-bottom: 20px;
+}
+
+#exif_additional_info {
+ display: none;
+}
+
+#exif_additional_info table {
+ font-size: 11px;
+ margin-top: 10px;
+}
+
+#exif_additional_info td {
+ vertical-align: top;
+ padding-bottom: 5px;
+}
+
+#exif_content .col1 {
+ padding-right: 20px;
+}
+
+#exif_additional_info table tr {
+ margin-bottom: 10px;
+}
+
/* navigation */
.navigation {
@@ -685,3 +731,29 @@ pre {
width: 46%;
}
}
+
+/* Exif display */
+#exif_content h3 {
+ border-bottom: 1px solid #333;
+}
+#exif_camera_information {
+ margin-bottom: 20px;
+}
+
+#exif_additional_info {
+ display: none;
+}
+#exif_additional_info table {
+ font-size: 11px;
+ margin-top: 10px;
+}
+#exif_additional_info td {
+ vertical-align: top;
+ padding-bottom: 5px;
+}
+#exif_content .col1 {
+ padding-right: 20px;
+}
+#exif_additional_info table tr {
+ margin-bottom: 10px;
+}
diff --git a/mediagoblin/static/css/pdf_viewer.css b/mediagoblin/static/css/pdf_viewer.css
deleted file mode 100644
index c04c8981..00000000
--- a/mediagoblin/static/css/pdf_viewer.css
+++ /dev/null
@@ -1,1448 +0,0 @@
-/* Copyright 2012 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-* {
- padding: 0;
- margin: 0;
-}
-
-html {
- height: 100%;
-}
-
-body {
- height: 100%;
- background-color: #404040;
- background-image: url(../extlib/pdf.js/web/images/texture.png);
-}
-
-body,
-input,
-button,
-select {
- font: message-box;
-}
-
-.hidden {
- display: none;
-}
-[hidden] {
- display: none !important;
-}
-
-#viewerContainer:-webkit-full-screen {
- top: 0px;
- border-top: 2px solid transparent;
- background-color: #404040;
- background-image: url(../extlib/pdf.js/web/images/texture.png);
- width: 100%;
- height: 100%;
- overflow: hidden;
- cursor: none;
-}
-
-#viewerContainer:-moz-full-screen {
- top: 0px;
- border-top: 2px solid transparent;
- background-color: #404040;
- background-image: url(../extlib/pdf.js/web/images/texture.png);
- width: 100%;
- height: 100%;
- overflow: hidden;
- cursor: none;
-}
-
-#viewerContainer:fullscreen {
- top: 0px;
- border-top: 2px solid transparent;
- background-color: #404040;
- background-image: url(../extlib/pdf.js/web/images/texture.png);
- width: 100%;
- height: 100%;
- overflow: hidden;
- cursor: none;
-}
-
-
-:-webkit-full-screen .page {
- margin-bottom: 100%;
-}
-
-:-moz-full-screen .page {
- margin-bottom: 100%;
-}
-
-:fullscreen .page {
- margin-bottom: 100%;
-}
-
-#viewerContainer.presentationControls {
- cursor: default;
-}
-
-/* outer/inner center provides horizontal center */
-html[dir='ltr'] .outerCenter {
- float: right;
- position: relative;
- right: 50%;
-}
-html[dir='rtl'] .outerCenter {
- float: left;
- position: relative;
- left: 50%;
-}
-html[dir='ltr'] .innerCenter {
- float: right;
- position: relative;
- right: -50%;
-}
-html[dir='rtl'] .innerCenter {
- float: left;
- position: relative;
- left: -50%;
-}
-
-#outerContainer {
- width: 100%;
- height: 100%;
-}
-
-#sidebarContainer {
- left: 0;
- right: 0;
- height: 200px;
- visibility: hidden;
- -webkit-transition-duration: 200ms;
- -webkit-transition-timing-function: ease;
- -moz-transition-duration: 200ms;
- -moz-transition-timing-function: ease;
- -ms-transition-duration: 200ms;
- -ms-transition-timing-function: ease;
- -o-transition-duration: 200ms;
- -o-transition-timing-function: ease;
- transition-duration: 200ms;
- transition-timing-function: ease;
-
-}
-html[dir='ltr'] #sidebarContainer {
- -webkit-transition-property: top;
- -moz-transition-property: top;
- -ms-transition-property: top;
- -o-transition-property: top;
- transition-property: top;
- top: -200px;
-}
-html[dir='rtl'] #sidebarContainer {
- -webkit-transition-property: top;
- -ms-transition-property: top;
- -o-transition-property: top;
- transition-property: top;
- top: -200px;
-}
-
-#outerContainer.sidebarMoving > #sidebarContainer,
-#outerContainer.sidebarOpen > #sidebarContainer {
- visibility: visible;
-}
-html[dir='ltr'] #outerContainer.sidebarOpen > #sidebarContainer {
- left: 0px;
-}
-html[dir='rtl'] #outerContainer.sidebarOpen > #sidebarContainer {
- right: 0px;
-}
-
-#mainContainer {
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- min-width: 320px;
- -webkit-transition-duration: 200ms;
- -webkit-transition-timing-function: ease;
- -moz-transition-duration: 200ms;
- -moz-transition-timing-function: ease;
- -ms-transition-duration: 200ms;
- -ms-transition-timing-function: ease;
- -o-transition-duration: 200ms;
- -o-transition-timing-function: ease;
- transition-duration: 200ms;
- transition-timing-function: ease;
-}
-html[dir='ltr'] #outerContainer.sidebarOpen > #mainContainer {
- -webkit-transition-property: left;
- -moz-transition-property: left;
- -ms-transition-property: left;
- -o-transition-property: left;
- transition-property: left;
- left: 200px;
-}
-html[dir='rtl'] #outerContainer.sidebarOpen > #mainContainer {
- -webkit-transition-property: right;
- -moz-transition-property: right;
- -ms-transition-property: right;
- -o-transition-property: right;
- transition-property: right;
- right: 200px;
-}
-
-#sidebarContent {
- top: 32px;
- bottom: 0;
- overflow: auto;
- height: 200px;
-
- background-color: hsla(0,0%,0%,.1);
- box-shadow: inset -1px 0 0 hsla(0,0%,0%,.25);
-}
-html[dir='ltr'] #sidebarContent {
- left: 0;
-}
-html[dir='rtl'] #sidebarContent {
- right: 0;
-}
-
-#viewerContainer {
- overflow: auto;
- box-shadow: inset 1px 0 0 hsla(0,0%,100%,.05);
- top: 32px;
- right: 0;
- bottom: 0;
- left: 0;
- height: 480px;
- width: 640px;
-}
-
-.toolbar {
- left: 0;
- right: 0;
- height: 32px;
- z-index: 9999;
- cursor: default;
-}
-
-#toolbarContainer {
- width: 100%;
-}
-
-#toolbarSidebar {
- width: 200px;
- height: 32px;
- background-image: url(../extlib/pdf.js/web/images/texture.png),
- -webkit-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95));
- background-image: url(../extlib/pdf.js/web/images/texture.png),
- -moz-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95));
- background-image: url(../extlib/pdf.js/web/images/texture.png),
- -ms-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95));
- background-image: url(../extlib/pdf.js/web/images/texture.png),
- -o-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95));
- background-image: url(../extlib/pdf.js/web/images/texture.png),
- linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95));
- box-shadow: inset -1px 0 0 rgba(0, 0, 0, 0.25),
-
- inset 0 -1px 0 hsla(0,0%,100%,.05),
- 0 1px 0 hsla(0,0%,0%,.15),
- 0 0 1px hsla(0,0%,0%,.1);
-}
-
-#toolbarViewer, .findbar {
- position: relative;
- height: 32px;
- background-color: #474747; /* IE9 */
- background-image: url(../extlib/pdf.js/web/images/texture.png),
- -webkit-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95));
- background-image: url(../extlib/pdf.js/web/images/texture.png),
- -moz-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95));
- background-image: url(../extlib/pdf.js/web/images/texture.png),
- -ms-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95));
- background-image: url(../extlib/pdf.js/web/images/texture.png),
- -o-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95));
- background-image: url(../extlib/pdf.js/web/images/texture.png),
- linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95));
- box-shadow: inset 1px 0 0 hsla(0,0%,100%,.08),
- inset 0 1px 1px hsla(0,0%,0%,.15),
- inset 0 -1px 0 hsla(0,0%,100%,.05),
- 0 1px 0 hsla(0,0%,0%,.15),
- 0 1px 1px hsla(0,0%,0%,.1);
-}
-
-.findbar {
- top: 64px;
- z-index: 10000;
- height: 32px;
-
- min-width: 16px;
- padding: 0px 6px 0px 6px;
- margin: 4px 2px 4px 2px;
- color: hsl(0,0%,85%);
- font-size: 12px;
- line-height: 14px;
- text-align: left;
- cursor: default;
-}
-
-html[dir='ltr'] .findbar {
- left: 68px;
-}
-
-html[dir='rtl'] .findbar {
- right: 68px;
-}
-
-.findbar label {
- -webkit-user-select: none;
- -moz-user-select: none;
-}
-
-#findInput[data-status="pending"] {
- background-image: url(../extlib/pdf.js/web/images/loading-small.png);
- background-repeat: no-repeat;
- background-position: right;
-}
-
-.doorHanger {
- border: 1px solid hsla(0,0%,0%,.5);
- border-radius: 2px;
- box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
-}
-.doorHanger:after, .doorHanger:before {
- bottom: 100%;
- border: solid transparent;
- content: " ";
- height: 0;
- width: 0;
- pointer-events: none;
-}
-.doorHanger:after {
- border-bottom-color: hsla(0,0%,32%,.99);
- border-width: 8px;
-}
-.doorHanger:before {
- border-bottom-color: hsla(0,0%,0%,.5);
- border-width: 9px;
-}
-
-html[dir='ltr'] .doorHanger:after {
- left: 13px;
- margin-left: -8px;
-}
-
-html[dir='ltr'] .doorHanger:before {
- left: 13px;
- margin-left: -9px;
-}
-
-html[dir='rtl'] .doorHanger:after {
- right: 13px;
- margin-right: -8px;
-}
-
-html[dir='rtl'] .doorHanger:before {
- right: 13px;
- margin-right: -9px;
-}
-
-#findMsg {
- font-style: italic;
- color: #A6B7D0;
-}
-
-.notFound {
- background-color: rgb(255, 137, 153);
-}
-
-html[dir='ltr'] #toolbarViewerLeft {
- margin-left: -1px;
-}
-html[dir='rtl'] #toolbarViewerRight {
- margin-left: -1px;
-}
-
-
-html[dir='ltr'] #toolbarViewerLeft,
-html[dir='rtl'] #toolbarViewerRight {
- position: absolute;
- top: 0;
- left: 0;
-}
-html[dir='ltr'] #toolbarViewerRight,
-html[dir='rtl'] #toolbarViewerLeft {
- position: absolute;
- top: 0;
- right: 0;
-}
-html[dir='ltr'] #toolbarViewerLeft > *,
-html[dir='ltr'] #toolbarViewerMiddle > *,
-html[dir='ltr'] #toolbarViewerRight > *,
-html[dir='ltr'] .findbar > * {
- float: left;
-}
-html[dir='rtl'] #toolbarViewerLeft > *,
-html[dir='rtl'] #toolbarViewerMiddle > *,
-html[dir='rtl'] #toolbarViewerRight > *,
-html[dir='rtl'] .findbar > * {
- float: right;
-}
-
-html[dir='ltr'] .splitToolbarButton {
- margin: 3px 2px 4px 0;
- display: inline-block;
-}
-html[dir='rtl'] .splitToolbarButton {
- margin: 3px 0 4px 2px;
- display: inline-block;
-}
-html[dir='ltr'] .splitToolbarButton > .toolbarButton {
- border-radius: 0;
- float: left;
-}
-html[dir='rtl'] .splitToolbarButton > .toolbarButton {
- border-radius: 0;
- float: right;
-}
-
-.toolbarButton {
- border: 0 none;
- background-color: rgba(0, 0, 0, 0);
- width: 32px;
- height: 25px;
-}
-
-.toolbarButton > span {
- display: inline-block;
- width: 0;
- height: 0;
- overflow: hidden;
-}
-
-.toolbarButton[disabled] {
- opacity: .5;
-}
-
-.toolbarButton.group {
- margin-right: 0;
-}
-
-.splitToolbarButton.toggled .toolbarButton {
- margin: 0;
-}
-
-.splitToolbarButton:hover > .toolbarButton,
-.splitToolbarButton:focus > .toolbarButton,
-.splitToolbarButton.toggled > .toolbarButton,
-.toolbarButton.textButton {
- background-color: hsla(0,0%,0%,.12);
- background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-clip: padding-box;
- border: 1px solid hsla(0,0%,0%,.35);
- border-color: hsla(0,0%,0%,.32) hsla(0,0%,0%,.38) hsla(0,0%,0%,.42);
- box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
- 0 0 1px hsla(0,0%,100%,.15) inset,
- 0 1px 0 hsla(0,0%,100%,.05);
- -webkit-transition-property: background-color, border-color, box-shadow;
- -webkit-transition-duration: 150ms;
- -webkit-transition-timing-function: ease;
- -moz-transition-property: background-color, border-color, box-shadow;
- -moz-transition-duration: 150ms;
- -moz-transition-timing-function: ease;
- -ms-transition-property: background-color, border-color, box-shadow;
- -ms-transition-duration: 150ms;
- -ms-transition-timing-function: ease;
- -o-transition-property: background-color, border-color, box-shadow;
- -o-transition-duration: 150ms;
- -o-transition-timing-function: ease;
- transition-property: background-color, border-color, box-shadow;
- transition-duration: 150ms;
- transition-timing-function: ease;
-
-}
-.splitToolbarButton > .toolbarButton:hover,
-.splitToolbarButton > .toolbarButton:focus,
-.dropdownToolbarButton:hover,
-.toolbarButton.textButton:hover,
-.toolbarButton.textButton:focus {
- background-color: hsla(0,0%,0%,.2);
- box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
- 0 0 1px hsla(0,0%,100%,.15) inset,
- 0 0 1px hsla(0,0%,0%,.05);
- z-index: 199;
-}
-html[dir='ltr'] .splitToolbarButton > .toolbarButton:first-child,
-html[dir='rtl'] .splitToolbarButton > .toolbarButton:last-child {
- position: relative;
- margin: 0;
- margin-right: -1px;
- border-top-left-radius: 2px;
- border-bottom-left-radius: 2px;
- border-right-color: transparent;
-}
-html[dir='ltr'] .splitToolbarButton > .toolbarButton:last-child,
-html[dir='rtl'] .splitToolbarButton > .toolbarButton:first-child {
- position: relative;
- margin: 0;
- margin-left: -1px;
- border-top-right-radius: 2px;
- border-bottom-right-radius: 2px;
- border-left-color: transparent;
-}
-.splitToolbarButtonSeparator {
- padding: 8px 0;
- width: 1px;
- background-color: hsla(0,0%,00%,.5);
- z-index: 99;
- box-shadow: 0 0 0 1px hsla(0,0%,100%,.08);
- display: inline-block;
- margin: 5px 0;
-}
-html[dir='ltr'] .splitToolbarButtonSeparator {
- float: left;
-}
-html[dir='rtl'] .splitToolbarButtonSeparator {
- float: right;
-}
-.splitToolbarButton:hover > .splitToolbarButtonSeparator,
-.splitToolbarButton.toggled > .splitToolbarButtonSeparator {
- padding: 12px 0;
- margin: 1px 0;
- box-shadow: 0 0 0 1px hsla(0,0%,100%,.03);
- -webkit-transition-property: padding;
- -webkit-transition-duration: 10ms;
- -webkit-transition-timing-function: ease;
- -moz-transition-property: padding;
- -moz-transition-duration: 10ms;
- -moz-transition-timing-function: ease;
- -ms-transition-property: padding;
- -ms-transition-duration: 10ms;
- -ms-transition-timing-function: ease;
- -o-transition-property: padding;
- -o-transition-duration: 10ms;
- -o-transition-timing-function: ease;
- transition-property: padding;
- transition-duration: 10ms;
- transition-timing-function: ease;
-}
-
-.toolbarButton,
-.dropdownToolbarButton {
- min-width: 16px;
- padding: 2px 6px 0;
- border: 1px solid transparent;
- border-radius: 2px;
- color: hsl(0,0%,95%);
- font-size: 12px;
- line-height: 14px;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- /* Opera does not support user-select, use <... unselectable="on"> instead */
- cursor: default;
- -webkit-transition-property: background-color, border-color, box-shadow;
- -webkit-transition-duration: 150ms;
- -webkit-transition-timing-function: ease;
- -moz-transition-property: background-color, border-color, box-shadow;
- -moz-transition-duration: 150ms;
- -moz-transition-timing-function: ease;
- -ms-transition-property: background-color, border-color, box-shadow;
- -ms-transition-duration: 150ms;
- -ms-transition-timing-function: ease;
- -o-transition-property: background-color, border-color, box-shadow;
- -o-transition-duration: 150ms;
- -o-transition-timing-function: ease;
- transition-property: background-color, border-color, box-shadow;
- transition-duration: 150ms;
- transition-timing-function: ease;
-}
-
-html[dir='ltr'] .toolbarButton,
-html[dir='ltr'] .dropdownToolbarButton {
- margin: 3px 2px 4px 0;
-}
-html[dir='rtl'] .toolbarButton,
-html[dir='rtl'] .dropdownToolbarButton {
- margin: 3px 0 4px 2px;
-}
-
-.toolbarButton:hover,
-.toolbarButton:focus,
-.dropdownToolbarButton {
- background-color: hsla(0,0%,0%,.12);
- background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-clip: padding-box;
- border: 1px solid hsla(0,0%,0%,.35);
- border-color: hsla(0,0%,0%,.32) hsla(0,0%,0%,.38) hsla(0,0%,0%,.42);
- box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
- 0 0 1px hsla(0,0%,100%,.15) inset,
- 0 1px 0 hsla(0,0%,100%,.05);
-}
-
-.toolbarButton:hover:active,
-.dropdownToolbarButton:hover:active {
- background-color: hsla(0,0%,0%,.2);
- background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- border-color: hsla(0,0%,0%,.35) hsla(0,0%,0%,.4) hsla(0,0%,0%,.45);
- box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset,
- 0 0 1px hsla(0,0%,0%,.2) inset,
- 0 1px 0 hsla(0,0%,100%,.05);
- -webkit-transition-property: background-color, border-color, box-shadow;
- -webkit-transition-duration: 10ms;
- -webkit-transition-timing-function: linear;
- -moz-transition-property: background-color, border-color, box-shadow;
- -moz-transition-duration: 10ms;
- -moz-transition-timing-function: linear;
- -ms-transition-property: background-color, border-color, box-shadow;
- -ms-transition-duration: 10ms;
- -ms-transition-timing-function: linear;
- -o-transition-property: background-color, border-color, box-shadow;
- -o-transition-duration: 10ms;
- -o-transition-timing-function: linear;
- transition-property: background-color, border-color, box-shadow;
- transition-duration: 10ms;
- transition-timing-function: linear;
-}
-
-.toolbarButton.toggled,
-.splitToolbarButton.toggled > .toolbarButton.toggled {
- background-color: hsla(0,0%,0%,.3);
- background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- border-color: hsla(0,0%,0%,.4) hsla(0,0%,0%,.45) hsla(0,0%,0%,.5);
- box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset,
- 0 0 1px hsla(0,0%,0%,.2) inset,
- 0 1px 0 hsla(0,0%,100%,.05);
- -webkit-transition-property: background-color, border-color, box-shadow;
- -webkit-transition-duration: 10ms;
- -webkit-transition-timing-function: linear;
- -moz-transition-property: background-color, border-color, box-shadow;
- -moz-transition-duration: 10ms;
- -moz-transition-timing-function: linear;
- -ms-transition-property: background-color, border-color, box-shadow;
- -ms-transition-duration: 10ms;
- -ms-transition-timing-function: linear;
- -o-transition-property: background-color, border-color, box-shadow;
- -o-transition-duration: 10ms;
- -o-transition-timing-function: linear;
- transition-property: background-color, border-color, box-shadow;
- transition-duration: 10ms;
- transition-timing-function: linear;
-}
-
-.toolbarButton.toggled:hover:active,
-.splitToolbarButton.toggled > .toolbarButton.toggled:hover:active {
- background-color: hsla(0,0%,0%,.4);
- border-color: hsla(0,0%,0%,.4) hsla(0,0%,0%,.5) hsla(0,0%,0%,.55);
- box-shadow: 0 1px 1px hsla(0,0%,0%,.2) inset,
- 0 0 1px hsla(0,0%,0%,.3) inset,
- 0 1px 0 hsla(0,0%,100%,.05);
-}
-
-.dropdownToolbarButton {
- width: 120px;
- max-width: 120px;
- padding: 3px 2px 2px;
- overflow: hidden;
- background: url(../extlib/pdf.js/web/images/toolbarButton-menuArrows.png) no-repeat;
-}
-html[dir='ltr'] .dropdownToolbarButton {
- background-position: 95%;
-}
-html[dir='rtl'] .dropdownToolbarButton {
- background-position: 5%;
-}
-
-.dropdownToolbarButton > select {
- -webkit-appearance: none;
- -moz-appearance: none; /* in the future this might matter, see bugzilla bug #649849 */
- min-width: 140px;
- font-size: 12px;
- color: hsl(0,0%,95%);
- margin: 0;
- padding: 0;
- border: none;
- background: rgba(0,0,0,0); /* Opera does not support 'transparent' <select> background */
-}
-
-.dropdownToolbarButton > select > option {
- background: hsl(0,0%,24%);
-}
-
-#customScaleOption {
- display: none;
-}
-
-#pageWidthOption {
- border-bottom: 1px rgba(255, 255, 255, .5) solid;
-}
-
-html[dir='ltr'] .splitToolbarButton:first-child,
-html[dir='ltr'] .toolbarButton:first-child,
-html[dir='rtl'] .splitToolbarButton:last-child,
-html[dir='rtl'] .toolbarButton:last-child {
- margin-left: 4px;
-}
-html[dir='ltr'] .splitToolbarButton:last-child,
-html[dir='ltr'] .toolbarButton:last-child,
-html[dir='rtl'] .splitToolbarButton:first-child,
-html[dir='rtl'] .toolbarButton:first-child {
- margin-right: 4px;
-}
-
-.toolbarButtonSpacer {
- width: 30px;
- display: inline-block;
- height: 1px;
-}
-
-.toolbarButtonFlexibleSpacer {
- -webkit-box-flex: 1;
- -moz-box-flex: 1;
- min-width: 30px;
-}
-
-.toolbarButton#sidebarToggle::before {
- display: inline-block;
- content: url(../extlib/pdf.js/web/images/toolbarButton-sidebarToggle.png);
-}
-
-html[dir='ltr'] #findPrevious {
- margin-left: 3px;
-}
-html[dir='ltr'] #findNext {
- margin-right: 3px;
-}
-
-html[dir='rtl'] #findPrevious {
- margin-right: 3px;
-}
-html[dir='rtl'] #findNext {
- margin-left: 3px;
-}
-
-html[dir='ltr'] .toolbarButton.findPrevious::before {
- display: inline-block;
- content: url(../extlib/pdf.js/web/images/findbarButton-previous.png);
-}
-
-html[dir='rtl'] .toolbarButton.findPrevious::before {
- display: inline-block;
- content: url(../extlib/pdf.js/web/images/findbarButton-previous-rtl.png);
-}
-
-html[dir='ltr'] .toolbarButton.findNext::before {
- display: inline-block;
- content: url(../extlib/pdf.js/web/images/findbarButton-next.png);
-}
-
-html[dir='rtl'] .toolbarButton.findNext::before {
- display: inline-block;
- content: url(../extlib/pdf.js/web/images/findbarButton-next-rtl.png);
-}
-
-html[dir='ltr'] .toolbarButton.pageUp::before {
- display: inline-block;
- content: url(../extlib/pdf.js/web/images/toolbarButton-pageUp.png);
-}
-
-html[dir='rtl'] .toolbarButton.pageUp::before {
- display: inline-block;
- content: url(../extlib/pdf.js/web/images/toolbarButton-pageUp-rtl.png);
-}
-
-html[dir='ltr'] .toolbarButton.pageDown::before {
- display: inline-block;
- content: url(../extlib/pdf.js/web/images/toolbarButton-pageDown.png);
-}
-
-html[dir='rtl'] .toolbarButton.pageDown::before {
- display: inline-block;
- content: url(../extlib/pdf.js/web/images/toolbarButton-pageDown-rtl.png);
-}
-
-.toolbarButton.zoomOut::before {
- display: inline-block;
- content: url(../extlib/pdf.js/web/images/toolbarButton-zoomOut.png);
-}
-
-.toolbarButton.zoomIn::before {
- display: inline-block;
- content: url(../extlib/pdf.js/web/images/toolbarButton-zoomIn.png);
-}
-
-.toolbarButton.fullscreen::before {
- display: inline-block;
- content: url(../extlib/pdf.js/web/images/toolbarButton-fullscreen.png);
-}
-
-.toolbarButton.print::before {
- display: inline-block;
- content: url(../extlib/pdf.js/web/images/toolbarButton-print.png);
-}
-
-.toolbarButton.openFile::before {
- display: inline-block;
- content: url(../extlib/pdf.js/web/images/toolbarButton-openFile.png);
-}
-
-.toolbarButton.download::before {
- display: inline-block;
- content: url(../extlib/pdf.js/web/images/toolbarButton-download.png);
-}
-
-.toolbarButton.bookmark {
- -webkit-box-sizing: border-box;
- -moz-box-sizing: border-box;
- box-sizing: border-box;
- margin-top: 3px;
- padding-top: 4px;
-}
-
-#viewBookmark[href='#'] {
- opacity: .5;
- pointer-events: none;
-}
-
-.toolbarButton.bookmark::before {
- content: url(../extlib/pdf.js/web/images/toolbarButton-bookmark.png);
-}
-
-#viewThumbnail.toolbarButton::before {
- display: inline-block;
- content: url(../extlib/pdf.js/web/images/toolbarButton-viewThumbnail.png);
-}
-
-#viewOutline.toolbarButton::before {
- display: inline-block;
- content: url(../extlib/pdf.js/web/images/toolbarButton-viewOutline.png);
-}
-
-#viewFind.toolbarButton::before {
- display: inline-block;
- content: url(../extlib/pdf.js/web/images/toolbarButton-search.png);
-}
-
-
-.toolbarField {
- padding: 3px 6px;
- margin: 4px 0 4px 0;
- border: 1px solid transparent;
- border-radius: 2px;
- background-color: hsla(0,0%,100%,.09);
- background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-clip: padding-box;
- border: 1px solid hsla(0,0%,0%,.35);
- border-color: hsla(0,0%,0%,.32) hsla(0,0%,0%,.38) hsla(0,0%,0%,.42);
- box-shadow: 0 1px 0 hsla(0,0%,0%,.05) inset,
- 0 1px 0 hsla(0,0%,100%,.05);
- color: hsl(0,0%,95%);
- font-size: 12px;
- line-height: 14px;
- outline-style: none;
- -moz-transition-property: background-color, border-color, box-shadow;
- -moz-transition-duration: 150ms;
- -moz-transition-timing-function: ease;
-}
-
-.toolbarField[type=checkbox] {
- display: inline-block;
- margin: 8px 0px;
-}
-
-.toolbarField.pageNumber {
- min-width: 16px;
- text-align: right;
- width: 40px;
-}
-
-.toolbarField.pageNumber::-webkit-inner-spin-button,
-.toolbarField.pageNumber::-webkit-outer-spin-button {
- -webkit-appearance: none;
- margin: 0;
-}
-
-.toolbarField:hover {
- background-color: hsla(0,0%,100%,.11);
- border-color: hsla(0,0%,0%,.4) hsla(0,0%,0%,.43) hsla(0,0%,0%,.45);
-}
-
-.toolbarField:focus {
- background-color: hsla(0,0%,100%,.15);
- border-color: hsla(204,100%,65%,.8) hsla(204,100%,65%,.85) hsla(204,100%,65%,.9);
-}
-
-.toolbarLabel {
- min-width: 16px;
- padding: 3px 6px 3px 2px;
- margin: 4px 2px 4px 0;
- border: 1px solid transparent;
- border-radius: 2px;
- color: hsl(0,0%,85%);
- font-size: 12px;
- line-height: 14px;
- text-align: left;
- -webkit-user-select: none;
- -moz-user-select: none;
- cursor: default;
-}
-
-#thumbnailView {
- top: 0;
- bottom: 0;
- padding: 10px 10px 0;
- overflow: auto;
-}
-
-.thumbnail {
- float: left;
-}
-
-.thumbnail:not([data-loaded]) {
- border: 1px dashed rgba(255, 255, 255, 0.5);
- margin-bottom: 10px;
-}
-
-.thumbnailImage {
- -moz-transition-duration: 150ms;
- border: 1px solid transparent;
- box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.5), 0 2px 8px rgba(0, 0, 0, 0.3);
- opacity: 0.8;
- z-index: 99;
-}
-
-.thumbnailSelectionRing {
- border-radius: 2px;
- padding: 7px;
- -moz-transition-duration: 150ms;
-}
-
-a:focus > .thumbnail > .thumbnailSelectionRing > .thumbnailImage,
-.thumbnail:hover > .thumbnailSelectionRing > .thumbnailImage {
- opacity: .9;
-}
-
-a:focus > .thumbnail > .thumbnailSelectionRing,
-.thumbnail:hover > .thumbnailSelectionRing {
- background-color: hsla(0,0%,100%,.15);
- background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-clip: padding-box;
- box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
- 0 0 1px hsla(0,0%,100%,.2) inset,
- 0 0 1px hsla(0,0%,0%,.2);
- color: hsla(0,0%,100%,.9);
-}
-
-.thumbnail.selected > .thumbnailSelectionRing > .thumbnailImage {
- box-shadow: 0 0 0 1px hsla(0,0%,0%,.5);
- opacity: 1;
-}
-
-.thumbnail.selected > .thumbnailSelectionRing {
- background-color: hsla(0,0%,100%,.3);
- background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-clip: padding-box;
- box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
- 0 0 1px hsla(0,0%,100%,.1) inset,
- 0 0 1px hsla(0,0%,0%,.2);
- color: hsla(0,0%,100%,1);
-}
-
-#outlineView {
- width: 192px;
- top: 0;
- bottom: 0;
- padding: 4px 4px 0;
- overflow: auto;
- -webkit-user-select: none;
- -moz-user-select: none;
-}
-
-html[dir='ltr'] .outlineItem > .outlineItems {
- margin-left: 20px;
-}
-
-html[dir='rtl'] .outlineItem > .outlineItems {
- margin-right: 20px;
-}
-
-.outlineItem > a {
- text-decoration: none;
- display: inline-block;
- min-width: 95%;
- height: auto;
- margin-bottom: 1px;
- border-radius: 2px;
- color: hsla(0,0%,100%,.8);
- font-size: 13px;
- line-height: 15px;
- -moz-user-select: none;
- white-space: normal;
-}
-
-html[dir='ltr'] .outlineItem > a {
- padding: 2px 0 5px 10px;
-}
-
-html[dir='rtl'] .outlineItem > a {
- padding: 2px 10px 5px 0;
-}
-
-.outlineItem > a:hover {
- background-color: hsla(0,0%,100%,.02);
- background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-clip: padding-box;
- box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
- 0 0 1px hsla(0,0%,100%,.2) inset,
- 0 0 1px hsla(0,0%,0%,.2);
- color: hsla(0,0%,100%,.9);
-}
-
-.outlineItem.selected {
- background-color: hsla(0,0%,100%,.08);
- background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-clip: padding-box;
- box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
- 0 0 1px hsla(0,0%,100%,.1) inset,
- 0 0 1px hsla(0,0%,0%,.2);
- color: hsla(0,0%,100%,1);
-}
-
-.noOutline,
-.noResults {
- font-size: 12px;
- color: hsla(0,0%,100%,.8);
- font-style: italic;
- cursor: default;
-}
-
-#findScrollView {
- position: absolute;
- top: 10px;
- bottom: 10px;
- left: 10px;
- width: 280px;
-}
-
-#sidebarControls {
- position:absolute;
- width: 180px;
- height: 32px;
- left: 15px;
- bottom: 35px;
-}
-
-canvas {
- margin: auto;
- display: block;
-}
-
-.page {
- direction: ltr;
- width: 816px;
- height: 1056px;
- margin: 1px auto -8px auto;
- position: relative;
- overflow: visible;
- border: 9px solid transparent;
- background-clip: content-box;
- border-image: url(../extlib/pdf.js/web/images/shadow.png) 9 9 repeat;
- background-color: white;
-}
-
-.page > a {
- display: block;
- position: absolute;
-}
-
-.page > a:hover {
- opacity: 0.2;
- background: #ff0;
- box-shadow: 0px 2px 10px #ff0;
-}
-
-.loadingIcon {
- position: absolute;
- display: block;
- left: 0;
- top: 0;
- right: 0;
- bottom: 0;
- background: url('../extlib/pdf.js/web/images/loading-icon.gif') center no-repeat;
-}
-
-#loadingBox {
- position: absolute;
- top: 50%;
- margin-top: -25px;
- left: 0;
- right: 0;
- text-align: center;
- color: #ddd;
- font-size: 14px;
-}
-
-#loadingBar {
- display: inline-block;
- clear: both;
- margin: 0px;
- margin-top: 5px;
- line-height: 0;
- border-radius: 2px;
- width: 200px;
- height: 25px;
-
- background-color: hsla(0,0%,0%,.3);
- background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- border: 1px solid #000;
- box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset,
- 0 0 1px hsla(0,0%,0%,.2) inset,
- 0 0 1px 1px rgba(255, 255, 255, 0.1);
-}
-
-#loadingBar .progress {
- display: inline-block;
- float: left;
-
- background: #666;
- background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#b2b2b2), color-stop(100%,#898989));
- background: -webkit-linear-gradient(top, #b2b2b2 0%,#898989 100%);
- background: -moz-linear-gradient(top, #b2b2b2 0%,#898989 100%);
- background: -ms-linear-gradient(top, #b2b2b2 0%,#898989 100%);
- background: -o-linear-gradient(top, #b2b2b2 0%,#898989 100%);
- background: linear-gradient(top, #b2b2b2 0%,#898989 100%);
-
- border-top-left-radius: 2px;
- border-bottom-left-radius: 2px;
-
- width: 0%;
- height: 100%;
-}
-
-#loadingBar .progress.full {
- border-top-right-radius: 2px;
- border-bottom-right-radius: 2px;
-}
-
-#loadingBar .progress.indeterminate {
- width: 100%;
- height: 25px;
- background-image: -moz-linear-gradient( 30deg, #404040, #404040 15%, #898989, #404040 85%, #404040);
- background-image: -webkit-linear-gradient( 30deg, #404040, #404040 15%, #898989, #404040 85%, #404040);
- background-image: -ms-linear-gradient( 30deg, #404040, #404040 15%, #898989, #404040 85%, #404040);
- background-image: -o-linear-gradient( 30deg, #404040, #404040 15%, #898989, #404040 85%, #404040);
- background-size: 75px 25px;
- -moz-animation: progressIndeterminate 1s linear infinite;
- -webkit-animation: progressIndeterminate 1s linear infinite;
-}
-
-@-moz-keyframes progressIndeterminate {
- from { background-position: 0px 0px; }
- to { background-position: 75px 0px; }
-}
-
-@-webkit-keyframes progressIndeterminate {
- from { background-position: 0px 0px; }
- to { background-position: 75px 0px; }
-}
-
-.textLayer {
- position: absolute;
- left: 0;
- top: 0;
- right: 0;
- bottom: 0;
- color: #000;
- font-family: sans-serif;
- overflow: hidden;
-}
-
-.textLayer > div {
- color: transparent;
- position: absolute;
- line-height: 1;
- white-space: pre;
- cursor: text;
-}
-
-.textLayer .highlight {
- margin: -1px;
- padding: 1px;
-
- background-color: rgba(180, 0, 170, 0.2);
- border-radius: 4px;
-}
-
-.textLayer .highlight.begin {
- border-radius: 4px 0px 0px 4px;
-}
-
-.textLayer .highlight.end {
- border-radius: 0px 4px 4px 0px;
-}
-
-.textLayer .highlight.middle {
- border-radius: 0px;
-}
-
-.textLayer .highlight.selected {
- background-color: rgba(0, 100, 0, 0.2);
-}
-
-/* TODO: file FF bug to support ::-moz-selection:window-inactive
- so we can override the opaque grey background when the window is inactive;
- see https://bugzilla.mozilla.org/show_bug.cgi?id=706209 */
-::selection { background:rgba(0,0,255,0.3); }
-::-moz-selection { background:rgba(0,0,255,0.3); }
-
-.annotText > div {
- z-index: 200;
- position: absolute;
- padding: 0.6em;
- max-width: 20em;
- background-color: #FFFF99;
- box-shadow: 0px 2px 10px #333;
- border-radius: 7px;
-}
-
-.annotText > img {
- position: absolute;
- opacity: 0.6;
-}
-
-.annotText > img:hover {
- cursor: pointer;
- opacity: 1;
-}
-
-.annotText > div > h1 {
- font-size: 1.2em;
- border-bottom: 1px solid #000000;
- margin: 0px;
-}
-
-#errorWrapper {
- background: none repeat scroll 0 0 #FF5555;
- color: white;
- left: 0;
- position: absolute;
- right: 0;
- top: 32px;
- z-index: 1000;
- padding: 3px;
- font-size: 0.8em;
-}
-
-#errorMessageLeft {
- float: left;
-}
-
-#errorMessageRight {
- float: right;
-}
-
-#errorMoreInfo {
- background-color: #FFFFFF;
- color: black;
- padding: 3px;
- margin: 3px;
- width: 98%;
-}
-
-.clearBoth {
- clear: both;
-}
-
-.fileInput {
- background: white;
- color: black;
- margin-top: 5px;
-}
-
-#PDFBug {
- background: none repeat scroll 0 0 white;
- border: 1px solid #666666;
- position: fixed;
- top: 32px;
- right: 0;
- bottom: 0;
- font-size: 10px;
- padding: 0;
- width: 300px;
-}
-#PDFBug .controls {
- background:#EEEEEE;
- border-bottom: 1px solid #666666;
- padding: 3px;
-}
-#PDFBug .panels {
- bottom: 0;
- left: 0;
- overflow: auto;
- position: absolute;
- right: 0;
- top: 27px;
-}
-#PDFBug button.active {
- font-weight: bold;
-}
-.debuggerShowText {
- background: none repeat scroll 0 0 yellow;
- color: blue;
- opacity: 0.3;
-}
-.debuggerHideText:hover {
- background: none repeat scroll 0 0 yellow;
- opacity: 0.3;
-}
-#PDFBug .stats {
- font-family: courier;
- font-size: 10px;
- white-space: pre;
-}
-#PDFBug .stats .title {
- font-weight: bold;
-}
-#PDFBug table {
- font-size: 10px;
-}
-
-#viewer.textLayer-visible .textLayer > div,
-#viewer.textLayer-hover .textLayer > div:hover {
- background-color: white;
- color: black;
-}
-
-#viewer.textLayer-shadow .textLayer > div {
- background-color: rgba(255,255,255, .6);
- color: black;
-}
-
-@page {
- margin: 0;
-}
-
-#printContainer {
- display: none;
-}
-
-@media print {
- /* Rules for browsers that don't support mozPrintCallback. */
- #sidebarContainer, .toolbar, #loadingBox, #errorWrapper, .textLayer {
- display: none;
- }
-
- #mainContainer, #viewerContainer, .page, .page canvas {
- position: static;
- padding: 0;
- margin: 0;
- }
-
- .page {
- float: left;
- display: none;
- box-shadow: none;
- }
-
- .page[data-loaded] {
- display: block;
- }
-
- /* Rules for browsers that support mozPrintCallback */
- body[data-mozPrintCallback] #outerContainer {
- display: none;
- }
- body[data-mozPrintCallback] #printContainer {
- display: block;
- }
- #printContainer canvas {
- position: relative;
- top: 0;
- left: 0;
- }
-}
-
-@media all and (max-width: 950px) {
- html[dir='ltr'] #outerContainer.sidebarMoving .outerCenter,
- html[dir='ltr'] #outerContainer.sidebarOpen .outerCenter {
- float: left;
- left: 180px;
- }
- html[dir='rtl'] #outerContainer.sidebarMoving .outerCenter,
- html[dir='rtl'] #outerContainer.sidebarOpen .outerCenter {
- float: right;
- right: 180px;
- }
-}
-
-@media all and (max-width: 770px) {
- #sidebarContainer {
- top: 33px;
- z-index: 100;
- }
- #sidebarContent {
- top: 32px;
- background-color: hsla(0,0%,0%,.7);
- }
-
- html[dir='ltr'] #outerContainer.sidebarOpen > #mainContainer {
- left: 0px;
- }
- html[dir='rtl'] #outerContainer.sidebarOpen > #mainContainer {
- right: 0px;
- }
-
- html[dir='ltr'] .outerCenter {
- float: left;
- left: 180px;
- }
- html[dir='rtl'] .outerCenter {
- float: right;
- right: 180px;
- }
-}
-
-@media all and (max-width: 600px) {
- .hiddenSmallView {
- display: none;
- }
- html[dir='ltr'] .outerCenter {
- left: 156px;
- }
- html[dir='rtr'] .outerCenter {
- right: 156px;
- }
- .toolbarButtonSpacer {
- width: 0;
- }
-}
-
-@media all and (max-width: 500px) {
- #scaleSelectContainer, #pageNumberLabel {
- display: none;
- }
-}
-
diff --git a/mediagoblin/static/js/notifications.js b/mediagoblin/static/js/notifications.js
new file mode 100644
index 00000000..0153463a
--- /dev/null
+++ b/mediagoblin/static/js/notifications.js
@@ -0,0 +1,36 @@
+'use strict';
+/**
+ * GNU MediaGoblin -- federated, autonomous media hosting
+ * Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+var notifications = {};
+
+(function (n) {
+ n._base = '/';
+ n._endpoint = 'notifications/json';
+
+ n.init = function () {
+ $('.notification-gem').on('click', function () {
+ $('.header_dropdown_down:visible').click();
+ });
+ }
+
+})(notifications)
+
+$(document).ready(function () {
+ notifications.init();
+});
diff --git a/mediagoblin/static/js/pdf_viewer.js b/mediagoblin/static/js/pdf_viewer.js
deleted file mode 100644
index 79c1e708..00000000
--- a/mediagoblin/static/js/pdf_viewer.js
+++ /dev/null
@@ -1,3615 +0,0 @@
-/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
-/* Copyright 2012 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/* globals PDFJS, PDFBug, FirefoxCom, Stats */
-
-'use strict';
-
-var DEFAULT_SCALE = 'auto';
-var DEFAULT_SCALE_DELTA = 1.1;
-var UNKNOWN_SCALE = 0;
-var CACHE_SIZE = 20;
-var CSS_UNITS = 96.0 / 72.0;
-var SCROLLBAR_PADDING = 40;
-var VERTICAL_PADDING = 5;
-var MIN_SCALE = 0.25;
-var MAX_SCALE = 4.0;
-var IMAGE_DIR = './images/';
-var SETTINGS_MEMORY = 20;
-var ANNOT_MIN_SIZE = 10;
-var RenderingStates = {
- INITIAL: 0,
- RUNNING: 1,
- PAUSED: 2,
- FINISHED: 3
-};
-var FindStates = {
- FIND_FOUND: 0,
- FIND_NOTFOUND: 1,
- FIND_WRAPPED: 2,
- FIND_PENDING: 3
-};
-
-//#if (FIREFOX || MOZCENTRAL || B2G || GENERIC || CHROME)
-//PDFJS.workerSrc = '../build/pdf.js';
-//#endif
-
-var mozL10n = document.mozL10n || document.webL10n;
-
-function getFileName(url) {
- var anchor = url.indexOf('#');
- var query = url.indexOf('?');
- var end = Math.min(
- anchor > 0 ? anchor : url.length,
- query > 0 ? query : url.length);
- return url.substring(url.lastIndexOf('/', end) + 1, end);
-}
-
-function scrollIntoView(element, spot) {
- // Assuming offsetParent is available (it's not available when viewer is in
- // hidden iframe or object). We have to scroll: if the offsetParent is not set
- // producing the error. See also animationStartedClosure.
- var parent = element.offsetParent;
- var offsetY = element.offsetTop + element.clientTop;
- if (!parent) {
- console.error('offsetParent is not set -- cannot scroll');
- return;
- }
- while (parent.clientHeight == parent.scrollHeight) {
- offsetY += parent.offsetTop;
- parent = parent.offsetParent;
- if (!parent)
- return; // no need to scroll
- }
- if (spot)
- offsetY += spot.top;
- parent.scrollTop = offsetY;
-}
-
-var Cache = function cacheCache(size) {
- var data = [];
- this.push = function cachePush(view) {
- var i = data.indexOf(view);
- if (i >= 0)
- data.splice(i);
- data.push(view);
- if (data.length > size)
- data.shift().destroy();
- };
-};
-
-var ProgressBar = (function ProgressBarClosure() {
-
- function clamp(v, min, max) {
- return Math.min(Math.max(v, min), max);
- }
-
- function ProgressBar(id, opts) {
-
- // Fetch the sub-elements for later
- this.div = document.querySelector(id + ' .progress');
-
- // Get options, with sensible defaults
- this.height = opts.height || 100;
- this.width = opts.width || 100;
- this.units = opts.units || '%';
-
- // Initialize heights
- this.div.style.height = this.height + this.units;
- }
-
- ProgressBar.prototype = {
-
- updateBar: function ProgressBar_updateBar() {
- if (this._indeterminate) {
- this.div.classList.add('indeterminate');
- return;
- }
-
- var progressSize = this.width * this._percent / 100;
-
- if (this._percent > 95)
- this.div.classList.add('full');
- else
- this.div.classList.remove('full');
- this.div.classList.remove('indeterminate');
-
- this.div.style.width = progressSize + this.units;
- },
-
- get percent() {
- return this._percent;
- },
-
- set percent(val) {
- this._indeterminate = isNaN(val);
- this._percent = clamp(val, 0, 100);
- this.updateBar();
- }
- };
-
- return ProgressBar;
-})();
-
-//#if FIREFOX || MOZCENTRAL
-//#include firefoxcom.js
-//#endif
-
-// Settings Manager - This is a utility for saving settings
-// First we see if localStorage is available
-// If not, we use FUEL in FF
-// Use asyncStorage for B2G
-var Settings = (function SettingsClosure() {
-//#if !(FIREFOX || MOZCENTRAL || B2G)
- var isLocalStorageEnabled = (function localStorageEnabledTest() {
- // Feature test as per http://diveintohtml5.info/storage.html
- // The additional localStorage call is to get around a FF quirk, see
- // bug #495747 in bugzilla
- try {
- return 'localStorage' in window && window['localStorage'] !== null &&
- localStorage;
- } catch (e) {
- return false;
- }
- })();
-//#endif
-
- function Settings(fingerprint) {
- this.fingerprint = fingerprint;
- this.initializedPromise = new PDFJS.Promise();
-
- var resolvePromise = (function settingsResolvePromise(db) {
- this.initialize(db || '{}');
- this.initializedPromise.resolve();
- }).bind(this);
-
-//#if B2G
-// asyncStorage.getItem('database', resolvePromise);
-//#endif
-
-//#if FIREFOX || MOZCENTRAL
-// resolvePromise(FirefoxCom.requestSync('getDatabase', null));
-//#endif
-
-//#if !(FIREFOX || MOZCENTRAL || B2G)
- if (isLocalStorageEnabled)
- resolvePromise(localStorage.getItem('database'));
-//#endif
- }
-
- Settings.prototype = {
- initialize: function settingsInitialize(database) {
- database = JSON.parse(database);
- if (!('files' in database))
- database.files = [];
- if (database.files.length >= SETTINGS_MEMORY)
- database.files.shift();
- var index;
- for (var i = 0, length = database.files.length; i < length; i++) {
- var branch = database.files[i];
- if (branch.fingerprint == this.fingerprint) {
- index = i;
- break;
- }
- }
- if (typeof index != 'number')
- index = database.files.push({fingerprint: this.fingerprint}) - 1;
- this.file = database.files[index];
- this.database = database;
- },
-
- set: function settingsSet(name, val) {
- if (!this.initializedPromise.isResolved)
- return;
-
- var file = this.file;
- file[name] = val;
- var database = JSON.stringify(this.database);
-
-//#if B2G
-// asyncStorage.setItem('database', database);
-//#endif
-
-//#if FIREFOX || MOZCENTRAL
-// FirefoxCom.requestSync('setDatabase', database);
-//#endif
-
-//#if !(FIREFOX || MOZCENTRAL || B2G)
- if (isLocalStorageEnabled)
- localStorage.setItem('database', database);
-//#endif
- },
-
- get: function settingsGet(name, defaultValue) {
- if (!this.initializedPromise.isResolved)
- return defaultValue;
-
- return this.file[name] || defaultValue;
- }
- };
-
- return Settings;
-})();
-
-var cache = new Cache(CACHE_SIZE);
-var currentPageNumber = 1;
-
-var PDFFindController = {
- startedTextExtraction: false,
-
- extractTextPromises: [],
-
- // If active, find results will be highlighted.
- active: false,
-
- // Stores the text for each page.
- pageContents: [],
-
- pageMatches: [],
-
- // Currently selected match.
- selected: {
- pageIdx: -1,
- matchIdx: -1
- },
-
- // Where find algorithm currently is in the document.
- offset: {
- pageIdx: null,
- matchIdx: null
- },
-
- resumePageIdx: null,
-
- resumeCallback: null,
-
- state: null,
-
- dirtyMatch: false,
-
- findTimeout: null,
-
- initialize: function() {
- var events = [
- 'find',
- 'findagain',
- 'findhighlightallchange',
- 'findcasesensitivitychange'
- ];
-
- this.handleEvent = this.handleEvent.bind(this);
-
- for (var i = 0; i < events.length; i++) {
- window.addEventListener(events[i], this.handleEvent);
- }
- },
-
- calcFindMatch: function(pageIndex) {
- var pageContent = this.pageContents[pageIndex];
- var query = this.state.query;
- var caseSensitive = this.state.caseSensitive;
- var queryLen = query.length;
-
- if (queryLen === 0) {
- // Do nothing the matches should be wiped out already.
- return;
- }
-
- if (!caseSensitive) {
- pageContent = pageContent.toLowerCase();
- query = query.toLowerCase();
- }
-
- var matches = [];
-
- var matchIdx = -queryLen;
- while (true) {
- matchIdx = pageContent.indexOf(query, matchIdx + queryLen);
- if (matchIdx === -1) {
- break;
- }
-
- matches.push(matchIdx);
- }
- this.pageMatches[pageIndex] = matches;
- this.updatePage(pageIndex);
- if (this.resumePageIdx === pageIndex) {
- var callback = this.resumeCallback;
- this.resumePageIdx = null;
- this.resumeCallback = null;
- callback();
- }
- },
-
- extractText: function() {
- if (this.startedTextExtraction) {
- return;
- }
- this.startedTextExtraction = true;
-
- this.pageContents = [];
- for (var i = 0, ii = PDFView.pdfDocument.numPages; i < ii; i++) {
- this.extractTextPromises.push(new PDFJS.Promise());
- }
-
- var self = this;
- function extractPageText(pageIndex) {
- PDFView.pages[pageIndex].getTextContent().then(
- function textContentResolved(data) {
- // Build the find string.
- var bidiTexts = data.bidiTexts;
- var str = '';
-
- for (var i = 0; i < bidiTexts.length; i++) {
- str += bidiTexts[i].str;
- }
-
- // Store the pageContent as a string.
- self.pageContents.push(str);
-
- self.extractTextPromises[pageIndex].resolve(pageIndex);
- if ((pageIndex + 1) < PDFView.pages.length)
- extractPageText(pageIndex + 1);
- }
- );
- }
- extractPageText(0);
- return this.extractTextPromise;
- },
-
- handleEvent: function(e) {
- if (this.state === null || e.type !== 'findagain') {
- this.dirtyMatch = true;
- }
- this.state = e.detail;
- this.updateUIState(FindStates.FIND_PENDING);
-
- this.extractText();
-
- clearTimeout(this.findTimeout);
- if (e.type === 'find') {
- // Only trigger the find action after 250ms of silence.
- this.findTimeout = setTimeout(this.nextMatch.bind(this), 250);
- } else {
- this.nextMatch();
- }
- },
-
- updatePage: function(idx) {
- var page = PDFView.pages[idx];
-
- if (this.selected.pageIdx === idx) {
- // If the page is selected, scroll the page into view, which triggers
- // rendering the page, which adds the textLayer. Once the textLayer is
- // build, it will scroll onto the selected match.
- page.scrollIntoView();
- }
-
- if (page.textLayer) {
- page.textLayer.updateMatches();
- }
- },
-
- nextMatch: function() {
- var pages = PDFView.pages;
- var previous = this.state.findPrevious;
- var numPages = PDFView.pages.length;
-
- this.active = true;
-
- if (this.dirtyMatch) {
- // Need to recalculate the matches, reset everything.
- this.dirtyMatch = false;
- this.selected.pageIdx = this.selected.matchIdx = -1;
- this.offset.pageIdx = previous ? numPages - 1 : 0;
- this.offset.matchIdx = null;
- this.hadMatch = false;
- this.resumeCallback = null;
- this.resumePageIdx = null;
- this.pageMatches = [];
- var self = this;
-
- for (var i = 0; i < numPages; i++) {
- // Wipe out any previous highlighted matches.
- this.updatePage(i);
-
- // As soon as the text is extracted start finding the matches.
- this.extractTextPromises[i].onData(function(pageIdx) {
- // Use a timeout since all the pages may already be extracted and we
- // want to start highlighting before finding all the matches.
- setTimeout(function() {
- self.calcFindMatch(pageIdx);
- });
- });
- }
- }
-
- // If there's no query there's no point in searching.
- if (this.state.query === '') {
- this.updateUIState(FindStates.FIND_FOUND);
- return;
- }
-
- // If we're waiting on a page, we return since we can't do anything else.
- if (this.resumeCallback) {
- return;
- }
-
- var offset = this.offset;
- // If there's already a matchIdx that means we are iterating through a
- // page's matches.
- if (offset.matchIdx !== null) {
- var numPageMatches = this.pageMatches[offset.pageIdx].length;
- if ((!previous && offset.matchIdx + 1 < numPageMatches) ||
- (previous && offset.matchIdx > 0)) {
- // The simple case, we just have advance the matchIdx to select the next
- // match on the page.
- this.hadMatch = true;
- offset.matchIdx = previous ? offset.matchIdx - 1 : offset.matchIdx + 1;
- this.updateMatch(true);
- return;
- }
- // We went beyond the current page's matches, so we advance to the next
- // page.
- this.advanceOffsetPage(previous);
- }
- // Start searching through the page.
- this.nextPageMatch();
- },
-
- nextPageMatch: function() {
- if (this.resumePageIdx !== null)
- console.error('There can only be one pending page.');
-
- var matchesReady = function(matches) {
- var offset = this.offset;
- var numMatches = matches.length;
- var previous = this.state.findPrevious;
- if (numMatches) {
- // There were matches for the page, so initialize the matchIdx.
- this.hadMatch = true;
- offset.matchIdx = previous ? numMatches - 1 : 0;
- this.updateMatch(true);
- } else {
- // No matches attempt to search the next page.
- this.advanceOffsetPage(previous);
- if (offset.wrapped) {
- offset.matchIdx = null;
- if (!this.hadMatch) {
- // No point in wrapping there were no matches.
- this.updateMatch(false);
- return;
- }
- }
- // Search the next page.
- this.nextPageMatch();
- }
- }.bind(this);
-
- var pageIdx = this.offset.pageIdx;
- var pageMatches = this.pageMatches;
- if (!pageMatches[pageIdx]) {
- // The matches aren't ready setup a callback so we can be notified,
- // when they are ready.
- this.resumeCallback = function() {
- matchesReady(pageMatches[pageIdx]);
- };
- this.resumePageIdx = pageIdx;
- return;
- }
- // The matches are finished already.
- matchesReady(pageMatches[pageIdx]);
- },
-
- advanceOffsetPage: function(previous) {
- var offset = this.offset;
- var numPages = this.extractTextPromises.length;
- offset.pageIdx = previous ? offset.pageIdx - 1 : offset.pageIdx + 1;
- offset.matchIdx = null;
- if (offset.pageIdx >= numPages || offset.pageIdx < 0) {
- offset.pageIdx = previous ? numPages - 1 : 0;
- offset.wrapped = true;
- return;
- }
- },
-
- updateMatch: function(found) {
- var state = FindStates.FIND_NOTFOUND;
- var wrapped = this.offset.wrapped;
- this.offset.wrapped = false;
- if (found) {
- var previousPage = this.selected.pageIdx;
- this.selected.pageIdx = this.offset.pageIdx;
- this.selected.matchIdx = this.offset.matchIdx;
- state = wrapped ? FindStates.FIND_WRAPPED : FindStates.FIND_FOUND;
- // Update the currently selected page to wipe out any selected matches.
- if (previousPage !== -1 && previousPage !== this.selected.pageIdx) {
- this.updatePage(previousPage);
- }
- }
- this.updateUIState(state, this.state.findPrevious);
- if (this.selected.pageIdx !== -1) {
- this.updatePage(this.selected.pageIdx, true);
- }
- },
-
- updateUIState: function(state, previous) {
- if (PDFView.supportsIntegratedFind) {
- FirefoxCom.request('updateFindControlState',
- {result: state, findPrevious: previous});
- return;
- }
- PDFFindBar.updateUIState(state, previous);
- }
-};
-
-var PDFFindBar = {
- // TODO: Enable the FindBar *AFTER* the pagesPromise in the load function
- // got resolved
-
- opened: false,
-
- initialize: function() {
- this.bar = document.getElementById('findbar');
- this.toggleButton = document.getElementById('viewFind');
- this.findField = document.getElementById('findInput');
- this.highlightAll = document.getElementById('findHighlightAll');
- this.caseSensitive = document.getElementById('findMatchCase');
- this.findMsg = document.getElementById('findMsg');
- this.findStatusIcon = document.getElementById('findStatusIcon');
-
- var self = this;
- this.toggleButton.addEventListener('click', function() {
- self.toggle();
- });
-
- this.findField.addEventListener('input', function() {
- self.dispatchEvent('');
- });
-
- this.bar.addEventListener('keydown', function(evt) {
- switch (evt.keyCode) {
- case 13: // Enter
- if (evt.target === self.findField) {
- self.dispatchEvent('again', evt.shiftKey);
- }
- break;
- case 27: // Escape
- self.close();
- break;
- }
- });
-
- document.getElementById('findPrevious').addEventListener('click',
- function() { self.dispatchEvent('again', true); }
- );
-
- document.getElementById('findNext').addEventListener('click', function() {
- self.dispatchEvent('again', false);
- });
-
- this.highlightAll.addEventListener('click', function() {
- self.dispatchEvent('highlightallchange');
- });
-
- this.caseSensitive.addEventListener('click', function() {
- self.dispatchEvent('casesensitivitychange');
- });
- },
-
- dispatchEvent: function(aType, aFindPrevious) {
- var event = document.createEvent('CustomEvent');
- event.initCustomEvent('find' + aType, true, true, {
- query: this.findField.value,
- caseSensitive: this.caseSensitive.checked,
- highlightAll: this.highlightAll.checked,
- findPrevious: aFindPrevious
- });
- return window.dispatchEvent(event);
- },
-
- updateUIState: function(state, previous) {
- var notFound = false;
- var findMsg = '';
- var status = '';
-
- switch (state) {
- case FindStates.FIND_FOUND:
- break;
-
- case FindStates.FIND_PENDING:
- status = 'pending';
- break;
-
- case FindStates.FIND_NOTFOUND:
- findMsg = mozL10n.get('find_not_found', null, 'Phrase not found');
- notFound = true;
- break;
-
- case FindStates.FIND_WRAPPED:
- if (previous) {
- findMsg = mozL10n.get('find_reached_top', null,
- 'Reached top of document, continued from bottom');
- } else {
- findMsg = mozL10n.get('find_reached_bottom', null,
- 'Reached end of document, continued from top');
- }
- break;
- }
-
- if (notFound) {
- this.findField.classList.add('notFound');
- } else {
- this.findField.classList.remove('notFound');
- }
-
- this.findField.setAttribute('data-status', status);
- this.findMsg.textContent = findMsg;
- },
-
- open: function() {
- if (this.opened) return;
-
- this.opened = true;
- this.toggleButton.classList.add('toggled');
- this.bar.classList.remove('hidden');
- this.findField.select();
- this.findField.focus();
- },
-
- close: function() {
- if (!this.opened) return;
-
- this.opened = false;
- this.toggleButton.classList.remove('toggled');
- this.bar.classList.add('hidden');
-
- PDFFindController.active = false;
- },
-
- toggle: function() {
- if (this.opened) {
- this.close();
- } else {
- this.open();
- }
- }
-};
-
-var PDFView = {
- pages: [],
- thumbnails: [],
- currentScale: UNKNOWN_SCALE,
- currentScaleValue: null,
- initialBookmark: document.location.hash.substring(1),
- startedTextExtraction: false,
- pageText: [],
- container: null,
- thumbnailContainer: null,
- initialized: false,
- fellback: false,
- pdfDocument: null,
- sidebarOpen: false,
- pageViewScroll: null,
- thumbnailViewScroll: null,
- isFullscreen: false,
- previousScale: null,
- pageRotation: 0,
- mouseScrollTimeStamp: 0,
- mouseScrollDelta: 0,
- lastScroll: 0,
- previousPageNumber: 1,
-
- // called once when the document is loaded
- initialize: function pdfViewInitialize() {
- var self = this;
- var container = this.container = document.getElementById('viewerContainer');
- this.pageViewScroll = {};
- this.watchScroll(container, this.pageViewScroll, updateViewarea);
-
- var thumbnailContainer = this.thumbnailContainer =
- document.getElementById('thumbnailView');
- this.thumbnailViewScroll = {};
- this.watchScroll(thumbnailContainer, this.thumbnailViewScroll,
- this.renderHighestPriority.bind(this));
-
- PDFFindBar.initialize();
- PDFFindController.initialize();
-
- this.initialized = true;
- container.addEventListener('scroll', function() {
- self.lastScroll = Date.now();
- }, false);
- },
-
- getPage: function pdfViewGetPage(n) {
- return this.pdfDocument.getPage(n);
- },
-
- // Helper function to keep track whether a div was scrolled up or down and
- // then call a callback.
- watchScroll: function pdfViewWatchScroll(viewAreaElement, state, callback) {
- state.down = true;
- state.lastY = viewAreaElement.scrollTop;
- viewAreaElement.addEventListener('scroll', function webViewerScroll(evt) {
- var currentY = viewAreaElement.scrollTop;
- var lastY = state.lastY;
- if (currentY > lastY)
- state.down = true;
- else if (currentY < lastY)
- state.down = false;
- // else do nothing and use previous value
- state.lastY = currentY;
- callback();
- }, true);
- },
-
- setScale: function pdfViewSetScale(val, resetAutoSettings, noScroll) {
- if (val == this.currentScale)
- return;
-
- var pages = this.pages;
- for (var i = 0; i < pages.length; i++)
- pages[i].update(val * CSS_UNITS);
-
- if (!noScroll && this.currentScale != val)
- this.pages[this.page - 1].scrollIntoView();
- this.currentScale = val;
-
- var event = document.createEvent('UIEvents');
- event.initUIEvent('scalechange', false, false, window, 0);
- event.scale = val;
- event.resetAutoSettings = resetAutoSettings;
- window.dispatchEvent(event);
- },
-
- parseScale: function pdfViewParseScale(value, resetAutoSettings, noScroll) {
- if ('custom' == value)
- return;
-
- var scale = parseFloat(value);
- this.currentScaleValue = value;
- if (scale) {
- this.setScale(scale, true, noScroll);
- return;
- }
-
- var container = this.container;
- var currentPage = this.pages[this.page - 1];
- if (!currentPage) {
- return;
- }
-
- var pageWidthScale = (container.clientWidth - SCROLLBAR_PADDING) /
- currentPage.width * currentPage.scale / CSS_UNITS;
- var pageHeightScale = (container.clientHeight - VERTICAL_PADDING) /
- currentPage.height * currentPage.scale / CSS_UNITS;
- switch (value) {
- case 'page-actual':
- scale = 1;
- break;
- case 'page-width':
- scale = pageWidthScale;
- break;
- case 'page-height':
- scale = pageHeightScale;
- break;
- case 'page-fit':
- scale = Math.min(pageWidthScale, pageHeightScale);
- break;
- case 'auto':
- scale = Math.min(1.0, pageWidthScale);
- break;
- }
- this.setScale(scale, resetAutoSettings, noScroll);
-
- selectScaleOption(value);
- },
-
- zoomIn: function pdfViewZoomIn() {
- var newScale = (this.currentScale * DEFAULT_SCALE_DELTA).toFixed(2);
- newScale = Math.ceil(newScale * 10) / 10;
- newScale = Math.min(MAX_SCALE, newScale);
- this.parseScale(newScale, true);
- },
-
- zoomOut: function pdfViewZoomOut() {
- var newScale = (this.currentScale / DEFAULT_SCALE_DELTA).toFixed(2);
- newScale = Math.floor(newScale * 10) / 10;
- newScale = Math.max(MIN_SCALE, newScale);
- this.parseScale(newScale, true);
- },
-
- set page(val) {
- var pages = this.pages;
- var input = document.getElementById('pageNumber');
- var event = document.createEvent('UIEvents');
- event.initUIEvent('pagechange', false, false, window, 0);
-
- if (!(0 < val && val <= pages.length)) {
- this.previousPageNumber = val;
- event.pageNumber = this.page;
- window.dispatchEvent(event);
- return;
- }
-
- pages[val - 1].updateStats();
- this.previousPageNumber = currentPageNumber;
- currentPageNumber = val;
- event.pageNumber = val;
- window.dispatchEvent(event);
-
- // checking if the this.page was called from the updateViewarea function:
- // avoiding the creation of two "set page" method (internal and public)
- if (updateViewarea.inProgress)
- return;
-
- // Avoid scrolling the first page during loading
- if (this.loading && val == 1)
- return;
-
- pages[val - 1].scrollIntoView();
- },
-
- get page() {
- return currentPageNumber;
- },
-
- get supportsPrinting() {
- var canvas = document.createElement('canvas');
- var value = 'mozPrintCallback' in canvas;
- // shadow
- Object.defineProperty(this, 'supportsPrinting', { value: value,
- enumerable: true,
- configurable: true,
- writable: false });
- return value;
- },
-
- get supportsFullscreen() {
- var doc = document.documentElement;
- var support = doc.requestFullscreen || doc.mozRequestFullScreen ||
- doc.webkitRequestFullScreen;
-
- // Disable fullscreen button if we're in an iframe
- if (!!window.frameElement)
- support = false;
-
- Object.defineProperty(this, 'supportsFullScreen', { value: support,
- enumerable: true,
- configurable: true,
- writable: false });
- return support;
- },
-
- get supportsIntegratedFind() {
- var support = false;
-//#if !(FIREFOX || MOZCENTRAL)
-//#else
-// support = FirefoxCom.requestSync('supportsIntegratedFind');
-//#endif
- Object.defineProperty(this, 'supportsIntegratedFind', { value: support,
- enumerable: true,
- configurable: true,
- writable: false });
- return support;
- },
-
- get supportsDocumentFonts() {
- var support = true;
-//#if !(FIREFOX || MOZCENTRAL)
-//#else
-// support = FirefoxCom.requestSync('supportsDocumentFonts');
-//#endif
- Object.defineProperty(this, 'supportsDocumentFonts', { value: support,
- enumerable: true,
- configurable: true,
- writable: false });
- return support;
- },
-
- get isHorizontalScrollbarEnabled() {
- var div = document.getElementById('viewerContainer');
- return div.scrollWidth > div.clientWidth;
- },
-
- initPassiveLoading: function pdfViewInitPassiveLoading() {
- if (!PDFView.loadingBar) {
- PDFView.loadingBar = new ProgressBar('#loadingBar', {});
- }
-
- window.addEventListener('message', function window_message(e) {
- var args = e.data;
-
- if (typeof args !== 'object' || !('pdfjsLoadAction' in args))
- return;
- switch (args.pdfjsLoadAction) {
- case 'progress':
- PDFView.progress(args.loaded / args.total);
- break;
- case 'complete':
- if (!args.data) {
- PDFView.error(mozL10n.get('loading_error', null,
- 'An error occurred while loading the PDF.'), e);
- break;
- }
- PDFView.open(args.data, 0);
- break;
- }
- });
- FirefoxCom.requestSync('initPassiveLoading', null);
- },
-
- setTitleUsingUrl: function pdfViewSetTitleUsingUrl(url) {
- this.url = url;
- try {
- this.setTitle(decodeURIComponent(getFileName(url)) || url);
- } catch (e) {
- // decodeURIComponent may throw URIError,
- // fall back to using the unprocessed url in that case
- this.setTitle(url);
- }
- },
-
- setTitle: function pdfViewSetTitle(title) {
- document.title = title;
-//#if B2G
-// document.getElementById('activityTitle').textContent = title;
-//#endif
- },
-
- open: function pdfViewOpen(url, scale, password) {
- var parameters = {password: password};
- if (typeof url === 'string') { // URL
- this.setTitleUsingUrl(url);
- parameters.url = url;
- } else if (url && 'byteLength' in url) { // ArrayBuffer
- parameters.data = url;
- }
-
- if (!PDFView.loadingBar) {
- PDFView.loadingBar = new ProgressBar('#loadingBar', {});
- }
-
- this.pdfDocument = null;
- var self = this;
- self.loading = true;
- PDFJS.getDocument(parameters).then(
- function getDocumentCallback(pdfDocument) {
- self.load(pdfDocument, scale);
- self.loading = false;
- },
- function getDocumentError(message, exception) {
- if (exception && exception.name === 'PasswordException') {
- if (exception.code === 'needpassword') {
- var promptString = mozL10n.get('request_password', null,
- 'PDF is protected by a password:');
- password = prompt(promptString);
- if (password && password.length > 0) {
- return PDFView.open(url, scale, password);
- }
- }
- }
-
- var loadingErrorMessage = mozL10n.get('loading_error', null,
- 'An error occurred while loading the PDF.');
-
- if (exception && exception.name === 'InvalidPDFException') {
- // change error message also for other builds
- var loadingErrorMessage = mozL10n.get('invalid_file_error', null,
- 'Invalid or corrupted PDF file.');
-//#if B2G
-// window.alert(loadingErrorMessage);
-// return window.close();
-//#endif
- }
-
- if (exception && exception.name === 'MissingPDFException') {
- // special message for missing PDF's
- var loadingErrorMessage = mozL10n.get('missing_file_error', null,
- 'Missing PDF file.');
-
-//#if B2G
-// window.alert(loadingErrorMessage);
-// return window.close();
-//#endif
- }
-
- var loadingIndicator = document.getElementById('loading');
- loadingIndicator.textContent = mozL10n.get('loading_error_indicator',
- null, 'Error');
- var moreInfo = {
- message: message
- };
- self.error(loadingErrorMessage, moreInfo);
- self.loading = false;
- },
- function getDocumentProgress(progressData) {
- self.progress(progressData.loaded / progressData.total);
- }
- );
- },
-
- download: function pdfViewDownload() {
- function noData() {
- FirefoxCom.request('download', { originalUrl: url });
- }
- var url = this.url.split('#')[0];
-//#if !(FIREFOX || MOZCENTRAL)
- url += '#pdfjs.action=download';
- window.open(url, '_parent');
-//#else
-// // Document isn't ready just try to download with the url.
-// if (!this.pdfDocument) {
-// noData();
-// return;
-// }
-// this.pdfDocument.getData().then(
-// function getDataSuccess(data) {
-// var blob = PDFJS.createBlob(data.buffer, 'application/pdf');
-// var blobUrl = window.URL.createObjectURL(blob);
-//
-// FirefoxCom.request('download', { blobUrl: blobUrl, originalUrl: url },
-// function response(err) {
-// if (err) {
-// // This error won't really be helpful because it's likely the
-// // fallback won't work either (or is already open).
-// PDFView.error('PDF failed to download.');
-// }
-// window.URL.revokeObjectURL(blobUrl);
-// }
-// );
-// },
-// noData // Error occurred try downloading with just the url.
-// );
-//#endif
- },
-
- fallback: function pdfViewFallback() {
-//#if !(FIREFOX || MOZCENTRAL)
-// return;
-//#else
-// // Only trigger the fallback once so we don't spam the user with messages
-// // for one PDF.
-// if (this.fellback)
-// return;
-// this.fellback = true;
-// var url = this.url.split('#')[0];
-// FirefoxCom.request('fallback', url, function response(download) {
-// if (!download)
-// return;
-// PDFView.download();
-// });
-//#endif
- },
-
- navigateTo: function pdfViewNavigateTo(dest) {
- if (typeof dest === 'string')
- dest = this.destinations[dest];
- if (!(dest instanceof Array))
- return; // invalid destination
- // dest array looks like that: <page-ref> </XYZ|FitXXX> <args..>
- var destRef = dest[0];
- var pageNumber = destRef instanceof Object ?
- this.pagesRefMap[destRef.num + ' ' + destRef.gen + ' R'] : (destRef + 1);
- if (pageNumber > this.pages.length)
- pageNumber = this.pages.length;
- if (pageNumber) {
- this.page = pageNumber;
- var currentPage = this.pages[pageNumber - 1];
- if (!this.isFullscreen) { // Avoid breaking fullscreen mode.
- currentPage.scrollIntoView(dest);
- }
- }
- },
-
- getDestinationHash: function pdfViewGetDestinationHash(dest) {
- if (typeof dest === 'string')
- return PDFView.getAnchorUrl('#' + escape(dest));
- if (dest instanceof Array) {
- var destRef = dest[0]; // see navigateTo method for dest format
- var pageNumber = destRef instanceof Object ?
- this.pagesRefMap[destRef.num + ' ' + destRef.gen + ' R'] :
- (destRef + 1);
- if (pageNumber) {
- var pdfOpenParams = PDFView.getAnchorUrl('#page=' + pageNumber);
- var destKind = dest[1];
- if (typeof destKind === 'object' && 'name' in destKind &&
- destKind.name == 'XYZ') {
- var scale = (dest[4] || this.currentScale);
- pdfOpenParams += '&zoom=' + (scale * 100);
- if (dest[2] || dest[3]) {
- pdfOpenParams += ',' + (dest[2] || 0) + ',' + (dest[3] || 0);
- }
- }
- return pdfOpenParams;
- }
- }
- return '';
- },
-
- /**
- * For the firefox extension we prefix the full url on anchor links so they
- * don't come up as resource:// urls and so open in new tab/window works.
- * @param {String} anchor The anchor hash include the #.
- */
- getAnchorUrl: function getAnchorUrl(anchor) {
-//#if !(FIREFOX || MOZCENTRAL)
- return anchor;
-//#else
-// return this.url.split('#')[0] + anchor;
-//#endif
- },
-
- /**
- * Returns scale factor for the canvas. It makes sense for the HiDPI displays.
- * @return {Object} The object with horizontal (sx) and vertical (sy)
- scales. The scaled property is set to false if scaling is
- not required, true otherwise.
- */
- getOutputScale: function pdfViewGetOutputDPI() {
- var pixelRatio = 'devicePixelRatio' in window ? window.devicePixelRatio : 1;
- return {
- sx: pixelRatio,
- sy: pixelRatio,
- scaled: pixelRatio != 1
- };
- },
-
- /**
- * Show the error box.
- * @param {String} message A message that is human readable.
- * @param {Object} moreInfo (optional) Further information about the error
- * that is more technical. Should have a 'message'
- * and optionally a 'stack' property.
- */
- error: function pdfViewError(message, moreInfo) {
- var moreInfoText = mozL10n.get('error_version_info',
- {version: PDFJS.version || '?', build: PDFJS.build || '?'},
- 'PDF.js v{{version}} (build: {{build}})') + '\n';
- if (moreInfo) {
- moreInfoText +=
- mozL10n.get('error_message', {message: moreInfo.message},
- 'Message: {{message}}');
- if (moreInfo.stack) {
- moreInfoText += '\n' +
- mozL10n.get('error_stack', {stack: moreInfo.stack},
- 'Stack: {{stack}}');
- } else {
- if (moreInfo.filename) {
- moreInfoText += '\n' +
- mozL10n.get('error_file', {file: moreInfo.filename},
- 'File: {{file}}');
- }
- if (moreInfo.lineNumber) {
- moreInfoText += '\n' +
- mozL10n.get('error_line', {line: moreInfo.lineNumber},
- 'Line: {{line}}');
- }
- }
- }
-
- var loadingBox = document.getElementById('loadingBox');
- loadingBox.setAttribute('hidden', 'true');
-
-//#if !(FIREFOX || MOZCENTRAL)
- var errorWrapper = document.getElementById('errorWrapper');
- errorWrapper.removeAttribute('hidden');
-
- var errorMessage = document.getElementById('errorMessage');
- errorMessage.textContent = message;
-
- var closeButton = document.getElementById('errorClose');
- closeButton.onclick = function() {
- errorWrapper.setAttribute('hidden', 'true');
- };
-
- var errorMoreInfo = document.getElementById('errorMoreInfo');
- var moreInfoButton = document.getElementById('errorShowMore');
- var lessInfoButton = document.getElementById('errorShowLess');
- moreInfoButton.onclick = function() {
- errorMoreInfo.removeAttribute('hidden');
- moreInfoButton.setAttribute('hidden', 'true');
- lessInfoButton.removeAttribute('hidden');
- };
- lessInfoButton.onclick = function() {
- errorMoreInfo.setAttribute('hidden', 'true');
- moreInfoButton.removeAttribute('hidden');
- lessInfoButton.setAttribute('hidden', 'true');
- };
- moreInfoButton.removeAttribute('hidden');
- lessInfoButton.setAttribute('hidden', 'true');
- errorMoreInfo.value = moreInfoText;
-
- errorMoreInfo.rows = moreInfoText.split('\n').length - 1;
-//#else
-// console.error(message + '\n' + moreInfoText);
-// this.fallback();
-//#endif
- },
-
- progress: function pdfViewProgress(level) {
- var percent = Math.round(level * 100);
- PDFView.loadingBar.percent = percent;
- },
-
- load: function pdfViewLoad(pdfDocument, scale) {
- function bindOnAfterDraw(pageView, thumbnailView) {
- // when page is painted, using the image as thumbnail base
- pageView.onAfterDraw = function pdfViewLoadOnAfterDraw() {
- thumbnailView.setImage(pageView.canvas);
- };
- }
-
- this.pdfDocument = pdfDocument;
-
- var errorWrapper = document.getElementById('errorWrapper');
- errorWrapper.setAttribute('hidden', 'true');
-
- var loadingBox = document.getElementById('loadingBox');
- loadingBox.setAttribute('hidden', 'true');
- var loadingIndicator = document.getElementById('loading');
- loadingIndicator.textContent = '';
-
- var thumbsView = document.getElementById('thumbnailView');
- thumbsView.parentNode.scrollTop = 0;
-
- while (thumbsView.hasChildNodes())
- thumbsView.removeChild(thumbsView.lastChild);
-
- if ('_loadingInterval' in thumbsView)
- clearInterval(thumbsView._loadingInterval);
-
- var container = document.getElementById('viewer');
- while (container.hasChildNodes())
- container.removeChild(container.lastChild);
-
- var pagesCount = pdfDocument.numPages;
- var id = pdfDocument.fingerprint;
- document.getElementById('numPages').textContent =
- mozL10n.get('page_of', {pageCount: pagesCount}, 'of {{pageCount}}');
- document.getElementById('pageNumber').max = pagesCount;
-
- PDFView.documentFingerprint = id;
- var store = PDFView.store = new Settings(id);
-
- this.pageRotation = 0;
-
- var pages = this.pages = [];
- this.pageText = [];
- this.startedTextExtraction = false;
- var pagesRefMap = this.pagesRefMap = {};
- var thumbnails = this.thumbnails = [];
-
- var pagesPromise = new PDFJS.Promise();
- var self = this;
-
- var firstPagePromise = pdfDocument.getPage(1);
-
- // Fetch a single page so we can get a viewport that will be the default
- // viewport for all pages
- firstPagePromise.then(function(pdfPage) {
- var viewport = pdfPage.getViewport(scale || 1.0);
- var pagePromises = [];
- for (var pageNum = 1; pageNum <= pagesCount; ++pageNum) {
- var viewportClone = viewport.clone();
- var pageView = new PageView(container, pageNum, scale,
- self.navigateTo.bind(self),
- viewportClone);
- var thumbnailView = new ThumbnailView(thumbsView, pageNum,
- viewportClone);
- bindOnAfterDraw(pageView, thumbnailView);
- pages.push(pageView);
- thumbnails.push(thumbnailView);
- }
-
- var event = document.createEvent('CustomEvent');
- event.initCustomEvent('documentload', true, true, {});
- window.dispatchEvent(event);
-
- for (var pageNum = 1; pageNum <= pagesCount; ++pageNum) {
- var pagePromise = pdfDocument.getPage(pageNum);
- pagePromise.then(function(pdfPage) {
- var pageNum = pdfPage.pageNumber;
- var pageView = pages[pageNum - 1];
- if (!pageView.pdfPage) {
- // The pdfPage might already be set if we've already entered
- // pageView.draw()
- pageView.setPdfPage(pdfPage);
- }
- var thumbnailView = thumbnails[pageNum - 1];
- if (!thumbnailView.pdfPage) {
- thumbnailView.setPdfPage(pdfPage);
- }
-
- var pageRef = pdfPage.ref;
- var refStr = pageRef.num + ' ' + pageRef.gen + ' R';
- pagesRefMap[refStr] = pdfPage.pageNumber;
- });
- pagePromises.push(pagePromise);
- }
-
- PDFJS.Promise.all(pagePromises).then(function(pages) {
- pagesPromise.resolve(pages);
- });
- });
-
- var storePromise = store.initializedPromise;
- PDFJS.Promise.all([firstPagePromise, storePromise]).then(function() {
- var storedHash = null;
- if (store.get('exists', false)) {
- var pageNum = store.get('page', '1');
- var zoom = store.get('zoom', PDFView.currentScale);
- var left = store.get('scrollLeft', '0');
- var top = store.get('scrollTop', '0');
-
- storedHash = 'page=' + pageNum + '&zoom=' + zoom + ',' +
- left + ',' + top;
- }
- self.setInitialView(storedHash, scale);
- });
-
- pagesPromise.then(function() {
- if (PDFView.supportsPrinting) {
- pdfDocument.getJavaScript().then(function(javaScript) {
- if (javaScript.length) {
- console.warn('Warning: JavaScript is not supported');
- PDFView.fallback();
- }
- // Hack to support auto printing.
- var regex = /\bprint\s*\(/g;
- for (var i = 0, ii = javaScript.length; i < ii; i++) {
- var js = javaScript[i];
- if (js && regex.test(js)) {
- setTimeout(function() {
- window.print();
- });
- return;
- }
- }
- });
- }
- });
-
- var destinationsPromise = pdfDocument.getDestinations();
- destinationsPromise.then(function(destinations) {
- self.destinations = destinations;
- });
-
- // outline depends on destinations and pagesRefMap
- var promises = [pagesPromise, destinationsPromise,
- PDFView.animationStartedPromise];
- PDFJS.Promise.all(promises).then(function() {
- pdfDocument.getOutline().then(function(outline) {
- self.outline = new DocumentOutlineView(outline);
- });
-
- // Make all navigation keys work on document load,
- // unless the viewer is embedded in another page.
- if (window.parent.location === window.location) {
- PDFView.container.focus();
- }
- });
-
- pdfDocument.getMetadata().then(function(data) {
- var info = data.info, metadata = data.metadata;
- self.documentInfo = info;
- self.metadata = metadata;
-
- // Provides some basic debug information
- console.log('PDF ' + pdfDocument.fingerprint + ' [' +
- info.PDFFormatVersion + ' ' + (info.Producer || '-') +
- ' / ' + (info.Creator || '-') + ']' +
- (PDFJS.version ? ' (PDF.js: ' + PDFJS.version + ')' : ''));
-
- var pdfTitle;
- if (metadata) {
- if (metadata.has('dc:title'))
- pdfTitle = metadata.get('dc:title');
- }
-
- if (!pdfTitle && info && info['Title'])
- pdfTitle = info['Title'];
-
- if (pdfTitle)
- self.setTitle(pdfTitle + ' - ' + document.title);
-
- if (info.IsAcroFormPresent) {
- console.warn('Warning: AcroForm/XFA is not supported');
- PDFView.fallback();
- }
- });
- },
-
- setInitialView: function pdfViewSetInitialView(storedHash, scale) {
- // Reset the current scale, as otherwise the page's scale might not get
- // updated if the zoom level stayed the same.
- this.currentScale = 0;
- this.currentScaleValue = null;
- if (this.initialBookmark) {
- this.setHash(this.initialBookmark);
- this.initialBookmark = null;
- }
- else if (storedHash)
- this.setHash(storedHash);
- else if (scale) {
- this.parseScale(scale, true);
- this.page = 1;
- }
-
- if (PDFView.currentScale === UNKNOWN_SCALE) {
- // Scale was not initialized: invalid bookmark or scale was not specified.
- // Setting the default one.
- this.parseScale(DEFAULT_SCALE, true);
- }
- },
-
- renderHighestPriority: function pdfViewRenderHighestPriority() {
- // Pages have a higher priority than thumbnails, so check them first.
- var visiblePages = this.getVisiblePages();
- var pageView = this.getHighestPriority(visiblePages, this.pages,
- this.pageViewScroll.down);
- if (pageView) {
- this.renderView(pageView, 'page');
- return;
- }
- // No pages needed rendering so check thumbnails.
- if (this.sidebarOpen) {
- var visibleThumbs = this.getVisibleThumbs();
- var thumbView = this.getHighestPriority(visibleThumbs,
- this.thumbnails,
- this.thumbnailViewScroll.down);
- if (thumbView)
- this.renderView(thumbView, 'thumbnail');
- }
- },
-
- getHighestPriority: function pdfViewGetHighestPriority(visible, views,
- scrolledDown) {
- // The state has changed figure out which page has the highest priority to
- // render next (if any).
- // Priority:
- // 1 visible pages
- // 2 if last scrolled down page after the visible pages
- // 2 if last scrolled up page before the visible pages
- var visibleViews = visible.views;
-
- var numVisible = visibleViews.length;
- if (numVisible === 0) {
- return false;
- }
- for (var i = 0; i < numVisible; ++i) {
- var view = visibleViews[i].view;
- if (!this.isViewFinished(view))
- return view;
- }
-
- // All the visible views have rendered, try to render next/previous pages.
- if (scrolledDown) {
- var nextPageIndex = visible.last.id;
- // ID's start at 1 so no need to add 1.
- if (views[nextPageIndex] && !this.isViewFinished(views[nextPageIndex]))
- return views[nextPageIndex];
- } else {
- var previousPageIndex = visible.first.id - 2;
- if (views[previousPageIndex] &&
- !this.isViewFinished(views[previousPageIndex]))
- return views[previousPageIndex];
- }
- // Everything that needs to be rendered has been.
- return false;
- },
-
- isViewFinished: function pdfViewNeedsRendering(view) {
- return view.renderingState === RenderingStates.FINISHED;
- },
-
- // Render a page or thumbnail view. This calls the appropriate function based
- // on the views state. If the view is already rendered it will return false.
- renderView: function pdfViewRender(view, type) {
- var state = view.renderingState;
- switch (state) {
- case RenderingStates.FINISHED:
- return false;
- case RenderingStates.PAUSED:
- PDFView.highestPriorityPage = type + view.id;
- view.resume();
- break;
- case RenderingStates.RUNNING:
- PDFView.highestPriorityPage = type + view.id;
- break;
- case RenderingStates.INITIAL:
- PDFView.highestPriorityPage = type + view.id;
- view.draw(this.renderHighestPriority.bind(this));
- break;
- }
- return true;
- },
-
- setHash: function pdfViewSetHash(hash) {
- if (!hash)
- return;
-
- if (hash.indexOf('=') >= 0) {
- var params = PDFView.parseQueryString(hash);
- // borrowing syntax from "Parameters for Opening PDF Files"
- if ('nameddest' in params) {
- PDFView.navigateTo(params.nameddest);
- return;
- }
- if ('page' in params) {
- var pageNumber = (params.page | 0) || 1;
- if ('zoom' in params) {
- var zoomArgs = params.zoom.split(','); // scale,left,top
- // building destination array
-
- // If the zoom value, it has to get divided by 100. If it is a string,
- // it should stay as it is.
- var zoomArg = zoomArgs[0];
- var zoomArgNumber = parseFloat(zoomArg);
- if (zoomArgNumber)
- zoomArg = zoomArgNumber / 100;
-
- var dest = [null, {name: 'XYZ'},
- zoomArgs.length > 1 ? (zoomArgs[1] | 0) : null,
- zoomArgs.length > 2 ? (zoomArgs[2] | 0) : null,
- zoomArg];
- var currentPage = this.pages[pageNumber - 1];
- currentPage.scrollIntoView(dest);
- } else {
- this.page = pageNumber; // simple page
- }
- }
- if ('pagemode' in params) {
- var toggle = document.getElementById('sidebarToggle');
- if (params.pagemode === 'thumbs' || params.pagemode === 'bookmarks') {
- if (!this.sidebarOpen) {
- toggle.click();
- }
- this.switchSidebarView(params.pagemode === 'thumbs' ?
- 'thumbs' : 'outline');
- } else if (params.pagemode === 'none' && this.sidebarOpen) {
- toggle.click();
- }
- }
- } else if (/^\d+$/.test(hash)) // page number
- this.page = hash;
- else // named destination
- PDFView.navigateTo(unescape(hash));
- },
-
- switchSidebarView: function pdfViewSwitchSidebarView(view) {
- var thumbsView = document.getElementById('thumbnailView');
- var outlineView = document.getElementById('outlineView');
-
- var thumbsButton = document.getElementById('viewThumbnail');
- var outlineButton = document.getElementById('viewOutline');
-
- switch (view) {
- case 'thumbs':
- var wasOutlineViewVisible = thumbsView.classList.contains('hidden');
-
- thumbsButton.classList.add('toggled');
- outlineButton.classList.remove('toggled');
- thumbsView.classList.remove('hidden');
- outlineView.classList.add('hidden');
-
- PDFView.renderHighestPriority();
-
- if (wasOutlineViewVisible) {
- // Ensure that the thumbnail of the current page is visible
- // when switching from the outline view.
- scrollIntoView(document.getElementById('thumbnailContainer' +
- this.page));
- }
- break;
-
- case 'outline':
- thumbsButton.classList.remove('toggled');
- outlineButton.classList.add('toggled');
- thumbsView.classList.add('hidden');
- outlineView.classList.remove('hidden');
-
- if (outlineButton.getAttribute('disabled'))
- return;
- break;
- }
- },
-
- getVisiblePages: function pdfViewGetVisiblePages() {
- if (!this.isFullscreen) {
- return this.getVisibleElements(this.container, this.pages, true);
- } else {
- // The algorithm in getVisibleElements is broken in fullscreen mode.
- var visible = [], page = this.page;
- var currentPage = this.pages[page - 1];
- visible.push({ id: currentPage.id, view: currentPage });
-
- return { first: currentPage, last: currentPage, views: visible};
- }
- },
-
- getVisibleThumbs: function pdfViewGetVisibleThumbs() {
- return this.getVisibleElements(this.thumbnailContainer, this.thumbnails);
- },
-
- // Generic helper to find out what elements are visible within a scroll pane.
- getVisibleElements: function pdfViewGetVisibleElements(
- scrollEl, views, sortByVisibility) {
- var top = scrollEl.scrollTop, bottom = top + scrollEl.clientHeight;
- var left = scrollEl.scrollLeft, right = left + scrollEl.clientWidth;
-
- var visible = [], view;
- var currentHeight, viewHeight, hiddenHeight, percentHeight;
- var currentWidth, viewWidth;
- for (var i = 0, ii = views.length; i < ii; ++i) {
- view = views[i];
- currentHeight = view.el.offsetTop + view.el.clientTop;
- viewHeight = view.el.clientHeight;
- if ((currentHeight + viewHeight) < top) {
- continue;
- }
- if (currentHeight > bottom) {
- break;
- }
- currentWidth = view.el.offsetLeft + view.el.clientLeft;
- viewWidth = view.el.clientWidth;
- if ((currentWidth + viewWidth) < left || currentWidth > right) {
- continue;
- }
- hiddenHeight = Math.max(0, top - currentHeight) +
- Math.max(0, currentHeight + viewHeight - bottom);
- percentHeight = ((viewHeight - hiddenHeight) * 100 / viewHeight) | 0;
-
- visible.push({ id: view.id, y: currentHeight,
- view: view, percent: percentHeight });
- }
-
- var first = visible[0];
- var last = visible[visible.length - 1];
-
- if (sortByVisibility) {
- visible.sort(function(a, b) {
- var pc = a.percent - b.percent;
- if (Math.abs(pc) > 0.001) {
- return -pc;
- }
- return a.id - b.id; // ensure stability
- });
- }
- return {first: first, last: last, views: visible};
- },
-
- // Helper function to parse query string (e.g. ?param1=value&parm2=...).
- parseQueryString: function pdfViewParseQueryString(query) {
- var parts = query.split('&');
- var params = {};
- for (var i = 0, ii = parts.length; i < parts.length; ++i) {
- var param = parts[i].split('=');
- var key = param[0];
- var value = param.length > 1 ? param[1] : null;
- params[unescape(key)] = unescape(value);
- }
- return params;
- },
-
- beforePrint: function pdfViewSetupBeforePrint() {
- if (!this.supportsPrinting) {
- var printMessage = mozL10n.get('printing_not_supported', null,
- 'Warning: Printing is not fully supported by this browser.');
- this.error(printMessage);
- return;
- }
-
- var alertNotReady = false;
- if (!this.pages.length) {
- alertNotReady = true;
- } else {
- for (var i = 0, ii = this.pages.length; i < ii; ++i) {
- if (!this.pages[i].pdfPage) {
- alertNotReady = true;
- break;
- }
- }
- }
- if (alertNotReady) {
- var notReadyMessage = mozL10n.get('printing_not_ready', null,
- 'Warning: The PDF is not fully loaded for printing.');
- window.alert(notReadyMessage);
- return;
- }
-
- var body = document.querySelector('body');
- body.setAttribute('data-mozPrintCallback', true);
- for (var i = 0, ii = this.pages.length; i < ii; ++i) {
- this.pages[i].beforePrint();
- }
- },
-
- afterPrint: function pdfViewSetupAfterPrint() {
- var div = document.getElementById('printContainer');
- while (div.hasChildNodes())
- div.removeChild(div.lastChild);
- },
-
- fullscreen: function pdfViewFullscreen() {
- var isFullscreen = document.fullscreenElement || document.mozFullScreen ||
- document.webkitIsFullScreen;
-
- if (isFullscreen) {
- return false;
- }
-
- var wrapper = document.getElementById('viewerContainer');
- if (document.documentElement.requestFullscreen) {
- wrapper.requestFullscreen();
- } else if (document.documentElement.mozRequestFullScreen) {
- wrapper.mozRequestFullScreen();
- } else if (document.documentElement.webkitRequestFullScreen) {
- wrapper.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
- } else {
- return false;
- }
-
- this.isFullscreen = true;
- var currentPage = this.pages[this.page - 1];
- this.previousScale = this.currentScaleValue;
- this.parseScale('page-fit', true);
-
- // Wait for fullscreen to take effect
- setTimeout(function() {
- currentPage.scrollIntoView();
- }, 0);
-
- this.showPresentationControls();
- return true;
- },
-
- exitFullscreen: function pdfViewExitFullscreen() {
- this.isFullscreen = false;
- this.parseScale(this.previousScale);
- this.page = this.page;
- this.clearMouseScrollState();
- this.hidePresentationControls();
-
- // Ensure that the thumbnail of the current page is visible
- // when exiting fullscreen mode.
- scrollIntoView(document.getElementById('thumbnailContainer' + this.page));
- },
-
- showPresentationControls: function pdfViewShowPresentationControls() {
- var DELAY_BEFORE_HIDING_CONTROLS = 3000;
- var wrapper = document.getElementById('viewerContainer');
- if (this.presentationControlsTimeout) {
- clearTimeout(this.presentationControlsTimeout);
- } else {
- wrapper.classList.add('presentationControls');
- }
- this.presentationControlsTimeout = setTimeout(function hideControls() {
- wrapper.classList.remove('presentationControls');
- delete PDFView.presentationControlsTimeout;
- }, DELAY_BEFORE_HIDING_CONTROLS);
- },
-
- hidePresentationControls: function pdfViewShowPresentationControls() {
- if (!this.presentationControlsTimeout) {
- return;
- }
- clearTimeout(this.presentationControlsTimeout);
- delete this.presentationControlsTimeout;
-
- var wrapper = document.getElementById('viewerContainer');
- wrapper.classList.remove('presentationControls');
- },
-
- rotatePages: function pdfViewPageRotation(delta) {
-
- this.pageRotation = (this.pageRotation + 360 + delta) % 360;
-
- for (var i = 0, l = this.pages.length; i < l; i++) {
- var page = this.pages[i];
- page.update(page.scale, this.pageRotation);
- }
-
- for (var i = 0, l = this.thumbnails.length; i < l; i++) {
- var thumb = this.thumbnails[i];
- thumb.update(this.pageRotation);
- }
-
- this.parseScale(this.currentScaleValue, true);
-
- this.renderHighestPriority();
-
- var currentPage = this.pages[this.page - 1];
- if (!currentPage) {
- return;
- }
-
- // Wait for fullscreen to take effect
- setTimeout(function() {
- currentPage.scrollIntoView();
- }, 0);
- },
-
- /**
- * This function flips the page in presentation mode if the user scrolls up
- * or down with large enough motion and prevents page flipping too often.
- *
- * @this {PDFView}
- * @param {number} mouseScrollDelta The delta value from the mouse event.
- */
- mouseScroll: function pdfViewMouseScroll(mouseScrollDelta) {
- var MOUSE_SCROLL_COOLDOWN_TIME = 50;
-
- var currentTime = (new Date()).getTime();
- var storedTime = this.mouseScrollTimeStamp;
-
- // In case one page has already been flipped there is a cooldown time
- // which has to expire before next page can be scrolled on to.
- if (currentTime > storedTime &&
- currentTime - storedTime < MOUSE_SCROLL_COOLDOWN_TIME)
- return;
-
- // In case the user decides to scroll to the opposite direction than before
- // clear the accumulated delta.
- if ((this.mouseScrollDelta > 0 && mouseScrollDelta < 0) ||
- (this.mouseScrollDelta < 0 && mouseScrollDelta > 0))
- this.clearMouseScrollState();
-
- this.mouseScrollDelta += mouseScrollDelta;
-
- var PAGE_FLIP_THRESHOLD = 120;
- if (Math.abs(this.mouseScrollDelta) >= PAGE_FLIP_THRESHOLD) {
-
- var PageFlipDirection = {
- UP: -1,
- DOWN: 1
- };
-
- // In fullscreen mode scroll one page at a time.
- var pageFlipDirection = (this.mouseScrollDelta > 0) ?
- PageFlipDirection.UP :
- PageFlipDirection.DOWN;
- this.clearMouseScrollState();
- var currentPage = this.page;
-
- // In case we are already on the first or the last page there is no need
- // to do anything.
- if ((currentPage == 1 && pageFlipDirection == PageFlipDirection.UP) ||
- (currentPage == this.pages.length &&
- pageFlipDirection == PageFlipDirection.DOWN))
- return;
-
- this.page += pageFlipDirection;
- this.mouseScrollTimeStamp = currentTime;
- }
- },
-
- /**
- * This function clears the member attributes used with mouse scrolling in
- * presentation mode.
- *
- * @this {PDFView}
- */
- clearMouseScrollState: function pdfViewClearMouseScrollState() {
- this.mouseScrollTimeStamp = 0;
- this.mouseScrollDelta = 0;
- }
-};
-
-var PageView = function pageView(container, id, scale,
- navigateTo, defaultViewport) {
- this.id = id;
-
- this.rotation = 0;
- this.scale = scale || 1.0;
- this.viewport = defaultViewport;
- this.pdfPageRotate = defaultViewport.rotate;
-
- this.renderingState = RenderingStates.INITIAL;
- this.resume = null;
-
- this.textContent = null;
- this.textLayer = null;
-
- var anchor = document.createElement('a');
- anchor.name = '' + this.id;
-
- var div = this.el = document.createElement('div');
- div.id = 'pageContainer' + this.id;
- div.className = 'page';
- div.style.width = Math.floor(this.viewport.width) + 'px';
- div.style.height = Math.floor(this.viewport.height) + 'px';
-
- container.appendChild(anchor);
- container.appendChild(div);
-
- this.setPdfPage = function pageViewSetPdfPage(pdfPage) {
- this.pdfPage = pdfPage;
- this.pdfPageRotate = pdfPage.rotate;
- this.viewport = pdfPage.getViewport(this.scale);
- this.stats = pdfPage.stats;
- this.update();
- };
-
- this.destroy = function pageViewDestroy() {
- this.update();
- if (this.pdfPage) {
- this.pdfPage.destroy();
- }
- };
-
- this.update = function pageViewUpdate(scale, rotation) {
- this.renderingState = RenderingStates.INITIAL;
- this.resume = null;
-
- if (typeof rotation !== 'undefined') {
- this.rotation = rotation;
- }
-
- this.scale = scale || this.scale;
-
- var totalRotation = (this.rotation + this.pdfPageRotate) % 360;
- this.viewport = this.viewport.clone({
- scale: this.scale,
- rotation: totalRotation
- });
-
- div.style.width = Math.floor(this.viewport.width) + 'px';
- div.style.height = Math.floor(this.viewport.height) + 'px';
-
- while (div.hasChildNodes())
- div.removeChild(div.lastChild);
- div.removeAttribute('data-loaded');
-
- delete this.canvas;
-
- this.loadingIconDiv = document.createElement('div');
- this.loadingIconDiv.className = 'loadingIcon';
- div.appendChild(this.loadingIconDiv);
- };
-
- Object.defineProperty(this, 'width', {
- get: function PageView_getWidth() {
- return this.viewport.width;
- },
- enumerable: true
- });
-
- Object.defineProperty(this, 'height', {
- get: function PageView_getHeight() {
- return this.viewport.height;
- },
- enumerable: true
- });
-
- function setupAnnotations(pdfPage, viewport) {
- function bindLink(link, dest) {
- link.href = PDFView.getDestinationHash(dest);
- link.onclick = function pageViewSetupLinksOnclick() {
- if (dest)
- PDFView.navigateTo(dest);
- return false;
- };
- }
- function createElementWithStyle(tagName, item, rect) {
- if (!rect) {
- rect = viewport.convertToViewportRectangle(item.rect);
- rect = PDFJS.Util.normalizeRect(rect);
- }
- var element = document.createElement(tagName);
- element.style.left = Math.floor(rect[0]) + 'px';
- element.style.top = Math.floor(rect[1]) + 'px';
- element.style.width = Math.ceil(rect[2] - rect[0]) + 'px';
- element.style.height = Math.ceil(rect[3] - rect[1]) + 'px';
- return element;
- }
- function createTextAnnotation(item) {
- var container = document.createElement('section');
- container.className = 'annotText';
-
- var rect = viewport.convertToViewportRectangle(item.rect);
- rect = PDFJS.Util.normalizeRect(rect);
- // sanity check because of OOo-generated PDFs
- if ((rect[3] - rect[1]) < ANNOT_MIN_SIZE) {
- rect[3] = rect[1] + ANNOT_MIN_SIZE;
- }
- if ((rect[2] - rect[0]) < ANNOT_MIN_SIZE) {
- rect[2] = rect[0] + (rect[3] - rect[1]); // make it square
- }
- var image = createElementWithStyle('img', item, rect);
- var iconName = item.name;
- image.src = IMAGE_DIR + 'annotation-' +
- iconName.toLowerCase() + '.svg';
- image.alt = mozL10n.get('text_annotation_type', {type: iconName},
- '[{{type}} Annotation]');
- var content = document.createElement('div');
- content.setAttribute('hidden', true);
- var title = document.createElement('h1');
- var text = document.createElement('p');
- content.style.left = Math.floor(rect[2]) + 'px';
- content.style.top = Math.floor(rect[1]) + 'px';
- title.textContent = item.title;
-
- if (!item.content && !item.title) {
- content.setAttribute('hidden', true);
- } else {
- var e = document.createElement('span');
- var lines = item.content.split(/(?:\r\n?|\n)/);
- for (var i = 0, ii = lines.length; i < ii; ++i) {
- var line = lines[i];
- e.appendChild(document.createTextNode(line));
- if (i < (ii - 1))
- e.appendChild(document.createElement('br'));
- }
- text.appendChild(e);
- image.addEventListener('mouseover', function annotationImageOver() {
- content.removeAttribute('hidden');
- }, false);
-
- image.addEventListener('mouseout', function annotationImageOut() {
- content.setAttribute('hidden', true);
- }, false);
- }
-
- content.appendChild(title);
- content.appendChild(text);
- container.appendChild(image);
- container.appendChild(content);
-
- return container;
- }
-
- pdfPage.getAnnotations().then(function(items) {
- for (var i = 0; i < items.length; i++) {
- var item = items[i];
- switch (item.type) {
- case 'Link':
- var link = createElementWithStyle('a', item);
- link.href = item.url || '';
- if (!item.url)
- bindLink(link, ('dest' in item) ? item.dest : null);
- div.appendChild(link);
- break;
- case 'Text':
- var textAnnotation = createTextAnnotation(item);
- if (textAnnotation)
- div.appendChild(textAnnotation);
- break;
- }
- }
- });
- }
-
- this.getPagePoint = function pageViewGetPagePoint(x, y) {
- return this.viewport.convertToPdfPoint(x, y);
- };
-
- this.scrollIntoView = function pageViewScrollIntoView(dest) {
- if (!dest) {
- scrollIntoView(div);
- return;
- }
-
- var x = 0, y = 0;
- var width = 0, height = 0, widthScale, heightScale;
- var scale = 0;
- switch (dest[1].name) {
- case 'XYZ':
- x = dest[2];
- y = dest[3];
- scale = dest[4];
- // If x and/or y coordinates are not supplied, default to
- // _top_ left of the page (not the obvious bottom left,
- // since aligning the bottom of the intended page with the
- // top of the window is rarely helpful).
- x = x !== null ? x : 0;
- y = y !== null ? y : this.height / this.scale;
- break;
- case 'Fit':
- case 'FitB':
- scale = 'page-fit';
- break;
- case 'FitH':
- case 'FitBH':
- y = dest[2];
- scale = 'page-width';
- break;
- case 'FitV':
- case 'FitBV':
- x = dest[2];
- scale = 'page-height';
- break;
- case 'FitR':
- x = dest[2];
- y = dest[3];
- width = dest[4] - x;
- height = dest[5] - y;
- widthScale = (this.container.clientWidth - SCROLLBAR_PADDING) /
- width / CSS_UNITS;
- heightScale = (this.container.clientHeight - SCROLLBAR_PADDING) /
- height / CSS_UNITS;
- scale = Math.min(widthScale, heightScale);
- break;
- default:
- return;
- }
-
- if (scale && scale !== PDFView.currentScale)
- PDFView.parseScale(scale, true, true);
- else if (PDFView.currentScale === UNKNOWN_SCALE)
- PDFView.parseScale(DEFAULT_SCALE, true, true);
-
- var boundingRect = [
- this.viewport.convertToViewportPoint(x, y),
- this.viewport.convertToViewportPoint(x + width, y + height)
- ];
- setTimeout(function pageViewScrollIntoViewRelayout() {
- // letting page to re-layout before scrolling
- var scale = PDFView.currentScale;
- var x = Math.min(boundingRect[0][0], boundingRect[1][0]);
- var y = Math.min(boundingRect[0][1], boundingRect[1][1]);
- var width = Math.abs(boundingRect[0][0] - boundingRect[1][0]);
- var height = Math.abs(boundingRect[0][1] - boundingRect[1][1]);
-
- scrollIntoView(div, {left: x, top: y, width: width, height: height});
- }, 0);
- };
-
- this.getTextContent = function pageviewGetTextContent() {
- if (!this.textContent) {
- this.textContent = this.pdfPage.getTextContent();
- }
- return this.textContent;
- };
-
- this.draw = function pageviewDraw(callback) {
- var pdfPage = this.pdfPage;
-
- if (!pdfPage) {
- var promise = PDFView.getPage(this.id);
- promise.then(function(pdfPage) {
- this.setPdfPage(pdfPage);
- this.draw(callback);
- }.bind(this));
- return;
- }
-
- if (this.renderingState !== RenderingStates.INITIAL) {
- console.error('Must be in new state before drawing');
- }
-
- this.renderingState = RenderingStates.RUNNING;
-
- var canvas = document.createElement('canvas');
- canvas.id = 'page' + this.id;
- div.appendChild(canvas);
- this.canvas = canvas;
-
- var scale = this.scale, viewport = this.viewport;
- var outputScale = PDFView.getOutputScale();
- canvas.width = Math.floor(viewport.width) * outputScale.sx;
- canvas.height = Math.floor(viewport.height) * outputScale.sy;
-
- var textLayerDiv = null;
- if (!PDFJS.disableTextLayer) {
- textLayerDiv = document.createElement('div');
- textLayerDiv.className = 'textLayer';
- textLayerDiv.style.width = canvas.width + 'px';
- textLayerDiv.style.height = canvas.height + 'px';
- div.appendChild(textLayerDiv);
- }
- var textLayer = this.textLayer =
- textLayerDiv ? new TextLayerBuilder(textLayerDiv, this.id - 1) : null;
-
- if (outputScale.scaled) {
- var cssScale = 'scale(' + (1 / outputScale.sx) + ', ' +
- (1 / outputScale.sy) + ')';
- CustomStyle.setProp('transform' , canvas, cssScale);
- CustomStyle.setProp('transformOrigin' , canvas, '0% 0%');
- if (textLayerDiv) {
- CustomStyle.setProp('transform' , textLayerDiv, cssScale);
- CustomStyle.setProp('transformOrigin' , textLayerDiv, '0% 0%');
- }
- }
-
- var ctx = canvas.getContext('2d');
- ctx.clearRect(0, 0, canvas.width, canvas.height);
- // TODO(mack): use data attributes to store these
- ctx._scaleX = outputScale.sx;
- ctx._scaleY = outputScale.sy;
- if (outputScale.scaled) {
- ctx.scale(outputScale.sx, outputScale.sy);
- }
-//#if (FIREFOX || MOZCENTRAL)
-// // Checking if document fonts are used only once
-// var checkIfDocumentFontsUsed = !PDFView.pdfDocument.embeddedFontsUsed;
-//#endif
-
- // Rendering area
-
- var self = this;
- var renderingWasReset = false;
- function pageViewDrawCallback(error) {
- if (renderingWasReset) {
- return;
- }
-
- self.renderingState = RenderingStates.FINISHED;
-
- if (self.loadingIconDiv) {
- div.removeChild(self.loadingIconDiv);
- delete self.loadingIconDiv;
- }
-
-//#if (FIREFOX || MOZCENTRAL)
-// if (checkIfDocumentFontsUsed && PDFView.pdfDocument.embeddedFontsUsed &&
-// !PDFView.supportsDocumentFonts) {
-// console.error(mozL10n.get('web_fonts_disabled', null,
-// 'Web fonts are disabled: unable to use embedded PDF fonts.'));
-// PDFView.fallback();
-// }
-//#endif
- if (error) {
- PDFView.error(mozL10n.get('rendering_error', null,
- 'An error occurred while rendering the page.'), error);
- }
-
- self.stats = pdfPage.stats;
- self.updateStats();
- if (self.onAfterDraw)
- self.onAfterDraw();
-
- cache.push(self);
-
- var event = document.createEvent('CustomEvent');
- event.initCustomEvent('pagerender', true, true, {
- pageNumber: pdfPage.pageNumber
- });
- div.dispatchEvent(event);
-
- callback();
- }
-
- var renderContext = {
- canvasContext: ctx,
- viewport: this.viewport,
- textLayer: textLayer,
- continueCallback: function pdfViewcContinueCallback(cont) {
- if (self.renderingState === RenderingStates.INITIAL) {
- // The page update() was called, we just need to abort any rendering.
- renderingWasReset = true;
- return;
- }
-
- if (PDFView.highestPriorityPage !== 'page' + self.id) {
- self.renderingState = RenderingStates.PAUSED;
- self.resume = function resumeCallback() {
- self.renderingState = RenderingStates.RUNNING;
- cont();
- };
- return;
- }
- cont();
- }
- };
- this.pdfPage.render(renderContext).then(
- function pdfPageRenderCallback() {
- pageViewDrawCallback(null);
- },
- function pdfPageRenderError(error) {
- pageViewDrawCallback(error);
- }
- );
-
- if (textLayer) {
- this.getTextContent().then(
- function textContentResolved(textContent) {
- textLayer.setTextContent(textContent);
- }
- );
- }
-
- setupAnnotations(this.pdfPage, this.viewport);
- div.setAttribute('data-loaded', true);
- };
-
- this.beforePrint = function pageViewBeforePrint() {
- var pdfPage = this.pdfPage;
-
- var viewport = pdfPage.getViewport(1);
- // Use the same hack we use for high dpi displays for printing to get better
- // output until bug 811002 is fixed in FF.
- var PRINT_OUTPUT_SCALE = 2;
- var canvas = this.canvas = document.createElement('canvas');
- canvas.width = Math.floor(viewport.width) * PRINT_OUTPUT_SCALE;
- canvas.height = Math.floor(viewport.height) * PRINT_OUTPUT_SCALE;
- canvas.style.width = (PRINT_OUTPUT_SCALE * viewport.width) + 'pt';
- canvas.style.height = (PRINT_OUTPUT_SCALE * viewport.height) + 'pt';
- var cssScale = 'scale(' + (1 / PRINT_OUTPUT_SCALE) + ', ' +
- (1 / PRINT_OUTPUT_SCALE) + ')';
- CustomStyle.setProp('transform' , canvas, cssScale);
- CustomStyle.setProp('transformOrigin' , canvas, '0% 0%');
-
- var printContainer = document.getElementById('printContainer');
- printContainer.appendChild(canvas);
-
- var self = this;
- canvas.mozPrintCallback = function(obj) {
- var ctx = obj.context;
-
- ctx.save();
- ctx.fillStyle = 'rgb(255, 255, 255)';
- ctx.fillRect(0, 0, canvas.width, canvas.height);
- ctx.restore();
- ctx.scale(PRINT_OUTPUT_SCALE, PRINT_OUTPUT_SCALE);
-
- var renderContext = {
- canvasContext: ctx,
- viewport: viewport
- };
-
- pdfPage.render(renderContext).then(function() {
- // Tell the printEngine that rendering this canvas/page has finished.
- obj.done();
- self.pdfPage.destroy();
- }, function(error) {
- console.error(error);
- // Tell the printEngine that rendering this canvas/page has failed.
- // This will make the print proces stop.
- if ('abort' in obj)
- obj.abort();
- else
- obj.done();
- self.pdfPage.destroy();
- });
- };
- };
-
- this.updateStats = function pageViewUpdateStats() {
- if (!this.stats) {
- return;
- }
-
- if (PDFJS.pdfBug && Stats.enabled) {
- var stats = this.stats;
- Stats.add(this.id, stats);
- }
- };
-};
-
-var ThumbnailView = function thumbnailView(container, id, defaultViewport) {
- var anchor = document.createElement('a');
- anchor.href = PDFView.getAnchorUrl('#page=' + id);
- anchor.title = mozL10n.get('thumb_page_title', {page: id}, 'Page {{page}}');
- anchor.onclick = function stopNavigation() {
- PDFView.page = id;
- return false;
- };
-
-
- this.pdfPage = undefined;
- this.viewport = defaultViewport;
- this.pdfPageRotate = defaultViewport.rotate;
-
- this.rotation = 0;
- this.pageWidth = this.viewport.width;
- this.pageHeight = this.viewport.height;
- this.pageRatio = this.pageWidth / this.pageHeight;
- this.id = id;
-
- this.canvasWidth = 98;
- this.canvasHeight = this.canvasWidth / this.pageWidth * this.pageHeight;
- this.scale = (this.canvasWidth / this.pageWidth);
-
- var div = this.el = document.createElement('div');
- div.id = 'thumbnailContainer' + id;
- div.className = 'thumbnail';
-
- if (id === 1) {
- // Highlight the thumbnail of the first page when no page number is
- // specified (or exists in cache) when the document is loaded.
- div.classList.add('selected');
- }
-
- var ring = document.createElement('div');
- ring.className = 'thumbnailSelectionRing';
- ring.style.width = this.canvasWidth + 'px';
- ring.style.height = this.canvasHeight + 'px';
-
- div.appendChild(ring);
- anchor.appendChild(div);
- container.appendChild(anchor);
-
- this.hasImage = false;
- this.renderingState = RenderingStates.INITIAL;
-
- this.setPdfPage = function thumbnailViewSetPdfPage(pdfPage) {
- this.pdfPage = pdfPage;
- this.pdfPageRotate = pdfPage.rotate;
- this.viewport = pdfPage.getViewport(1);
- this.update();
- };
-
- this.update = function thumbnailViewUpdate(rot) {
- if (!this.pdfPage) {
- return;
- }
-
- if (rot !== undefined) {
- this.rotation = rot;
- }
-
- var totalRotation = (this.rotation + this.pdfPage.rotate) % 360;
- this.viewport = this.viewport.clone({
- scale: 1,
- rotation: totalRotation
- });
- this.pageWidth = this.viewport.width;
- this.pageHeight = this.viewport.height;
- this.pageRatio = this.pageWidth / this.pageHeight;
-
- this.canvasHeight = this.canvasWidth / this.pageWidth * this.pageHeight;
- this.scale = (this.canvasWidth / this.pageWidth);
-
- div.removeAttribute('data-loaded');
- ring.textContent = '';
- ring.style.width = this.canvasWidth + 'px';
- ring.style.height = this.canvasHeight + 'px';
-
- this.hasImage = false;
- this.renderingState = RenderingStates.INITIAL;
- this.resume = null;
- };
-
- this.getPageDrawContext = function thumbnailViewGetPageDrawContext() {
- var canvas = document.createElement('canvas');
- canvas.id = 'thumbnail' + id;
-
- canvas.width = this.canvasWidth;
- canvas.height = this.canvasHeight;
- canvas.className = 'thumbnailImage';
- canvas.setAttribute('aria-label', mozL10n.get('thumb_page_canvas',
- {page: id}, 'Thumbnail of Page {{page}}'));
-
- div.setAttribute('data-loaded', true);
-
- ring.appendChild(canvas);
-
- var ctx = canvas.getContext('2d');
- ctx.save();
- ctx.fillStyle = 'rgb(255, 255, 255)';
- ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight);
- ctx.restore();
- return ctx;
- };
-
- this.drawingRequired = function thumbnailViewDrawingRequired() {
- return !this.hasImage;
- };
-
- this.draw = function thumbnailViewDraw(callback) {
- if (!this.pdfPage) {
- var promise = PDFView.getPage(this.id);
- promise.then(function(pdfPage) {
- this.setPdfPage(pdfPage);
- this.draw(callback);
- }.bind(this));
- return;
- }
-
- if (this.renderingState !== RenderingStates.INITIAL) {
- console.error('Must be in new state before drawing');
- }
-
- this.renderingState = RenderingStates.RUNNING;
- if (this.hasImage) {
- callback();
- return;
- }
-
- var self = this;
- var ctx = this.getPageDrawContext();
- var drawViewport = this.viewport.clone({ scale: this.scale });
- var renderContext = {
- canvasContext: ctx,
- viewport: drawViewport,
- continueCallback: function(cont) {
- if (PDFView.highestPriorityPage !== 'thumbnail' + self.id) {
- self.renderingState = RenderingStates.PAUSED;
- self.resume = function() {
- self.renderingState = RenderingStates.RUNNING;
- cont();
- };
- return;
- }
- cont();
- }
- };
- this.pdfPage.render(renderContext).then(
- function pdfPageRenderCallback() {
- self.renderingState = RenderingStates.FINISHED;
- callback();
- },
- function pdfPageRenderError(error) {
- self.renderingState = RenderingStates.FINISHED;
- callback();
- }
- );
- this.hasImage = true;
- };
-
- this.setImage = function thumbnailViewSetImage(img) {
- if (this.hasImage || !img)
- return;
- this.renderingState = RenderingStates.FINISHED;
- var ctx = this.getPageDrawContext();
- ctx.drawImage(img, 0, 0, img.width, img.height,
- 0, 0, ctx.canvas.width, ctx.canvas.height);
-
- this.hasImage = true;
- };
-};
-
-var DocumentOutlineView = function documentOutlineView(outline) {
- var outlineView = document.getElementById('outlineView');
- while (outlineView.firstChild)
- outlineView.removeChild(outlineView.firstChild);
-
- function bindItemLink(domObj, item) {
- domObj.href = PDFView.getDestinationHash(item.dest);
- domObj.onclick = function documentOutlineViewOnclick(e) {
- PDFView.navigateTo(item.dest);
- return false;
- };
- }
-
- if (!outline) {
- var noOutline = document.createElement('div');
- noOutline.classList.add('noOutline');
- noOutline.textContent = mozL10n.get('no_outline', null,
- 'No Outline Available');
- outlineView.appendChild(noOutline);
- return;
- }
-
- var queue = [{parent: outlineView, items: outline}];
- while (queue.length > 0) {
- var levelData = queue.shift();
- var i, n = levelData.items.length;
- for (i = 0; i < n; i++) {
- var item = levelData.items[i];
- var div = document.createElement('div');
- div.className = 'outlineItem';
- var a = document.createElement('a');
- bindItemLink(a, item);
- a.textContent = item.title;
- div.appendChild(a);
-
- if (item.items.length > 0) {
- var itemsDiv = document.createElement('div');
- itemsDiv.className = 'outlineItems';
- div.appendChild(itemsDiv);
- queue.push({parent: itemsDiv, items: item.items});
- }
-
- levelData.parent.appendChild(div);
- }
- }
-};
-
-// optimised CSS custom property getter/setter
-var CustomStyle = (function CustomStyleClosure() {
-
- // As noted on: http://www.zachstronaut.com/posts/2009/02/17/
- // animate-css-transforms-firefox-webkit.html
- // in some versions of IE9 it is critical that ms appear in this list
- // before Moz
- var prefixes = ['ms', 'Moz', 'Webkit', 'O'];
- var _cache = { };
-
- function CustomStyle() {
- }
-
- CustomStyle.getProp = function get(propName, element) {
- // check cache only when no element is given
- if (arguments.length == 1 && typeof _cache[propName] == 'string') {
- return _cache[propName];
- }
-
- element = element || document.documentElement;
- var style = element.style, prefixed, uPropName;
-
- // test standard property first
- if (typeof style[propName] == 'string') {
- return (_cache[propName] = propName);
- }
-
- // capitalize
- uPropName = propName.charAt(0).toUpperCase() + propName.slice(1);
-
- // test vendor specific properties
- for (var i = 0, l = prefixes.length; i < l; i++) {
- prefixed = prefixes[i] + uPropName;
- if (typeof style[prefixed] == 'string') {
- return (_cache[propName] = prefixed);
- }
- }
-
- //if all fails then set to undefined
- return (_cache[propName] = 'undefined');
- };
-
- CustomStyle.setProp = function set(propName, element, str) {
- var prop = this.getProp(propName);
- if (prop != 'undefined')
- element.style[prop] = str;
- };
-
- return CustomStyle;
-})();
-
-var TextLayerBuilder = function textLayerBuilder(textLayerDiv, pageIdx) {
- var textLayerFrag = document.createDocumentFragment();
-
- this.textLayerDiv = textLayerDiv;
- this.layoutDone = false;
- this.divContentDone = false;
- this.pageIdx = pageIdx;
- this.matches = [];
-
- this.beginLayout = function textLayerBuilderBeginLayout() {
- this.textDivs = [];
- this.textLayerQueue = [];
- this.renderingDone = false;
- };
-
- this.endLayout = function textLayerBuilderEndLayout() {
- this.layoutDone = true;
- this.insertDivContent();
- };
-
- this.renderLayer = function textLayerBuilderRenderLayer() {
- var self = this;
- var textDivs = this.textDivs;
- var bidiTexts = this.textContent.bidiTexts;
- var textLayerDiv = this.textLayerDiv;
- var canvas = document.createElement('canvas');
- var ctx = canvas.getContext('2d');
-
- // No point in rendering so many divs as it'd make the browser unusable
- // even after the divs are rendered
- var MAX_TEXT_DIVS_TO_RENDER = 100000;
- if (textDivs.length > MAX_TEXT_DIVS_TO_RENDER)
- return;
-
- for (var i = 0, ii = textDivs.length; i < ii; i++) {
- var textDiv = textDivs[i];
- if ('isWhitespace' in textDiv.dataset) {
- continue;
- }
- textLayerFrag.appendChild(textDiv);
-
- ctx.font = textDiv.style.fontSize + ' ' + textDiv.style.fontFamily;
- var width = ctx.measureText(textDiv.textContent).width;
-
- if (width > 0) {
- var textScale = textDiv.dataset.canvasWidth / width;
-
- var transform = 'scale(' + textScale + ', 1)';
- if (bidiTexts[i].dir === 'ttb') {
- transform = 'rotate(90deg) ' + transform;
- }
- CustomStyle.setProp('transform' , textDiv, transform);
- CustomStyle.setProp('transformOrigin' , textDiv, '0% 0%');
-
- textLayerDiv.appendChild(textDiv);
- }
- }
-
- this.renderingDone = true;
- this.updateMatches();
-
- textLayerDiv.appendChild(textLayerFrag);
- };
-
- this.setupRenderLayoutTimer = function textLayerSetupRenderLayoutTimer() {
- // Schedule renderLayout() if user has been scrolling, otherwise
- // run it right away
- var RENDER_DELAY = 200; // in ms
- var self = this;
- if (Date.now() - PDFView.lastScroll > RENDER_DELAY) {
- // Render right away
- this.renderLayer();
- } else {
- // Schedule
- if (this.renderTimer)
- clearTimeout(this.renderTimer);
- this.renderTimer = setTimeout(function() {
- self.setupRenderLayoutTimer();
- }, RENDER_DELAY);
- }
- };
-
- this.appendText = function textLayerBuilderAppendText(geom) {
- var textDiv = document.createElement('div');
-
- // vScale and hScale already contain the scaling to pixel units
- var fontHeight = geom.fontSize * Math.abs(geom.vScale);
- textDiv.dataset.canvasWidth = geom.canvasWidth * geom.hScale;
- textDiv.dataset.fontName = geom.fontName;
-
- textDiv.style.fontSize = fontHeight + 'px';
- textDiv.style.fontFamily = geom.fontFamily;
- textDiv.style.left = geom.x + 'px';
- textDiv.style.top = (geom.y - fontHeight) + 'px';
-
- // The content of the div is set in the `setTextContent` function.
-
- this.textDivs.push(textDiv);
- };
-
- this.insertDivContent = function textLayerUpdateTextContent() {
- // Only set the content of the divs once layout has finished, the content
- // for the divs is available and content is not yet set on the divs.
- if (!this.layoutDone || this.divContentDone || !this.textContent)
- return;
-
- this.divContentDone = true;
-
- var textDivs = this.textDivs;
- var bidiTexts = this.textContent.bidiTexts;
-
- for (var i = 0; i < bidiTexts.length; i++) {
- var bidiText = bidiTexts[i];
- var textDiv = textDivs[i];
- if (!/\S/.test(bidiText.str)) {
- textDiv.dataset.isWhitespace = true;
- continue;
- }
-
- textDiv.textContent = bidiText.str;
- // bidiText.dir may be 'ttb' for vertical texts.
- textDiv.dir = bidiText.dir === 'rtl' ? 'rtl' : 'ltr';
- }
-
- this.setupRenderLayoutTimer();
- };
-
- this.setTextContent = function textLayerBuilderSetTextContent(textContent) {
- this.textContent = textContent;
- this.insertDivContent();
- };
-
- this.convertMatches = function textLayerBuilderConvertMatches(matches) {
- var i = 0;
- var iIndex = 0;
- var bidiTexts = this.textContent.bidiTexts;
- var end = bidiTexts.length - 1;
- var queryLen = PDFFindController.state.query.length;
-
- var lastDivIdx = -1;
- var pos;
-
- var ret = [];
-
- // Loop over all the matches.
- for (var m = 0; m < matches.length; m++) {
- var matchIdx = matches[m];
- // # Calculate the begin position.
-
- // Loop over the divIdxs.
- while (i !== end && matchIdx >= (iIndex + bidiTexts[i].str.length)) {
- iIndex += bidiTexts[i].str.length;
- i++;
- }
-
- // TODO: Do proper handling here if something goes wrong.
- if (i == bidiTexts.length) {
- console.error('Could not find matching mapping');
- }
-
- var match = {
- begin: {
- divIdx: i,
- offset: matchIdx - iIndex
- }
- };
-
- // # Calculate the end position.
- matchIdx += queryLen;
-
- // Somewhat same array as above, but use a > instead of >= to get the end
- // position right.
- while (i !== end && matchIdx > (iIndex + bidiTexts[i].str.length)) {
- iIndex += bidiTexts[i].str.length;
- i++;
- }
-
- match.end = {
- divIdx: i,
- offset: matchIdx - iIndex
- };
- ret.push(match);
- }
-
- return ret;
- };
-
- this.renderMatches = function textLayerBuilder_renderMatches(matches) {
- // Early exit if there is nothing to render.
- if (matches.length === 0) {
- return;
- }
-
- var bidiTexts = this.textContent.bidiTexts;
- var textDivs = this.textDivs;
- var prevEnd = null;
- var isSelectedPage = this.pageIdx === PDFFindController.selected.pageIdx;
- var selectedMatchIdx = PDFFindController.selected.matchIdx;
- var highlightAll = PDFFindController.state.highlightAll;
-
- var infty = {
- divIdx: -1,
- offset: undefined
- };
-
- function beginText(begin, className) {
- var divIdx = begin.divIdx;
- var div = textDivs[divIdx];
- div.textContent = '';
-
- var content = bidiTexts[divIdx].str.substring(0, begin.offset);
- var node = document.createTextNode(content);
- if (className) {
- var isSelected = isSelectedPage &&
- divIdx === selectedMatchIdx;
- var span = document.createElement('span');
- span.className = className + (isSelected ? ' selected' : '');
- span.appendChild(node);
- div.appendChild(span);
- return;
- }
- div.appendChild(node);
- }
-
- function appendText(from, to, className) {
- var divIdx = from.divIdx;
- var div = textDivs[divIdx];
-
- var content = bidiTexts[divIdx].str.substring(from.offset, to.offset);
- var node = document.createTextNode(content);
- if (className) {
- var span = document.createElement('span');
- span.className = className;
- span.appendChild(node);
- div.appendChild(span);
- return;
- }
- div.appendChild(node);
- }
-
- function highlightDiv(divIdx, className) {
- textDivs[divIdx].className = className;
- }
-
- var i0 = selectedMatchIdx, i1 = i0 + 1, i;
-
- if (highlightAll) {
- i0 = 0;
- i1 = matches.length;
- } else if (!isSelectedPage) {
- // Not highlighting all and this isn't the selected page, so do nothing.
- return;
- }
-
- for (i = i0; i < i1; i++) {
- var match = matches[i];
- var begin = match.begin;
- var end = match.end;
-
- var isSelected = isSelectedPage && i === selectedMatchIdx;
- var highlightSuffix = (isSelected ? ' selected' : '');
- if (isSelected)
- scrollIntoView(textDivs[begin.divIdx], {top: -50});
-
- // Match inside new div.
- if (!prevEnd || begin.divIdx !== prevEnd.divIdx) {
- // If there was a previous div, then add the text at the end
- if (prevEnd !== null) {
- appendText(prevEnd, infty);
- }
- // clears the divs and set the content until the begin point.
- beginText(begin);
- } else {
- appendText(prevEnd, begin);
- }
-
- if (begin.divIdx === end.divIdx) {
- appendText(begin, end, 'highlight' + highlightSuffix);
- } else {
- appendText(begin, infty, 'highlight begin' + highlightSuffix);
- for (var n = begin.divIdx + 1; n < end.divIdx; n++) {
- highlightDiv(n, 'highlight middle' + highlightSuffix);
- }
- beginText(end, 'highlight end' + highlightSuffix);
- }
- prevEnd = end;
- }
-
- if (prevEnd) {
- appendText(prevEnd, infty);
- }
- };
-
- this.updateMatches = function textLayerUpdateMatches() {
- // Only show matches, once all rendering is done.
- if (!this.renderingDone)
- return;
-
- // Clear out all matches.
- var matches = this.matches;
- var textDivs = this.textDivs;
- var bidiTexts = this.textContent.bidiTexts;
- var clearedUntilDivIdx = -1;
-
- // Clear out all current matches.
- for (var i = 0; i < matches.length; i++) {
- var match = matches[i];
- var begin = Math.max(clearedUntilDivIdx, match.begin.divIdx);
- for (var n = begin; n <= match.end.divIdx; n++) {
- var div = textDivs[n];
- div.textContent = bidiTexts[n].str;
- div.className = '';
- }
- clearedUntilDivIdx = match.end.divIdx + 1;
- }
-
- if (!PDFFindController.active)
- return;
-
- // Convert the matches on the page controller into the match format used
- // for the textLayer.
- this.matches = matches =
- this.convertMatches(PDFFindController.pageMatches[this.pageIdx] || []);
-
- this.renderMatches(this.matches);
- };
-};
-
-document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) {
- PDFView.initialize();
- var params = PDFView.parseQueryString(document.location.search.substring(1));
-
-//#if !(FIREFOX || MOZCENTRAL)
- var file = params.file || DEFAULT_URL;
-//#else
-//var file = window.location.toString()
-//#endif
-
-//#if !(FIREFOX || MOZCENTRAL)
- if (!window.File || !window.FileReader || !window.FileList || !window.Blob) {
- document.getElementById('openFile').setAttribute('hidden', 'true');
- } else {
- document.getElementById('fileInput').value = null;
- }
-//#else
-//document.getElementById('openFile').setAttribute('hidden', 'true');
-//#endif
-
- // Special debugging flags in the hash section of the URL.
- var hash = document.location.hash.substring(1);
- var hashParams = PDFView.parseQueryString(hash);
-
- if ('disableWorker' in hashParams)
- PDFJS.disableWorker = (hashParams['disableWorker'] === 'true');
-
-//#if !(FIREFOX || MOZCENTRAL)
- var locale = navigator.language;
- if ('locale' in hashParams)
- locale = hashParams['locale'];
- mozL10n.setLanguage(locale);
-//#endif
-
- if ('textLayer' in hashParams) {
- switch (hashParams['textLayer']) {
- case 'off':
- PDFJS.disableTextLayer = true;
- break;
- case 'visible':
- case 'shadow':
- case 'hover':
- var viewer = document.getElementById('viewer');
- viewer.classList.add('textLayer-' + hashParams['textLayer']);
- break;
- }
- }
-
-//#if !(FIREFOX || MOZCENTRAL)
- if ('pdfBug' in hashParams) {
-//#else
-//if ('pdfBug' in hashParams && FirefoxCom.requestSync('pdfBugEnabled')) {
-//#endif
- PDFJS.pdfBug = true;
- var pdfBug = hashParams['pdfBug'];
- var enabled = pdfBug.split(',');
- PDFBug.enable(enabled);
- PDFBug.init();
- }
-
- if (!PDFView.supportsPrinting) {
- document.getElementById('print').classList.add('hidden');
- }
-
- if (!PDFView.supportsFullscreen) {
- document.getElementById('fullscreen').classList.add('hidden');
- }
-
- if (PDFView.supportsIntegratedFind) {
- document.querySelector('#viewFind').classList.add('hidden');
- }
-
- // Listen for warnings to trigger the fallback UI. Errors should be caught
- // and call PDFView.error() so we don't need to listen for those.
- PDFJS.LogManager.addLogger({
- warn: function() {
- PDFView.fallback();
- }
- });
-
- var mainContainer = document.getElementById('mainContainer');
- var outerContainer = document.getElementById('outerContainer');
- mainContainer.addEventListener('transitionend', function(e) {
- if (e.target == mainContainer) {
- var event = document.createEvent('UIEvents');
- event.initUIEvent('resize', false, false, window, 0);
- window.dispatchEvent(event);
- outerContainer.classList.remove('sidebarMoving');
- }
- }, true);
-
- document.getElementById('sidebarToggle').addEventListener('click',
- function() {
- this.classList.toggle('toggled');
- outerContainer.classList.add('sidebarMoving');
- outerContainer.classList.toggle('sidebarOpen');
- PDFView.sidebarOpen = outerContainer.classList.contains('sidebarOpen');
- PDFView.renderHighestPriority();
- });
-
- document.getElementById('viewThumbnail').addEventListener('click',
- function() {
- PDFView.switchSidebarView('thumbs');
- });
-
- document.getElementById('viewOutline').addEventListener('click',
- function() {
- PDFView.switchSidebarView('outline');
- });
-
- document.getElementById('previous').addEventListener('click',
- function() {
- PDFView.page--;
- });
-
- document.getElementById('next').addEventListener('click',
- function() {
- PDFView.page++;
- });
-
- document.querySelector('.zoomIn').addEventListener('click',
- function() {
- PDFView.zoomIn();
- });
-
- document.querySelector('.zoomOut').addEventListener('click',
- function() {
- PDFView.zoomOut();
- });
-
- document.getElementById('fullscreen').addEventListener('click',
- function() {
- PDFView.fullscreen();
- });
-
- document.getElementById('openFile').addEventListener('click',
- function() {
- document.getElementById('fileInput').click();
- });
-
- document.getElementById('print').addEventListener('click',
- function() {
- window.print();
- });
-
- document.getElementById('download').addEventListener('click',
- function() {
- PDFView.download();
- });
-
- document.getElementById('pageNumber').addEventListener('click',
- function() {
- this.select();
- });
-
- document.getElementById('pageNumber').addEventListener('change',
- function() {
- // Handle the user inputting a floating point number.
- PDFView.page = (this.value | 0);
-
- if (this.value !== (this.value | 0).toString()) {
- this.value = PDFView.page;
- }
- });
-
- document.getElementById('scaleSelect').addEventListener('change',
- function() {
- PDFView.parseScale(this.value);
- });
-
- document.getElementById('first_page').addEventListener('click',
- function() {
- PDFView.page = 1;
- });
-
- document.getElementById('last_page').addEventListener('click',
- function() {
- PDFView.page = PDFView.pdfDocument.numPages;
- });
-
- document.getElementById('page_rotate_ccw').addEventListener('click',
- function() {
- PDFView.rotatePages(-90);
- });
-
- document.getElementById('page_rotate_cw').addEventListener('click',
- function() {
- PDFView.rotatePages(90);
- });
-
-//#if (FIREFOX || MOZCENTRAL)
-//if (FirefoxCom.requestSync('getLoadingType') == 'passive') {
-// PDFView.setTitleUsingUrl(file);
-// PDFView.initPassiveLoading();
-// return;
-//}
-//#endif
-
-//#if !B2G
- PDFView.open(file, 0);
-//#endif
-}, true);
-
-function updateViewarea() {
-
- if (!PDFView.initialized)
- return;
- var visible = PDFView.getVisiblePages();
- var visiblePages = visible.views;
- if (visiblePages.length === 0) {
- return;
- }
-
- PDFView.renderHighestPriority();
-
- var currentId = PDFView.page;
- var firstPage = visible.first;
-
- for (var i = 0, ii = visiblePages.length, stillFullyVisible = false;
- i < ii; ++i) {
- var page = visiblePages[i];
-
- if (page.percent < 100)
- break;
-
- if (page.id === PDFView.page) {
- stillFullyVisible = true;
- break;
- }
- }
-
- if (!stillFullyVisible) {
- currentId = visiblePages[0].id;
- }
-
- if (!PDFView.isFullscreen) {
- updateViewarea.inProgress = true; // used in "set page"
- PDFView.page = currentId;
- updateViewarea.inProgress = false;
- }
-
- var currentScale = PDFView.currentScale;
- var currentScaleValue = PDFView.currentScaleValue;
- var normalizedScaleValue = currentScaleValue == currentScale ?
- currentScale * 100 : currentScaleValue;
-
- var pageNumber = firstPage.id;
- var pdfOpenParams = '#page=' + pageNumber;
- pdfOpenParams += '&zoom=' + normalizedScaleValue;
- var currentPage = PDFView.pages[pageNumber - 1];
- var topLeft = currentPage.getPagePoint(PDFView.container.scrollLeft,
- (PDFView.container.scrollTop - firstPage.y));
- pdfOpenParams += ',' + Math.round(topLeft[0]) + ',' + Math.round(topLeft[1]);
-
- var store = PDFView.store;
- store.initializedPromise.then(function() {
- store.set('exists', true);
- store.set('page', pageNumber);
- store.set('zoom', normalizedScaleValue);
- store.set('scrollLeft', Math.round(topLeft[0]));
- store.set('scrollTop', Math.round(topLeft[1]));
- });
- var href = PDFView.getAnchorUrl(pdfOpenParams);
- document.getElementById('viewBookmark').href = href;
-}
-
-window.addEventListener('resize', function webViewerResize(evt) {
- if (PDFView.initialized &&
- (document.getElementById('pageWidthOption').selected ||
- document.getElementById('pageFitOption').selected ||
- document.getElementById('pageAutoOption').selected))
- PDFView.parseScale(document.getElementById('scaleSelect').value);
- updateViewarea();
-});
-
-window.addEventListener('hashchange', function webViewerHashchange(evt) {
- PDFView.setHash(document.location.hash.substring(1));
-});
-
-window.addEventListener('change', function webViewerChange(evt) {
- var files = evt.target.files;
- if (!files || files.length === 0)
- return;
-
- // Read the local file into a Uint8Array.
- var fileReader = new FileReader();
- fileReader.onload = function webViewerChangeFileReaderOnload(evt) {
- var buffer = evt.target.result;
- var uint8Array = new Uint8Array(buffer);
- PDFView.open(uint8Array, 0);
- };
-
- var file = files[0];
- fileReader.readAsArrayBuffer(file);
- PDFView.setTitleUsingUrl(file.name);
-
- // URL does not reflect proper document location - hiding some icons.
- document.getElementById('viewBookmark').setAttribute('hidden', 'true');
- document.getElementById('download').setAttribute('hidden', 'true');
-}, true);
-
-function selectScaleOption(value) {
- var options = document.getElementById('scaleSelect').options;
- var predefinedValueFound = false;
- for (var i = 0; i < options.length; i++) {
- var option = options[i];
- if (option.value != value) {
- option.selected = false;
- continue;
- }
- option.selected = true;
- predefinedValueFound = true;
- }
- return predefinedValueFound;
-}
-
-window.addEventListener('localized', function localized(evt) {
- document.getElementsByTagName('html')[0].dir = mozL10n.getDirection();
-
- // Adjust the width of the zoom box to fit the content.
- PDFView.animationStartedPromise.then(
- function() {
- var container = document.getElementById('scaleSelectContainer');
- var select = document.getElementById('scaleSelect');
- select.setAttribute('style', 'min-width: inherit;');
- var width = select.clientWidth + 8;
- select.setAttribute('style', 'min-width: ' + (width + 20) + 'px;');
- container.setAttribute('style', 'min-width: ' + width + 'px; ' +
- 'max-width: ' + width + 'px;');
- });
-}, true);
-
-window.addEventListener('scalechange', function scalechange(evt) {
- var customScaleOption = document.getElementById('customScaleOption');
- customScaleOption.selected = false;
-
- if (!evt.resetAutoSettings &&
- (document.getElementById('pageWidthOption').selected ||
- document.getElementById('pageFitOption').selected ||
- document.getElementById('pageAutoOption').selected)) {
- updateViewarea();
- return;
- }
-
- var predefinedValueFound = selectScaleOption('' + evt.scale);
- if (!predefinedValueFound) {
- customScaleOption.textContent = Math.round(evt.scale * 10000) / 100 + '%';
- customScaleOption.selected = true;
- }
-
- document.getElementById('zoom_out').disabled = (evt.scale === MIN_SCALE);
- document.getElementById('zoom_in').disabled = (evt.scale === MAX_SCALE);
-
- updateViewarea();
-}, true);
-
-window.addEventListener('pagechange', function pagechange(evt) {
- var page = evt.pageNumber;
- if (PDFView.previousPageNumber !== page) {
- document.getElementById('pageNumber').value = page;
- var selected = document.querySelector('.thumbnail.selected');
- if (selected)
- selected.classList.remove('selected');
- var thumbnail = document.getElementById('thumbnailContainer' + page);
- thumbnail.classList.add('selected');
- var visibleThumbs = PDFView.getVisibleThumbs();
- var numVisibleThumbs = visibleThumbs.views.length;
- // If the thumbnail isn't currently visible scroll it into view.
- if (numVisibleThumbs > 0) {
- var first = visibleThumbs.first.id;
- // Account for only one thumbnail being visible.
- var last = numVisibleThumbs > 1 ?
- visibleThumbs.last.id : first;
- if (page <= first || page >= last)
- scrollIntoView(thumbnail);
- }
-
- }
- document.getElementById('previous').disabled = (page <= 1);
- document.getElementById('next').disabled = (page >= PDFView.pages.length);
-}, true);
-
-// Firefox specific event, so that we can prevent browser from zooming
-window.addEventListener('DOMMouseScroll', function(evt) {
- if (evt.ctrlKey) {
- evt.preventDefault();
-
- var ticks = evt.detail;
- var direction = (ticks > 0) ? 'zoomOut' : 'zoomIn';
- for (var i = 0, length = Math.abs(ticks); i < length; i++)
- PDFView[direction]();
- } else if (PDFView.isFullscreen) {
- var FIREFOX_DELTA_FACTOR = -40;
- PDFView.mouseScroll(evt.detail * FIREFOX_DELTA_FACTOR);
- }
-}, false);
-
-window.addEventListener('mousemove', function mousemove(evt) {
- if (PDFView.isFullscreen) {
- PDFView.showPresentationControls();
- }
-}, false);
-
-window.addEventListener('mousedown', function mousedown(evt) {
- if (PDFView.isFullscreen && evt.button === 0) {
- // Enable clicking of links in fullscreen mode.
- // Note: Only links that point to the currently loaded PDF document works.
- var targetHref = evt.target.href;
- var internalLink = targetHref && (targetHref.replace(/#.*$/, '') ===
- window.location.href.replace(/#.*$/, ''));
- if (!internalLink) {
- // Unless an internal link was clicked, advance a page in fullscreen mode.
- evt.preventDefault();
- PDFView.page++;
- }
- }
-}, false);
-
-window.addEventListener('click', function click(evt) {
- if (PDFView.isFullscreen && evt.button === 0) {
- // Necessary since preventDefault() in 'mousedown' won't stop
- // the event propagation in all circumstances.
- evt.preventDefault();
- }
-}, false);
-
-window.addEventListener('keydown', function keydown(evt) {
- var handled = false;
- var cmd = (evt.ctrlKey ? 1 : 0) |
- (evt.altKey ? 2 : 0) |
- (evt.shiftKey ? 4 : 0) |
- (evt.metaKey ? 8 : 0);
-
- // First, handle the key bindings that are independent whether an input
- // control is selected or not.
- if (cmd === 1 || cmd === 8 || cmd === 5 || cmd === 12) {
- // either CTRL or META key with optional SHIFT.
- switch (evt.keyCode) {
- case 70:
- if (!PDFView.supportsIntegratedFind) {
- PDFFindBar.toggle();
- handled = true;
- }
- break;
- case 61: // FF/Mac '='
- case 107: // FF '+' and '='
- case 187: // Chrome '+'
- case 171: // FF with German keyboard
- PDFView.zoomIn();
- handled = true;
- break;
- case 173: // FF/Mac '-'
- case 109: // FF '-'
- case 189: // Chrome '-'
- PDFView.zoomOut();
- handled = true;
- break;
- case 48: // '0'
- case 96: // '0' on Numpad of Swedish keyboard
- PDFView.parseScale(DEFAULT_SCALE, true);
- handled = false; // keeping it unhandled (to restore page zoom to 100%)
- break;
- }
- }
-
- // CTRL or META with or without SHIFT.
- if (cmd == 1 || cmd == 8 || cmd == 5 || cmd == 12) {
- switch (evt.keyCode) {
- case 71: // g
- if (!PDFView.supportsIntegratedFind) {
- PDFFindBar.dispatchEvent('again', cmd == 5 || cmd == 12);
- handled = true;
- }
- break;
- }
- }
-
- if (handled) {
- evt.preventDefault();
- return;
- }
-
- // Some shortcuts should not get handled if a control/input element
- // is selected.
- var curElement = document.activeElement;
- if (curElement && (curElement.tagName == 'INPUT' ||
- curElement.tagName == 'SELECT')) {
- return;
- }
- var controlsElement = document.getElementById('toolbar');
- while (curElement) {
- if (curElement === controlsElement && !PDFView.isFullscreen)
- return; // ignoring if the 'toolbar' element is focused
- curElement = curElement.parentNode;
- }
-
- if (cmd === 0) { // no control key pressed at all.
- switch (evt.keyCode) {
- case 38: // up arrow
- case 33: // pg up
- case 8: // backspace
- if (!PDFView.isFullscreen && PDFView.currentScaleValue !== 'page-fit') {
- break;
- }
- /* in fullscreen mode */
- /* falls through */
- case 37: // left arrow
- // horizontal scrolling using arrow keys
- if (PDFView.isHorizontalScrollbarEnabled) {
- break;
- }
- /* falls through */
- case 75: // 'k'
- case 80: // 'p'
- PDFView.page--;
- handled = true;
- break;
- case 27: // esc key
- if (!PDFView.supportsIntegratedFind && PDFFindBar.opened) {
- PDFFindBar.close();
- handled = true;
- }
- break;
- case 40: // down arrow
- case 34: // pg down
- case 32: // spacebar
- if (!PDFView.isFullscreen && PDFView.currentScaleValue !== 'page-fit') {
- break;
- }
- /* falls through */
- case 39: // right arrow
- // horizontal scrolling using arrow keys
- if (PDFView.isHorizontalScrollbarEnabled) {
- break;
- }
- /* falls through */
- case 74: // 'j'
- case 78: // 'n'
- PDFView.page++;
- handled = true;
- break;
-
- case 36: // home
- if (PDFView.isFullscreen) {
- PDFView.page = 1;
- handled = true;
- }
- break;
- case 35: // end
- if (PDFView.isFullscreen) {
- PDFView.page = PDFView.pdfDocument.numPages;
- handled = true;
- }
- break;
-
- case 82: // 'r'
- PDFView.rotatePages(90);
- break;
- }
- }
-
- if (cmd == 4) { // shift-key
- switch (evt.keyCode) {
- case 82: // 'r'
- PDFView.rotatePages(-90);
- break;
- }
- }
-
- if (handled) {
- evt.preventDefault();
- PDFView.clearMouseScrollState();
- }
-});
-
-window.addEventListener('beforeprint', function beforePrint(evt) {
- PDFView.beforePrint();
-});
-
-window.addEventListener('afterprint', function afterPrint(evt) {
- PDFView.afterPrint();
-});
-
-(function fullscreenClosure() {
- function fullscreenChange(e) {
- var isFullscreen = document.fullscreenElement || document.mozFullScreen ||
- document.webkitIsFullScreen;
-
- if (!isFullscreen) {
- PDFView.exitFullscreen();
- }
- }
-
- window.addEventListener('fullscreenchange', fullscreenChange, false);
- window.addEventListener('mozfullscreenchange', fullscreenChange, false);
- window.addEventListener('webkitfullscreenchange', fullscreenChange, false);
-})();
-
-(function animationStartedClosure() {
- // The offsetParent is not set until the pdf.js iframe or object is visible.
- // Waiting for first animation.
- var requestAnimationFrame = window.requestAnimationFrame ||
- window.mozRequestAnimationFrame ||
- window.webkitRequestAnimationFrame ||
- window.oRequestAnimationFrame ||
- window.msRequestAnimationFrame ||
- function startAtOnce(callback) { callback(); };
- PDFView.animationStartedPromise = new PDFJS.Promise();
- requestAnimationFrame(function onAnimationFrame() {
- PDFView.animationStartedPromise.resolve();
- });
-})();
-
-//#if B2G
-//window.navigator.mozSetMessageHandler('activity', function(activity) {
-// var url = activity.source.data.url;
-// PDFView.open(url);
-// var cancelButton = document.getElementById('activityClose');
-// cancelButton.addEventListener('click', function() {
-// activity.postResult('close');
-// });
-//});
-//#endif
diff --git a/mediagoblin/storage/cloudfiles.py b/mediagoblin/storage/cloudfiles.py
index b6e57c91..250f06d4 100644
--- a/mediagoblin/storage/cloudfiles.py
+++ b/mediagoblin/storage/cloudfiles.py
@@ -75,7 +75,7 @@ class CloudFilesStorage(StorageInterface):
_log.debug('Container: {0}'.format(
self.container.name))
- self.container_uri = self.container.public_uri()
+ self.container_uri = self.container.public_ssl_uri()
def _resolve_filepath(self, filepath):
return '/'.join(
diff --git a/mediagoblin/submit/lib.py b/mediagoblin/submit/lib.py
index 7c3b8ab3..7e85696b 100644
--- a/mediagoblin/submit/lib.py
+++ b/mediagoblin/submit/lib.py
@@ -19,6 +19,7 @@ import uuid
from werkzeug.utils import secure_filename
from werkzeug.datastructures import FileStorage
+from mediagoblin.db.models import MediaEntry
from mediagoblin.processing import mark_entry_failed
from mediagoblin.processing.task import process_media
@@ -36,6 +37,16 @@ def check_file_field(request, field_name):
return retval
+def new_upload_entry(user):
+ """
+ Create a new MediaEntry for uploading
+ """
+ entry = MediaEntry()
+ entry.uploader = user.id
+ entry.license = user.license_preference
+ return entry
+
+
def prepare_queue_task(app, entry, filename):
"""
Prepare a MediaEntry for the processing queue and get a queue file
diff --git a/mediagoblin/submit/views.py b/mediagoblin/submit/views.py
index e964ec12..3f9d5b2d 100644
--- a/mediagoblin/submit/views.py
+++ b/mediagoblin/submit/views.py
@@ -19,6 +19,7 @@ import mediagoblin.mg_globals as mg_globals
from os.path import splitext
import logging
+import uuid
_log = logging.getLogger(__name__)
@@ -32,7 +33,9 @@ from mediagoblin.messages import add_message, SUCCESS
from mediagoblin.media_types import sniff_media, \
InvalidFileType, FileTypeNotSupported
from mediagoblin.submit.lib import check_file_field, prepare_queue_task, \
- run_process_media
+ run_process_media, new_upload_entry
+
+from mediagoblin.notifications import add_comment_subscription
@require_active_login
@@ -51,24 +54,26 @@ def submit_start(request):
try:
filename = request.files['file'].filename
+ # If the filename contains non ascii generate a unique name
+ if not all(ord(c) < 128 for c in filename):
+ filename = unicode(uuid.uuid4()) + splitext(filename)[-1]
+
# Sniff the submitted media to determine which
# media plugin should handle processing
media_type, media_manager = sniff_media(
request.files['file'])
# create entry and save in database
- entry = request.db.MediaEntry()
+ entry = new_upload_entry(request.user)
entry.media_type = unicode(media_type)
entry.title = (
unicode(submit_form.title.data)
- or unicode(splitext(filename)[0]))
+ or unicode(splitext(request.files['file'].filename)[0]))
entry.description = unicode(submit_form.description.data)
entry.license = unicode(submit_form.license.data) or None
- entry.uploader = request.user.id
-
# Process the user's folksonomy "tags"
entry.tags = convert_to_tag_list_of_dicts(
submit_form.tags.data)
@@ -94,6 +99,8 @@ def submit_start(request):
run_process_media(entry, feed_url)
add_message(request, SUCCESS, _('Woohoo! Submitted!'))
+ add_comment_subscription(request.user, entry)
+
return redirect(request, "mediagoblin.user_pages.user_home",
user=request.user.username)
except Exception as e:
@@ -131,9 +138,9 @@ def add_collection(request, media=None):
collection.generate_slug()
# Make sure this user isn't duplicating an existing collection
- existing_collection = request.db.Collection.find_one({
- 'creator': request.user.id,
- 'title':collection.title})
+ existing_collection = request.db.Collection.query.filter_by(
+ creator=request.user.id,
+ title=collection.title).first()
if existing_collection:
add_message(request, messages.ERROR,
diff --git a/mediagoblin/templates/mediagoblin/auth/change_fp.html b/mediagoblin/templates/mediagoblin/auth/change_fp.html
index 1f7d9aca..a3cf9cb9 100644
--- a/mediagoblin/templates/mediagoblin/auth/change_fp.html
+++ b/mediagoblin/templates/mediagoblin/auth/change_fp.html
@@ -34,11 +34,10 @@
{{ csrf_token }}
<div class="form_box">
<h1>{% trans %}Set your new password{% endtrans %}</h1>
- {{ wtforms_util.render_divs(cp_form) }}
+ {{ wtforms_util.render_divs(cp_form, True) }}
<div class="form_submit_buttons">
<input type="submit" value="{% trans %}Set password{% endtrans %}" class="button_form"/>
</div>
</div>
- </form>
{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/auth/forgot_password.html b/mediagoblin/templates/mediagoblin/auth/forgot_password.html
index 46aeddef..6cfd2c85 100644
--- a/mediagoblin/templates/mediagoblin/auth/forgot_password.html
+++ b/mediagoblin/templates/mediagoblin/auth/forgot_password.html
@@ -29,7 +29,7 @@
{{ csrf_token }}
<div class="form_box">
<h1>{% trans %}Recover password{% endtrans %}</h1>
- {{ wtforms_util.render_divs(fp_form) }}
+ {{ wtforms_util.render_divs(fp_form, True) }}
<div class="form_submit_buttons">
<input type="submit" value="{% trans %}Send instructions{% endtrans %}" class="button_form"/>
</div>
diff --git a/mediagoblin/templates/mediagoblin/auth/login.html b/mediagoblin/templates/mediagoblin/auth/login.html
index 4a39059d..3329b5d0 100644
--- a/mediagoblin/templates/mediagoblin/auth/login.html
+++ b/mediagoblin/templates/mediagoblin/auth/login.html
@@ -29,7 +29,7 @@
{%- endblock %}
{% block mediagoblin_content %}
- <form action="{{ request.urlgen('mediagoblin.auth.login') }}"
+ <form action="{{ post_url }}"
method="POST" enctype="multipart/form-data">
{{ csrf_token }}
<div class="form_box">
@@ -41,15 +41,19 @@
{% endif %}
{% if allow_registration %}
<p>
- {% trans %}Don't have an account yet?{% endtrans %} <a href="{{ request.urlgen('mediagoblin.auth.register') }}">
+ {% trans %}Don't have an account yet?{% endtrans %}
+ <a href="{{ request.urlgen('mediagoblin.auth.register') }}">
{%- trans %}Create one here!{% endtrans %}</a>
</p>
{% endif %}
- {{ wtforms_util.render_divs(login_form) }}
- <p>
- <a href="{{ request.urlgen('mediagoblin.auth.forgot_password') }}" id="forgot_password">
- {% trans %}Forgot your password?{% endtrans %}</a>
- </p>
+ {% template_hook("login_link") %}
+ {{ wtforms_util.render_divs(login_form, True) }}
+ {% if pass_auth %}
+ <p>
+ <a href="{{ request.urlgen('mediagoblin.auth.forgot_password') }}" id="forgot_password">
+ {% trans %}Forgot your password?{% endtrans %}</a>
+ </p>
+ {% endif %}
<div class="form_submit_buttons">
<input type="submit" value="{% trans %}Log in{% endtrans %}" class="button_form"/>
</div>
diff --git a/mediagoblin/templates/mediagoblin/auth/register.html b/mediagoblin/templates/mediagoblin/auth/register.html
index 6dff0207..a7b8033f 100644
--- a/mediagoblin/templates/mediagoblin/auth/register.html
+++ b/mediagoblin/templates/mediagoblin/auth/register.html
@@ -30,11 +30,12 @@
{% block mediagoblin_content %}
- <form action="{{ request.urlgen('mediagoblin.auth.register') }}"
+ <form action="{{ post_url }}"
method="POST" enctype="multipart/form-data">
<div class="form_box">
<h1>{% trans %}Create an account!{% endtrans %}</h1>
- {{ wtforms_util.render_divs(register_form) }}
+ {% template_hook("register_link") %}
+ {{ wtforms_util.render_divs(register_form, True) }}
{{ csrf_token }}
<div class="form_submit_buttons">
<input type="submit" value="{% trans %}Create{% endtrans %}"
@@ -42,6 +43,4 @@
</div>
</div>
</form>
-<!-- Focus the username field by default -->
-<script>$(document).ready(function(){$("#username").focus();});</script>
{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/base.html b/mediagoblin/templates/mediagoblin/base.html
index 9c42a756..1fc4467c 100644
--- a/mediagoblin/templates/mediagoblin/base.html
+++ b/mediagoblin/templates/mediagoblin/base.html
@@ -34,6 +34,8 @@
src="{{ request.staticdirect('/js/extlib/jquery.js') }}"></script>
<script type="text/javascript"
src="{{ request.staticdirect('/js/header_dropdown.js') }}"></script>
+ <script type="text/javascript"
+ src="{{ request.staticdirect('/js/notifications.js') }}"></script>
{# For clarification, the difference between the extra_head.html template
# and the head template hook is that the former should be used by
@@ -48,7 +50,7 @@
{% endblock mediagoblin_head %}
</head>
<body>
- {% include 'mediagoblin/bits/body-start.html' %}
+ {% include 'mediagoblin/bits/body_start.html' %}
{% block mediagoblin_body %}
{% block mediagoblin_header %}
<header>
@@ -57,6 +59,12 @@
<div class="header_right">
{%- if request.user %}
{% if request.user and request.user.status == 'active' %}
+
+ {% set notification_count = request.notifications.get_notification_count(request.user.id) %}
+ {% if notification_count %}
+ <a href="#notifications" class="notification-gem button_action" title="Notifications">
+ {{ notification_count }}</a>
+ {% endif %}
<div class="button_action header_dropdown_down">&#9660;</div>
<div class="button_action header_dropdown_up">&#9650;</div>
{% elif request.user and request.user.status == "needs_email_verification" %}
@@ -67,7 +75,7 @@
{% trans %}Verify your email!{% endtrans %}</a>
or <a href="{{ request.urlgen('mediagoblin.auth.logout') }}">{% trans %}log out{% endtrans %}</a>
{% endif %}
- {%- else %}
+ {%- elif auth %}
<a href="{{ request.urlgen('mediagoblin.auth.login') }}?next={{
request.base_url|urlencode }}">
{%- trans %}Log in{% endtrans -%}
@@ -109,29 +117,21 @@
</a>
</p>
{% endif %}
+ {% include 'mediagoblin/fragments/header_notifications.html' %}
</div>
{% endif %}
</header>
{% endblock %}
<div class="container">
- {% include 'mediagoblin/bits/above-content.html' %}
+ {% include 'mediagoblin/bits/above_content.html' %}
<div class="mediagoblin_content">
{% include "mediagoblin/utils/messages.html" %}
{% block mediagoblin_content %}
{% endblock mediagoblin_content %}
</div>
- {%- block mediagoblin_footer %}
- <footer>
- {% trans -%}
- Powered by <a href="http://mediagoblin.org/" title='Version {{ version }}'>MediaGoblin</a>, a <a href="http://gnu.org/">GNU</a> project.
- {%- endtrans %}
- {% trans source_link=app_config['source_link'] -%}
- Released under the <a href="http://www.fsf.org/licensing/licenses/agpl-3.0.html">AGPL</a>. <a href="{{ source_link }}">Source code</a> available.
- {%- endtrans %}
- </footer>
- {%- endblock mediagoblin_footer %}
+ {%- include "mediagoblin/bits/base_footer.html" %}
</div>
{%- endblock mediagoblin_body %}
- {% include 'mediagoblin/bits/body-end.html' %}
+ {% include 'mediagoblin/bits/body_end.html' %}
</body>
</html>
diff --git a/mediagoblin/templates/mediagoblin/bits/above-content.html b/mediagoblin/templates/mediagoblin/bits/above_content.html
index bb7b9762..bb7b9762 100644
--- a/mediagoblin/templates/mediagoblin/bits/above-content.html
+++ b/mediagoblin/templates/mediagoblin/bits/above_content.html
diff --git a/mediagoblin/templates/mediagoblin/bits/base_footer.html b/mediagoblin/templates/mediagoblin/bits/base_footer.html
new file mode 100644
index 00000000..80cd41b0
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/bits/base_footer.html
@@ -0,0 +1,28 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011-2013 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#}
+
+{%- block mediagoblin_footer %}
+ <footer>
+ {% trans -%}
+ Powered by <a href="http://mediagoblin.org/" title='Version {{ version }}'>MediaGoblin</a>, a <a href="http://gnu.org/">GNU</a> project.
+ {%- endtrans %}
+ {% trans source_link=app_config['source_link'] -%}
+ Released under the <a href="http://www.fsf.org/licensing/licenses/agpl-3.0.html">AGPL</a>. <a href="{{ source_link }}">Source code</a> available.
+ {%- endtrans %}
+ </footer>
+{%- endblock mediagoblin_footer -%}
diff --git a/mediagoblin/templates/mediagoblin/bits/body-end.html b/mediagoblin/templates/mediagoblin/bits/body_end.html
index bb7b9762..bb7b9762 100644
--- a/mediagoblin/templates/mediagoblin/bits/body-end.html
+++ b/mediagoblin/templates/mediagoblin/bits/body_end.html
diff --git a/mediagoblin/templates/mediagoblin/bits/body-start.html b/mediagoblin/templates/mediagoblin/bits/body_start.html
index bb7b9762..bb7b9762 100644
--- a/mediagoblin/templates/mediagoblin/bits/body-start.html
+++ b/mediagoblin/templates/mediagoblin/bits/body_start.html
diff --git a/mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html b/mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html
new file mode 100644
index 00000000..9ef28a4d
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/bits/frontpage_welcome.html
@@ -0,0 +1,41 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#}
+
+{% if request.user %}
+ <h1>{% trans %}Explore{% endtrans %}</h1>
+ {% else %}
+ <h1>{% trans %}Hi there, welcome to this MediaGoblin site!{% endtrans %}</h1>
+ <img class="right_align" src="{{ request.staticdirect('/images/frontpage_image.png') }}" />
+ <p>{% trans %}This site is running <a href="http://mediagoblin.org">MediaGoblin</a>, an extraordinarily great piece of media hosting software.{% endtrans %}</p>
+ {% if auth %}
+ <p>{% trans %}To add your own media, place comments, and more, you can log in with your MediaGoblin account.{% endtrans %}</p>
+ {% if allow_registration %}
+ <p>{% trans %}Don't have one yet? It's easy!{% endtrans %}</p>
+ {% trans register_url=request.urlgen('mediagoblin.auth.register') -%}
+ <a class="button_action_highlight" href="{{ register_url }}">Create an account at this site</a>
+ or
+ {%- endtrans %}
+ {% endif %}
+ {% endif %}
+ {% trans %}
+ <a class="button_action" href="http://wiki.mediagoblin.org/HackingHowto">Set up MediaGoblin on your own server</a>
+ {%- endtrans %}
+
+ <div class="clear"></div>
+ {% endif %}
+
diff --git a/mediagoblin/templates/mediagoblin/edit/change_pass.html b/mediagoblin/templates/mediagoblin/edit/change_pass.html
new file mode 100644
index 00000000..2a1ffee0
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/edit/change_pass.html
@@ -0,0 +1,52 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#}
+{% extends "mediagoblin/base.html" %}
+
+{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
+
+{% block mediagoblin_head %}
+ <script type="text/javascript"
+ src="{{ request.staticdirect('/js/show_password.js') }}"></script>
+{% endblock mediagoblin_head %}
+
+{% block title -%}
+ {% trans username=user.username -%}
+ Changing {{ username }}'s password
+ {%- endtrans %} &mdash; {{ super() }}
+{%- endblock %}
+
+{% block mediagoblin_content %}
+ <form action="{{ request.urlgen('mediagoblin.edit.pass') }}"
+ method="POST" enctype="multipart/form-data">
+ <div class="form_box edit_box">
+ <h1>
+ {%- trans username=user.username -%}
+ Changing {{ username }}'s password
+ {%- endtrans -%}
+ </h1>
+ {{ wtforms_util.render_divs(form, True) }}
+ {{ csrf_token }}
+ <div class="form_submit_buttons">
+ <input type="submit" value="{% trans %}Save{% endtrans %}"
+ class="button_form" />
+ </div>
+ </div>
+ </form>
+{% endblock %}
+
+
diff --git a/mediagoblin/templates/mediagoblin/edit/edit_account.html b/mediagoblin/templates/mediagoblin/edit/edit_account.html
index 7fe2c031..51293acb 100644
--- a/mediagoblin/templates/mediagoblin/edit/edit_account.html
+++ b/mediagoblin/templates/mediagoblin/edit/edit_account.html
@@ -41,16 +41,18 @@
Changing {{ username }}'s account settings
{%- endtrans -%}
</h1>
- {{ wtforms_util.render_field_div(form.old_password) }}
- {{ wtforms_util.render_field_div(form.new_password) }}
- <div class="form_field_input">
- <p>{{ form.wants_comment_notification }}
- {{ wtforms_util.render_label(form.wants_comment_notification) }}</p>
- </div>
- {{- wtforms_util.render_field_div(form.license_preference) }}
- <div class="form_submit_buttons">
+ {% if pass_auth is defined %}
+ <p>
+ <a href="{{ request.urlgen('mediagoblin.edit.pass') }}">
+ {% trans %}Change your password.{% endtrans %}
+ </a>
+ </p>
+ {% endif %}
+ {% template_hook("edit_link") %}
+ {{ wtforms_util.render_divs(form, True) }}
+ <div class="form_submit_buttons">
<input type="submit" value="{% trans %}Save changes{% endtrans %}" class="button_form" />
- {{ csrf_token }}
+ {{ csrf_token }}
</div>
</div>
</form>
diff --git a/mediagoblin/templates/mediagoblin/edit/verification.txt b/mediagoblin/templates/mediagoblin/edit/verification.txt
new file mode 100644
index 00000000..d53cd5e8
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/edit/verification.txt
@@ -0,0 +1,29 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+-#}
+
+{% trans username=username, verification_url=verification_url|safe -%}
+Hi,
+
+We wanted to verify that you are {{ username }}. If this is the case, then
+please follow the link below to verify your new email address.
+
+{{ verification_url }}
+
+If you are not {{ username }} or didn't request an email change, you can ignore
+this email.
+{%- endtrans %}
diff --git a/mediagoblin/templates/mediagoblin/fragments/header_notifications.html b/mediagoblin/templates/mediagoblin/fragments/header_notifications.html
new file mode 100644
index 00000000..613100aa
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/fragments/header_notifications.html
@@ -0,0 +1,40 @@
+{% set notifications = request.notifications.get_notifications(request.user.id) %}
+{% if notifications %}
+ <div class="header_notifications">
+ <h3>{% trans %}New comments{% endtrans %}</h3>
+ <ul>
+ {% for notification in notifications %}
+ {% set comment = notification.subject %}
+ {% set comment_author = comment.get_author %}
+ {% set media = comment.get_entry %}
+ <li class="comment_wrapper">
+ <div class="comment_author">
+ <img src="{{ request.staticdirect('/images/icon_comment.png') }}" />
+ <a href="{{ request.urlgen('mediagoblin.user_pages.user_home',
+ user=comment_author.username) }}"
+ class="comment_authorlink">
+ {{- comment_author.username -}}
+ </a>
+ <a href="{{ request.urlgen('mediagoblin.user_pages.media_home.view_comment',
+ comment=comment.id,
+ user=media.get_uploader.username,
+ media=media.slug_or_id) }}#comment"
+ class="comment_whenlink">
+ <span title='{{- comment.created.strftime("%I:%M%p %Y-%m-%d") -}}'>
+ {%- trans formatted_time=timesince(comment.created) -%}
+ {{ formatted_time }} ago
+ {%- endtrans -%}
+ </span>
+ </a>:
+ </div>
+ <div class="comment_content">
+ {% autoescape False -%}
+ {{ comment.content_html }}
+ {%- endautoescape %}
+ </div>
+
+ </li>
+ {% endfor %}
+ </ul>
+ </div>
+{% endif %}
diff --git a/mediagoblin/templates/mediagoblin/media_displays/image.html b/mediagoblin/templates/mediagoblin/media_displays/image.html
index 158dd67f..d0050f50 100644
--- a/mediagoblin/templates/mediagoblin/media_displays/image.html
+++ b/mediagoblin/templates/mediagoblin/media_displays/image.html
@@ -27,3 +27,20 @@
{{ super() }}
{% template_hook("image_sideinfo") %}
{% endblock %}
+
+{% block mediagoblin_after_added_sidebar %}
+ {% if app_config['original_date_visible'] %}
+ {% set original_date = media.media_manager.get_original_date() %}
+
+ {% if original_date %}
+ <h3>{% trans %}Created{% endtrans %}</h3>
+
+ <p><span title="{{ original_date.strftime("%I:%M%p %Y-%m-%d") }}">
+ {%- trans formatted_time=timesince(original_date) -%}
+ {{ formatted_time }} ago
+ {%- endtrans -%}
+ </span></p>
+ {%- endif %}
+ {% endif %}
+{% endblock %}
+
diff --git a/mediagoblin/templates/mediagoblin/media_displays/pdf.html b/mediagoblin/templates/mediagoblin/media_displays/pdf.html
index e946f3ab..9319e87c 100644
--- a/mediagoblin/templates/mediagoblin/media_displays/pdf.html
+++ b/mediagoblin/templates/mediagoblin/media_displays/pdf.html
@@ -46,19 +46,21 @@
{%- endblock %}
{% block mediagoblin_media %}
-{% if pdf_js %}
-<iframe width=640px height=480px
- src="{{ request.staticdirect('/extlib/pdf.js/web/viewer.html') }}?file={{ pdf_view }} ">
-</iframe>
-
-{% else %}
- <a href="{{ pdf_view }}">
- <img id="medium"
- class="media_image"
- src="{{ medium_view }}"
- alt="{% trans media_title=media.title -%} Image for {{ media_title}}{% endtrans %}"/>
- </a>
-{% endif %}
+ {% if pdf_js %}
+ <iframe width="640px" height="480px"
+ src="{{ request.staticdirect('/extlib/pdf.js/web/viewer.html') }}?file={{ pdf_view }} ">
+ </iframe>
+ {% else %}
+ <a href="{{ pdf_view }}">
+ <img id="medium"
+ class="media_image"
+ src="{{ medium_view }}"
+ alt="
+ {%- trans media_title=media.title -%}
+ Image for {{ media_title}}
+ {%- endtrans %}"/>
+ </a>
+ {% endif %}
{% endblock %}
{% block mediagoblin_sidebar %}
diff --git a/mediagoblin/templates/mediagoblin/media_displays/stl.html b/mediagoblin/templates/mediagoblin/media_displays/stl.html
index a89e0b4f..bc12ce4e 100644
--- a/mediagoblin/templates/mediagoblin/media_displays/stl.html
+++ b/mediagoblin/templates/mediagoblin/media_displays/stl.html
@@ -108,32 +108,26 @@ window.show_things = function () {
<div style="padding: 4px;">
- <a class="button_action" onclick="show('perspective');"
- title="{%- trans %}Toggle Rotate{% endtrans -%}">
+ <a class="button_action" onclick="show('perspective');">
{%- trans %}Perspective{% endtrans -%}
</a>
- <a class="button_action" onclick="show('front_view');"
- title="{%- trans %}Front{% endtrans -%}">
+ <a class="button_action" onclick="show('front_view');">
{%- trans %}Front{% endtrans -%}
</a>
- <a class="button_action" onclick="show('top_view');"
- title="{%- trans %}Top{% endtrans -%}">
+ <a class="button_action" onclick="show('top_view');">
{%- trans %}Top{% endtrans -%}
</a>
- <a class="button_action" onclick="show('side_view');"
- title="{%- trans %}Side{% endtrans -%}">
+ <a class="button_action" onclick="show('side_view');">
{%- trans %}Side{% endtrans -%}
</a>
{% if media.media_data.file_type == "stl" %}
<a id="webgl_button" class="button_action"
- onclick="show_things();"
- title="{%- trans %}WebGL{% endtrans -%}">
+ onclick="show_things();">
{%- trans %}WebGL{% endtrans -%}
</a>
{% endif %}
<a class="button_action" href="{{ model_download }}"
- title="{%- trans %}Download{% endtrans -%}"
style="float:right;">
{%- trans %}Download model{% endtrans -%}
</a>
diff --git a/mediagoblin/templates/mediagoblin/root.html b/mediagoblin/templates/mediagoblin/root.html
index 529d89ef..15d53af1 100644
--- a/mediagoblin/templates/mediagoblin/root.html
+++ b/mediagoblin/templates/mediagoblin/root.html
@@ -27,23 +27,8 @@
{%- endblock mediagoblin_head %}
{% block mediagoblin_content %}
- {% if request.user %}
- <h1>{% trans %}Explore{% endtrans %}</h1>
- {% else %}
- <h1>{% trans %}Hi there, welcome to this MediaGoblin site!{% endtrans %}</h1>
- <img class="right_align" src="{{ request.staticdirect('/images/frontpage_image.png') }}" />
- <p>{% trans %}This site is running <a href="http://mediagoblin.org">MediaGoblin</a>, an extraordinarily great piece of media hosting software.{% endtrans %}</p>
- <p>{% trans %}To add your own media, place comments, and more, you can log in with your MediaGoblin account.{% endtrans %}</p>
- {% if allow_registration %}
- <p>{% trans %}Don't have one yet? It's easy!{% endtrans %}</p>
- {% trans register_url=request.urlgen('mediagoblin.auth.register') -%}
- <a class="button_action_highlight" href="{{ register_url }}">Create an account at this site</a>
- or
- <a class="button_action" href="http://wiki.mediagoblin.org/HackingHowto">Set up MediaGoblin on your own server</a>
- {%- endtrans %}
- {% endif %}
- <div class="clear"></div>
- {% endif %}
+ {% include "mediagoblin/bits/frontpage_welcome.html" %}
+
<h2>{% trans %}Most recent media{% endtrans %}</h2>
{{ object_gallery(request, media_entries, pagination) }}
diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html
index 667510d5..c16e4c78 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/media.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/media.html
@@ -81,20 +81,23 @@
user= media.get_uploader.username,
media_id=media.id) %}
<a class="button_action" href="{{ delete_url }}">{% trans %}Delete{% endtrans %}</a>
+
{% endif %}
{% autoescape False %}
<p>{{ media.description_html }}</p>
{% endautoescape %}
{% if comments %}
- <a
- {% if not request.user %}
- href="{{ request.urlgen('mediagoblin.auth.login') }}"
- {% endif %}
- {% if app_config['allow_comments'] %}
- class="button_action" id="button_addcomment" title="Add a comment">
- {% trans %}Add a comment{% endtrans %}
- {% endif %}
- </a>
+ {% if app_config['allow_comments'] %}
+ <a
+ {% if not request.user %}
+ href="{{ request.urlgen('mediagoblin.auth.login') }}"
+ {% endif %}
+ class="button_action" id="button_addcomment" title="Add a comment">
+ {% trans %}Add a comment{% endtrans %}
+ </a>
+ {% include "mediagoblin/utils/comment-subscription.html" %}
+
+ {% endif %}
{% if request.user %}
<form action="{{ request.urlgen('mediagoblin.user_pages.media_post_comment',
user= media.get_uploader.username,
@@ -154,19 +157,8 @@
{%- endtrans -%}
</span></p>
- {% if app_config['original_date_visible'] %}
- {% set original_date = media.media_manager.get_original_date() %}
-
- {% if original_date %}
- <h3>{% trans %}Created{% endtrans %}</h3>
-
- <p><span title="{{ original_date.strftime("%I:%M%p %Y-%m-%d") }}">
- {%- trans formatted_time=timesince(original_date) -%}
- {{ formatted_time }} ago
- {%- endtrans -%}
- </span></p>
- {%- endif %}
- {% endif %}
+ {% block mediagoblin_after_added_sidebar %}
+ {% endblock %}
{% if media.tags %}
{% include "mediagoblin/utils/tags.html" %}
diff --git a/mediagoblin/templates/mediagoblin/utils/comment-subscription.html b/mediagoblin/templates/mediagoblin/utils/comment-subscription.html
new file mode 100644
index 00000000..bd367e80
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/utils/comment-subscription.html
@@ -0,0 +1,34 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#}
+{%- if request.user %}
+ {% set subscription = request.notifications.get_comment_subscription(
+ request.user.id, media.id) %}
+ {% if not subscription or not subscription.notify %}
+ <a type="submit" href="{{ request.urlgen('mediagoblin.notifications.subscribe_comments',
+ user=media.get_uploader.username,
+ media=media.slug_or_id)}}"
+ class="button_action">Subscribe to comments
+ </a>
+ {% else %}
+ <a type="submit" href="{{ request.urlgen('mediagoblin.notifications.silence_comments',
+ user=media.get_uploader.username,
+ media=media.slug_or_id)}}"
+ class="button_action">Silence comments
+ </a>
+ {% endif %}
+{%- endif %}
diff --git a/mediagoblin/templates/mediagoblin/utils/exif.html b/mediagoblin/templates/mediagoblin/utils/exif.html
index a89e69c8..b62208e1 100644
--- a/mediagoblin/templates/mediagoblin/utils/exif.html
+++ b/mediagoblin/templates/mediagoblin/utils/exif.html
@@ -17,18 +17,51 @@
#}
{% block exif_content %}
+<noscript>
+ <style type="text/css">
+ #exif_additional_info {
+ display: block;
+ }
+ </style>
+</noscript>
+<div id="exif_content">
{% if app_config['exif_visible']
and media.media_data
and media.media_data.exif_all is defined
and media.media_data.exif_all %}
- <h3>EXIF</h3>
- <table>
+ <h3>Camera Information</h3>
+ <table id="exif_camera_information">
+ <tbody>
+ {% for label, value in media.exif_display_data_short().iteritems() %}
+ <tr>
+ <td class="col1">{{ label }}</td>
+ <td>{{ value }}</td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ <h3 id="exif_additional_info_button" class="button_action">
+ Additional Information
+ </h3>
+ <div id="exif_additional_info">
+ <table class="exif_info">
{% for key, tag in media.exif_display_iter() %}
<tr>
- <td>{{ key }}</td>
+ <td class="col1">{{ key }}</td>
<td>{{ tag.printable }}</td>
</tr>
{% endfor %}
</table>
+ </div>
{% endif %}
+<script type="text/javascript">
+$(document).ready(function(){
+
+$("#exif_additional_info_button").click(function(){
+ $("#exif_additional_info").slideToggle("slow");
+});
+
+});
+</script>
+</div> <!-- end exif_content div -->
{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/utils/wtforms.html b/mediagoblin/templates/mediagoblin/utils/wtforms.html
index be6976c2..e079274e 100644
--- a/mediagoblin/templates/mediagoblin/utils/wtforms.html
+++ b/mediagoblin/templates/mediagoblin/utils/wtforms.html
@@ -33,25 +33,37 @@
{%- endmacro %}
{# Generically render a field #}
-{% macro render_field_div(field) %}
- {{- render_label_p(field) }}
- <div class="form_field_input">
- {{ field }}
- {%- if field.errors -%}
- {% for error in field.errors %}
- <p class="form_field_error">{{ error }}</p>
- {% endfor %}
- {%- endif %}
- {%- if field.description %}
- <p class="form_field_description">{{ field.description|safe }}</p>
- {%- endif %}
- </div>
+{% macro render_field_div(field, autofocus_first=False) %}
+ {% if field.type == 'BooleanField' %}
+ {{ render_bool(field) }}
+ {% else %}
+ {{- render_label_p(field) }}
+ <div class="form_field_input">
+ {% if autofocus_first %}
+ {{ field(autofocus=True) }}
+ {% else %}
+ {{ field }}
+ {% endif %}
+ {%- if field.errors -%}
+ {% for error in field.errors %}
+ <p class="form_field_error">{{ error }}</p>
+ {% endfor %}
+ {%- endif %}
+ {%- if field.description %}
+ <p class="form_field_description">{{ field.description|safe }}</p>
+ {%- endif %}
+ </div>
+ {% endif %}
{%- endmacro %}
{# Auto-render a form as a series of divs #}
-{% macro render_divs(form) -%}
+{% macro render_divs(form, autofocus_first=False) -%}
{% for field in form %}
- {{ render_field_div(field) }}
+ {% if autofocus_first and loop.first %}
+ {{ render_field_div(field, True) }}
+ {% else %}
+ {{ render_field_div(field) }}
+ {% endif %}
{% endfor %}
{%- endmacro %}
@@ -74,3 +86,19 @@
</tr>
{% endfor %}
{%- endmacro %}
+
+{# Render a boolean field #}
+{% macro render_bool(field) %}
+ <div class="boolean">
+ <label for="{{ field.label.field_id }}">
+ {{ field }}</input>
+ {{ field.description|safe }}
+ </label>
+ {%- if field.errors -%}
+ {% for error in field.errors %}
+ <p class="form_field_error">{{ error }}</p>
+ {% endfor %}
+ {% endif %}
+ </div>
+{% endmacro %}
+
diff --git a/mediagoblin/tests/__init__.py b/mediagoblin/tests/__init__.py
index 7a88281e..cf200791 100644
--- a/mediagoblin/tests/__init__.py
+++ b/mediagoblin/tests/__init__.py
@@ -14,21 +14,9 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import os
-import shutil
-
-from mediagoblin import mg_globals
-from mediagoblin.tests.tools import TEST_USER_DEV
-
def setup_package():
import warnings
from sqlalchemy.exc import SAWarning
warnings.simplefilter("error", SAWarning)
-
-
-def teardown_package():
- # Remove and reinstall user_dev directories
- if os.path.exists(TEST_USER_DEV):
- shutil.rmtree(TEST_USER_DEV)
diff --git a/mediagoblin/tests/appconfig_context_modified.ini b/mediagoblin/tests/appconfig_context_modified.ini
new file mode 100644
index 00000000..cc6721f5
--- /dev/null
+++ b/mediagoblin/tests/appconfig_context_modified.ini
@@ -0,0 +1,27 @@
+[mediagoblin]
+direct_remote_path = /test_static/
+email_sender_address = "notice@mediagoblin.example.org"
+email_debug_mode = true
+
+#Runs with an in-memory sqlite db for speed.
+sql_engine = "sqlite://"
+run_migrations = true
+
+# Celery shouldn't be set up by the application as it's setup via
+# mediagoblin.init.celery.from_celery
+celery_setup_elsewhere = true
+
+[storage:publicstore]
+base_dir = %(here)s/user_dev/media/public
+base_url = /mgoblin_media/
+
+[storage:queuestore]
+base_dir = %(here)s/user_dev/media/queue
+
+[celery]
+CELERY_ALWAYS_EAGER = true
+CELERY_RESULT_DBURI = "sqlite:///%(here)s/user_dev/celery.db"
+BROKER_HOST = "sqlite:///%(here)s/user_dev/kombu.db"
+
+[plugins]
+[[mediagoblin.tests.testplugins.modify_context]]
diff --git a/mediagoblin/tests/appconfig_static_plugin.ini b/mediagoblin/tests/appconfig_static_plugin.ini
new file mode 100644
index 00000000..5ce5c5bd
--- /dev/null
+++ b/mediagoblin/tests/appconfig_static_plugin.ini
@@ -0,0 +1,27 @@
+[mediagoblin]
+direct_remote_path = /test_static/
+email_sender_address = "notice@mediagoblin.example.org"
+email_debug_mode = true
+
+#Runs with an in-memory sqlite db for speed.
+sql_engine = "sqlite://"
+run_migrations = true
+
+# Celery shouldn't be set up by the application as it's setup via
+# mediagoblin.init.celery.from_celery
+celery_setup_elsewhere = true
+
+[storage:publicstore]
+base_dir = %(here)s/user_dev/media/public
+base_url = /mgoblin_media/
+
+[storage:queuestore]
+base_dir = %(here)s/user_dev/media/queue
+
+[celery]
+CELERY_ALWAYS_EAGER = true
+CELERY_RESULT_DBURI = "sqlite:///%(here)s/user_dev/celery.db"
+BROKER_HOST = "sqlite:///%(here)s/user_dev/kombu.db"
+
+[plugins]
+[[mediagoblin.tests.testplugins.staticstuff]]
diff --git a/mediagoblin/tests/auth_configs/__init__.py b/mediagoblin/tests/auth_configs/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/mediagoblin/tests/auth_configs/__init__.py
diff --git a/mediagoblin/tests/auth_configs/authentication_disabled_appconfig.ini b/mediagoblin/tests/auth_configs/authentication_disabled_appconfig.ini
new file mode 100644
index 00000000..a64e9e40
--- /dev/null
+++ b/mediagoblin/tests/auth_configs/authentication_disabled_appconfig.ini
@@ -0,0 +1,25 @@
+[mediagoblin]
+direct_remote_path = /test_static/
+email_sender_address = "notice@mediagoblin.example.org"
+email_debug_mode = true
+
+# TODO: Switch to using an in-memory database
+sql_engine = "sqlite:///%(here)s/user_dev/mediagoblin.db"
+
+# Celery shouldn't be set up by the application as it's setup via
+# mediagoblin.init.celery.from_celery
+celery_setup_elsewhere = true
+
+[storage:publicstore]
+base_dir = %(here)s/user_dev/media/public
+base_url = /mgoblin_media/
+
+[storage:queuestore]
+base_dir = %(here)s/user_dev/media/queue
+
+[celery]
+CELERY_ALWAYS_EAGER = true
+CELERY_RESULT_DBURI = "sqlite:///%(here)s/user_dev/celery.db"
+BROKER_HOST = "sqlite:///%(here)s/user_dev/kombu.db"
+
+[plugins]
diff --git a/mediagoblin/tests/auth_configs/openid_appconfig.ini b/mediagoblin/tests/auth_configs/openid_appconfig.ini
new file mode 100644
index 00000000..c2bd82fd
--- /dev/null
+++ b/mediagoblin/tests/auth_configs/openid_appconfig.ini
@@ -0,0 +1,41 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+[mediagoblin]
+direct_remote_path = /test_static/
+email_sender_address = "notice@mediagoblin.example.org"
+email_debug_mode = true
+
+# TODO: Switch to using an in-memory database
+sql_engine = "sqlite:///%(here)s/user_dev/mediagoblin.db"
+
+# Celery shouldn't be set up by the application as it's setup via
+# mediagoblin.init.celery.from_celery
+celery_setup_elsewhere = true
+
+[storage:publicstore]
+base_dir = %(here)s/user_dev/media/public
+base_url = /mgoblin_media/
+
+[storage:queuestore]
+base_dir = %(here)s/user_dev/media/queue
+
+[celery]
+CELERY_ALWAYS_EAGER = true
+CELERY_RESULT_DBURI = "sqlite:///%(here)s/user_dev/celery.db"
+BROKER_HOST = "sqlite:///%(here)s/user_dev/kombu.db"
+
+[plugins]
+[[mediagoblin.plugins.openid]]
diff --git a/mediagoblin/tests/conftest.py b/mediagoblin/tests/conftest.py
index 25f495d6..dbb0aa0a 100644
--- a/mediagoblin/tests/conftest.py
+++ b/mediagoblin/tests/conftest.py
@@ -1,7 +1,25 @@
-from mediagoblin.tests import tools
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2013 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
import pytest
+from mediagoblin.tests import tools
+from mediagoblin.tools.testing import _activate_testing
+
+
@pytest.fixture()
def test_app(request):
"""
@@ -13,3 +31,11 @@ def test_app(request):
in differently to get_app.
"""
return tools.get_app(request)
+
+
+@pytest.fixture()
+def pt_fixture_enable_testing():
+ """
+ py.test fixture to enable testing mode in tools.
+ """
+ _activate_testing()
diff --git a/mediagoblin/tests/pytest.ini b/mediagoblin/tests/pytest.ini
index d4aa2d69..e561c074 100644
--- a/mediagoblin/tests/pytest.ini
+++ b/mediagoblin/tests/pytest.ini
@@ -1,2 +1,2 @@
[pytest]
-usefixtures = tmpdir \ No newline at end of file
+usefixtures = tmpdir pt_fixture_enable_testing
diff --git a/mediagoblin/tests/test_auth.py b/mediagoblin/tests/test_auth.py
index 755727f9..61503d32 100644
--- a/mediagoblin/tests/test_auth.py
+++ b/mediagoblin/tests/test_auth.py
@@ -13,54 +13,15 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
import urlparse
-import datetime
+import pkg_resources
+import pytest
from mediagoblin import mg_globals
-from mediagoblin.auth import lib as auth_lib
from mediagoblin.db.models import User
-from mediagoblin.tests.tools import fixture_add_user
+from mediagoblin.tests.tools import get_app, fixture_add_user
from mediagoblin.tools import template, mail
-
-
-########################
-# Test bcrypt auth funcs
-########################
-
-def test_bcrypt_check_password():
- # Check known 'lollerskates' password against check function
- assert auth_lib.bcrypt_check_password(
- 'lollerskates',
- '$2a$12$PXU03zfrVCujBhVeICTwtOaHTUs5FFwsscvSSTJkqx/2RQ0Lhy/nO')
-
- assert not auth_lib.bcrypt_check_password(
- 'notthepassword',
- '$2a$12$PXU03zfrVCujBhVeICTwtOaHTUs5FFwsscvSSTJkqx/2RQ0Lhy/nO')
-
- # Same thing, but with extra fake salt.
- assert not auth_lib.bcrypt_check_password(
- 'notthepassword',
- '$2a$12$ELVlnw3z1FMu6CEGs/L8XO8vl0BuWSlUHgh0rUrry9DUXGMUNWwl6',
- '3><7R45417')
-
-
-def test_bcrypt_gen_password_hash():
- pw = 'youwillneverguessthis'
-
- # Normal password hash generation, and check on that hash
- hashed_pw = auth_lib.bcrypt_gen_password_hash(pw)
- assert auth_lib.bcrypt_check_password(
- pw, hashed_pw)
- assert not auth_lib.bcrypt_check_password(
- 'notthepassword', hashed_pw)
-
- # Same thing, extra salt.
- hashed_pw = auth_lib.bcrypt_gen_password_hash(pw, '3><7R45417')
- assert auth_lib.bcrypt_check_password(
- pw, hashed_pw, '3><7R45417')
- assert not auth_lib.bcrypt_check_password(
- 'notthepassword', hashed_pw, '3><7R45417')
+from mediagoblin.auth import tools as auth_tools
def test_register_views(test_app):
@@ -132,8 +93,8 @@ def test_register_views(test_app):
assert 'mediagoblin/user_pages/user.html' in template.TEMPLATE_TEST_CONTEXT
## Make sure user is in place
- new_user = mg_globals.database.User.find_one(
- {'username': u'happygirl'})
+ new_user = mg_globals.database.User.query.filter_by(
+ username=u'happygirl').first()
assert new_user
assert new_user.status == u'needs_email_verification'
assert new_user.email_verified == False
@@ -156,24 +117,19 @@ def test_register_views(test_app):
assert path == u'/auth/verify_email/'
parsed_get_params = urlparse.parse_qs(get_params)
- ### user should have these same parameters
- assert parsed_get_params['userid'] == [
- unicode(new_user.id)]
- assert parsed_get_params['token'] == [
- new_user.verification_key]
-
## Try verifying with bs verification key, shouldn't work
template.clear_test_template_context()
response = test_app.get(
- "/auth/verify_email/?userid=%s&token=total_bs" % unicode(
- new_user.id))
+ "/auth/verify_email/?token=total_bs")
response.follow()
- context = template.TEMPLATE_TEST_CONTEXT[
- 'mediagoblin/user_pages/user.html']
+
+ # Correct redirect?
+ assert urlparse.urlsplit(response.location)[2] == '/'
+
# assert context['verification_successful'] == True
# TODO: Would be good to test messages here when we can do so...
- new_user = mg_globals.database.User.find_one(
- {'username': u'happygirl'})
+ new_user = mg_globals.database.User.query.filter_by(
+ username=u'happygirl').first()
assert new_user
assert new_user.status == u'needs_email_verification'
assert new_user.email_verified == False
@@ -186,8 +142,8 @@ def test_register_views(test_app):
'mediagoblin/user_pages/user.html']
# assert context['verification_successful'] == True
# TODO: Would be good to test messages here when we can do so...
- new_user = mg_globals.database.User.find_one(
- {'username': u'happygirl'})
+ new_user = mg_globals.database.User.query.filter_by(
+ username=u'happygirl').first()
assert new_user
assert new_user.status == u'active'
assert new_user.email_verified == True
@@ -233,35 +189,17 @@ def test_register_views(test_app):
path = urlparse.urlsplit(email_context['verification_url'])[2]
get_params = urlparse.urlsplit(email_context['verification_url'])[3]
- assert path == u'/auth/forgot_password/verify/'
parsed_get_params = urlparse.parse_qs(get_params)
-
- # user should have matching parameters
- new_user = mg_globals.database.User.find_one({'username': u'happygirl'})
- assert parsed_get_params['userid'] == [unicode(new_user.id)]
- assert parsed_get_params['token'] == [new_user.fp_verification_key]
-
- ### The forgotten password token should be set to expire in ~ 10 days
- # A few ticks have expired so there are only 9 full days left...
- assert (new_user.fp_token_expire - datetime.datetime.now()).days == 9
+ assert path == u'/auth/forgot_password/verify/'
## Try using a bs password-changing verification key, shouldn't work
template.clear_test_template_context()
response = test_app.get(
- "/auth/forgot_password/verify/?userid=%s&token=total_bs" % unicode(
- new_user.id), status=404)
- assert response.status.split()[0] == u'404' # status="404 NOT FOUND"
+ "/auth/forgot_password/verify/?token=total_bs")
+ response.follow()
- ## Try using an expired token to change password, shouldn't work
- template.clear_test_template_context()
- new_user = mg_globals.database.User.find_one({'username': u'happygirl'})
- real_token_expiration = new_user.fp_token_expire
- new_user.fp_token_expire = datetime.datetime.now()
- new_user.save()
- response = test_app.get("%s?%s" % (path, get_params), status=404)
- assert response.status.split()[0] == u'404' # status="404 NOT FOUND"
- new_user.fp_token_expire = real_token_expiration
- new_user.save()
+ # Correct redirect?
+ assert urlparse.urlsplit(response.location)[2] == '/'
## Verify step 1 of password-change works -- can see form to change password
template.clear_test_template_context()
@@ -272,7 +210,6 @@ def test_register_views(test_app):
template.clear_test_template_context()
response = test_app.post(
'/auth/forgot_password/verify/', {
- 'userid': parsed_get_params['userid'],
'password': 'iamveryveryhappy',
'token': parsed_get_params['token']})
response.follow()
@@ -298,6 +235,7 @@ def test_authentication_views(test_app):
# Make a new user
test_user = fixture_add_user(active_user=False)
+
# Get login
# ---------
test_app.get('/auth/login/')
@@ -310,7 +248,6 @@ def test_authentication_views(test_app):
context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
form = context['login_form']
assert form.username.errors == [u'This field is required.']
- assert form.password.errors == [u'This field is required.']
# Failed login - blank user
# -------------------------
@@ -328,9 +265,7 @@ def test_authentication_views(test_app):
response = test_app.post(
'/auth/login/', {
'username': u'chris'})
- context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
- form = context['login_form']
- assert form.password.errors == [u'This field is required.']
+ assert 'mediagoblin/auth/login.html' in template.TEMPLATE_TEST_CONTEXT
# Failed login - bad user
# -----------------------
@@ -394,3 +329,47 @@ def test_authentication_views(test_app):
'password': 'toast',
'next' : '/u/chris/'})
assert urlparse.urlsplit(response.location)[2] == '/u/chris/'
+
+
+@pytest.fixture()
+def authentication_disabled_app(request):
+ return get_app(
+ request,
+ mgoblin_config=pkg_resources.resource_filename(
+ 'mediagoblin.tests.auth_configs',
+ 'authentication_disabled_appconfig.ini'))
+
+
+def test_authentication_disabled_app(authentication_disabled_app):
+ # app.auth should = false
+ assert mg_globals.app.auth is False
+
+ # Try to visit register page
+ template.clear_test_template_context()
+ response = authentication_disabled_app.get('/auth/register/')
+ response.follow()
+
+ # Correct redirect?
+ assert urlparse.urlsplit(response.location)[2] == '/'
+ assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT
+
+ # Try to vist login page
+ template.clear_test_template_context()
+ response = authentication_disabled_app.get('/auth/login/')
+ response.follow()
+
+ # Correct redirect?
+ assert urlparse.urlsplit(response.location)[2] == '/'
+ assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT
+
+ ## Test check_login_simple should return None
+ assert auth_tools.check_login_simple('test', 'simple') is None
+
+ # Try to visit the forgot password page
+ template.clear_test_template_context()
+ response = authentication_disabled_app.get('/auth/register/')
+ response.follow()
+
+ # Correct redirect?
+ assert urlparse.urlsplit(response.location)[2] == '/'
+ assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT
diff --git a/mediagoblin/tests/test_basic_auth.py b/mediagoblin/tests/test_basic_auth.py
new file mode 100644
index 00000000..cdd80fca
--- /dev/null
+++ b/mediagoblin/tests/test_basic_auth.py
@@ -0,0 +1,59 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+from mediagoblin.plugins.basic_auth import tools as auth_tools
+from mediagoblin.tools.testing import _activate_testing
+
+_activate_testing()
+
+
+########################
+# Test bcrypt auth funcs
+########################
+
+
+def test_bcrypt_check_password():
+ # Check known 'lollerskates' password against check function
+ assert auth_tools.bcrypt_check_password(
+ 'lollerskates',
+ '$2a$12$PXU03zfrVCujBhVeICTwtOaHTUs5FFwsscvSSTJkqx/2RQ0Lhy/nO')
+
+ assert not auth_tools.bcrypt_check_password(
+ 'notthepassword',
+ '$2a$12$PXU03zfrVCujBhVeICTwtOaHTUs5FFwsscvSSTJkqx/2RQ0Lhy/nO')
+
+ # Same thing, but with extra fake salt.
+ assert not auth_tools.bcrypt_check_password(
+ 'notthepassword',
+ '$2a$12$ELVlnw3z1FMu6CEGs/L8XO8vl0BuWSlUHgh0rUrry9DUXGMUNWwl6',
+ '3><7R45417')
+
+
+def test_bcrypt_gen_password_hash():
+ pw = 'youwillneverguessthis'
+
+ # Normal password hash generation, and check on that hash
+ hashed_pw = auth_tools.bcrypt_gen_password_hash(pw)
+ assert auth_tools.bcrypt_check_password(
+ pw, hashed_pw)
+ assert not auth_tools.bcrypt_check_password(
+ 'notthepassword', hashed_pw)
+
+ # Same thing, extra salt.
+ hashed_pw = auth_tools.bcrypt_gen_password_hash(pw, '3><7R45417')
+ assert auth_tools.bcrypt_check_password(
+ pw, hashed_pw, '3><7R45417')
+ assert not auth_tools.bcrypt_check_password(
+ 'notthepassword', hashed_pw, '3><7R45417')
diff --git a/mediagoblin/tests/test_celery_setup.py b/mediagoblin/tests/test_celery_setup.py
index 5530c6f2..0184436a 100644
--- a/mediagoblin/tests/test_celery_setup.py
+++ b/mediagoblin/tests/test_celery_setup.py
@@ -48,7 +48,7 @@ def test_setup_celery_from_config():
assert isinstance(fake_celery_module.CELERYD_ETA_SCHEDULER_PRECISION, float)
assert fake_celery_module.CELERY_RESULT_PERSISTENT is True
assert fake_celery_module.CELERY_IMPORTS == [
- 'foo.bar.baz', 'this.is.an.import', 'mediagoblin.processing.task']
+ 'foo.bar.baz', 'this.is.an.import', 'mediagoblin.processing.task', 'mediagoblin.notifications.task']
assert fake_celery_module.CELERY_RESULT_BACKEND == 'database'
assert fake_celery_module.CELERY_RESULT_DBURI == (
'sqlite:///' +
diff --git a/mediagoblin/tests/test_edit.py b/mediagoblin/tests/test_edit.py
index cda2607f..d70d0478 100644
--- a/mediagoblin/tests/test_edit.py
+++ b/mediagoblin/tests/test_edit.py
@@ -14,13 +14,14 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import pytest
+import urlparse
from mediagoblin import mg_globals
from mediagoblin.db.models import User
from mediagoblin.tests.tools import fixture_add_user
-from mediagoblin.tools import template
-from mediagoblin.auth.lib import bcrypt_check_password
+from mediagoblin import auth
+from mediagoblin.tools import template, mail
+
class TestUserEdit(object):
def setup(self):
@@ -60,32 +61,34 @@ class TestUserEdit(object):
self.login(test_app)
# test that the password can be changed
- # template.clear_test_template_context()
+ template.clear_test_template_context()
res = test_app.post(
- '/edit/account/', {
+ '/edit/password/', {
'old_password': 'toast',
'new_password': '123456',
- 'wants_comment_notification': 'y'
})
+ res.follow()
+
+ # Did we redirect to the correct page?
+ assert urlparse.urlsplit(res.location)[2] == '/edit/account/'
- # Check for redirect on success
- assert res.status_int == 302
# test_user has to be fetched again in order to have the current values
test_user = User.query.filter_by(username=u'chris').first()
- assert bcrypt_check_password('123456', test_user.pw_hash)
+ assert auth.check_password('123456', test_user.pw_hash)
# Update current user passwd
self.user_password = '123456'
# test that the password cannot be changed if the given
- # old_password is wrong template.clear_test_template_context()
+ # old_password is wrong
+ template.clear_test_template_context()
test_app.post(
- '/edit/account/', {
+ '/edit/password/', {
'old_password': 'toast',
'new_password': '098765',
})
test_user = User.query.filter_by(username=u'chris').first()
- assert not bcrypt_check_password('098765', test_user.pw_hash)
+ assert not auth.check_password('098765', test_user.pw_hash)
def test_change_bio_url(self, test_app):
@@ -138,4 +141,68 @@ class TestUserEdit(object):
assert form.url.errors == [
u'This address contains errors']
+ def test_email_change(self, test_app):
+ self.login(test_app)
+
+ # Test email already in db
+ template.clear_test_template_context()
+ test_app.post(
+ '/edit/account/', {
+ 'new_email': 'chris@example.com',
+ 'password': 'toast'})
+
+ # Check form errors
+ context = template.TEMPLATE_TEST_CONTEXT[
+ 'mediagoblin/edit/edit_account.html']
+ assert context['form'].new_email.errors == [
+ u'Sorry, a user with that email address already exists.']
+
+ # Test successful email change
+ template.clear_test_template_context()
+ res = test_app.post(
+ '/edit/account/', {
+ 'new_email': 'new@example.com',
+ 'password': 'toast'})
+ res.follow()
+
+ # Correct redirect?
+ assert urlparse.urlsplit(res.location)[2] == '/u/chris/'
+
+ # Make sure we get email verification and try verifying
+ assert len(mail.EMAIL_TEST_INBOX) == 1
+ message = mail.EMAIL_TEST_INBOX.pop()
+ assert message['To'] == 'new@example.com'
+ email_context = template.TEMPLATE_TEST_CONTEXT[
+ 'mediagoblin/edit/verification.txt']
+ assert email_context['verification_url'] in \
+ message.get_payload(decode=True)
+
+ path = urlparse.urlsplit(email_context['verification_url'])[2]
+ assert path == u'/edit/verify_email/'
+
+ ## Try verifying with bs verification key, shouldn't work
+ template.clear_test_template_context()
+ res = test_app.get(
+ "/edit/verify_email/?token=total_bs")
+ res.follow()
+
+ # Correct redirect?
+ assert urlparse.urlsplit(res.location)[2] == '/'
+
+ # Email shouldn't be saved
+ email_in_db = mg_globals.database.User.query.filter_by(
+ email='new@example.com').first()
+ email = User.query.filter_by(username='chris').first().email
+ assert email_in_db is None
+ assert email == 'chris@example.com'
+
+ # Verify email activation works
+ template.clear_test_template_context()
+ get_params = urlparse.urlsplit(email_context['verification_url'])[3]
+ res = test_app.get('%s?%s' % (path, get_params))
+ res.follow()
+
+ # New email saved?
+ email = User.query.filter_by(username='chris').first().email
+ assert email == 'new@example.com'
# test changing the url inproperly
diff --git a/mediagoblin/tests/test_exif.py b/mediagoblin/tests/test_exif.py
index 824de3c2..c07e24ae 100644
--- a/mediagoblin/tests/test_exif.py
+++ b/mediagoblin/tests/test_exif.py
@@ -48,63 +48,324 @@ def test_exif_extraction():
assert gps == {}
# Do we have the "useful" tags?
- assert useful == {
- 'EXIF Flash': {
- 'field_type': 3,
- 'printable': u'Flash did not fire',
- 'field_offset': 380,
- 'tag': 37385,
- 'values': [0],
- 'field_length': 2},
- 'EXIF ExposureTime': {
- 'field_type': 5,
- 'printable': '1/125',
- 'field_offset': 700,
- 'tag': 33434,
- 'values': [[1, 125]],
- 'field_length': 8},
- 'EXIF FocalLength': {
- 'field_type': 5,
- 'printable': '18',
- 'field_offset': 780,
- 'tag': 37386,
- 'values': [[18, 1]],
- 'field_length': 8},
- 'Image Model': {
- 'field_type': 2,
- 'printable': 'NIKON D80',
- 'field_offset': 152,
- 'tag': 272,
- 'values': 'NIKON D80',
- 'field_length': 10},
- 'Image Make': {
- 'field_type': 2,
- 'printable': 'NIKON CORPORATION',
- 'field_offset': 134,
- 'tag': 271,
- 'values': 'NIKON CORPORATION',
- 'field_length': 18},
- 'EXIF ExposureMode': {
- 'field_type': 3,
- 'printable': 'Manual Exposure',
- 'field_offset': 584,
- 'tag': 41986,
- 'values': [1],
- 'field_length': 2},
- 'EXIF ISOSpeedRatings': {
- 'field_type': 3,
- 'printable': '100',
- 'field_offset': 260,
- 'tag': 34855,
- 'values': [100],
- 'field_length': 2},
- 'EXIF FNumber': {
- 'field_type': 5,
- 'printable': '10',
- 'field_offset': 708,
- 'tag': 33437,
- 'values': [[10, 1]],
- 'field_length': 8}}
+ assert useful == {'EXIF CVAPattern': {'field_length': 8,
+ 'field_offset': 26224,
+ 'field_type': 7,
+ 'printable': u'[0, 2, 0, 2, 1, 2, 0, 1]',
+ 'tag': 41730,
+ 'values': [0, 2, 0, 2, 1, 2, 0, 1]},
+ 'EXIF ColorSpace': {'field_length': 2,
+ 'field_offset': 476,
+ 'field_type': 3,
+ 'printable': u'sRGB',
+ 'tag': 40961,
+ 'values': [1]},
+ 'EXIF ComponentsConfiguration': {'field_length': 4,
+ 'field_offset': 308,
+ 'field_type': 7,
+ 'printable': u'YCbCr',
+ 'tag': 37121,
+ 'values': [1, 2, 3, 0]},
+ 'EXIF CompressedBitsPerPixel': {'field_length': 8,
+ 'field_offset': 756,
+ 'field_type': 5,
+ 'printable': u'4',
+ 'tag': 37122,
+ 'values': [[4, 1]]},
+ 'EXIF Contrast': {'field_length': 2,
+ 'field_offset': 656,
+ 'field_type': 3,
+ 'printable': u'Soft',
+ 'tag': 41992,
+ 'values': [1]},
+ 'EXIF CustomRendered': {'field_length': 2,
+ 'field_offset': 572,
+ 'field_type': 3,
+ 'printable': u'Normal',
+ 'tag': 41985,
+ 'values': [0]},
+ 'EXIF DateTimeDigitized': {'field_length': 20,
+ 'field_offset': 736,
+ 'field_type': 2,
+ 'printable': u'2011:06:22 12:20:33',
+ 'tag': 36868,
+ 'values': u'2011:06:22 12:20:33'},
+ 'EXIF DateTimeOriginal': {'field_length': 20,
+ 'field_offset': 716,
+ 'field_type': 2,
+ 'printable': u'2011:06:22 12:20:33',
+ 'tag': 36867,
+ 'values': u'2011:06:22 12:20:33'},
+ 'EXIF DigitalZoomRatio': {'field_length': 8,
+ 'field_offset': 26232,
+ 'field_type': 5,
+ 'printable': u'1',
+ 'tag': 41988,
+ 'values': [[1, 1]]},
+ 'EXIF ExifImageLength': {'field_length': 2,
+ 'field_offset': 500,
+ 'field_type': 3,
+ 'printable': u'2592',
+ 'tag': 40963,
+ 'values': [2592]},
+ 'EXIF ExifImageWidth': {'field_length': 2,
+ 'field_offset': 488,
+ 'field_type': 3,
+ 'printable': u'3872',
+ 'tag': 40962,
+ 'values': [3872]},
+ 'EXIF ExifVersion': {'field_length': 4,
+ 'field_offset': 272,
+ 'field_type': 7,
+ 'printable': u'0221',
+ 'tag': 36864,
+ 'values': [48, 50, 50, 49]},
+ 'EXIF ExposureBiasValue': {'field_length': 8,
+ 'field_offset': 764,
+ 'field_type': 10,
+ 'printable': u'0',
+ 'tag': 37380,
+ 'values': [[0, 1]]},
+ 'EXIF ExposureMode': {'field_length': 2,
+ 'field_offset': 584,
+ 'field_type': 3,
+ 'printable': u'Manual Exposure',
+ 'tag': 41986,
+ 'values': [1]},
+ 'EXIF ExposureProgram': {'field_length': 2,
+ 'field_offset': 248,
+ 'field_type': 3,
+ 'printable': u'Manual',
+ 'tag': 34850,
+ 'values': [1]},
+ 'EXIF ExposureTime': {'field_length': 8,
+ 'field_offset': 700,
+ 'field_type': 5,
+ 'printable': u'1/125',
+ 'tag': 33434,
+ 'values': [[1, 125]]},
+ 'EXIF FNumber': {'field_length': 8,
+ 'field_offset': 708,
+ 'field_type': 5,
+ 'printable': u'10',
+ 'tag': 33437,
+ 'values': [[10, 1]]},
+ 'EXIF FileSource': {'field_length': 1,
+ 'field_offset': 536,
+ 'field_type': 7,
+ 'printable': u'Digital Camera',
+ 'tag': 41728,
+ 'values': [3]},
+ 'EXIF Flash': {'field_length': 2,
+ 'field_offset': 380,
+ 'field_type': 3,
+ 'printable': u'Flash did not fire',
+ 'tag': 37385,
+ 'values': [0]},
+ 'EXIF FlashPixVersion': {'field_length': 4,
+ 'field_offset': 464,
+ 'field_type': 7,
+ 'printable': u'0100',
+ 'tag': 40960,
+ 'values': [48, 49, 48, 48]},
+ 'EXIF FocalLength': {'field_length': 8,
+ 'field_offset': 780,
+ 'field_type': 5,
+ 'printable': u'18',
+ 'tag': 37386,
+ 'values': [[18, 1]]},
+ 'EXIF FocalLengthIn35mmFilm': {'field_length': 2,
+ 'field_offset': 620,
+ 'field_type': 3,
+ 'printable': u'27',
+ 'tag': 41989,
+ 'values': [27]},
+ 'EXIF GainControl': {'field_length': 2,
+ 'field_offset': 644,
+ 'field_type': 3,
+ 'printable': u'None',
+ 'tag': 41991,
+ 'values': [0]},
+ 'EXIF ISOSpeedRatings': {'field_length': 2,
+ 'field_offset': 260,
+ 'field_type': 3,
+ 'printable': u'100',
+ 'tag': 34855,
+ 'values': [100]},
+ 'EXIF InteroperabilityOffset': {'field_length': 4,
+ 'field_offset': 512,
+ 'field_type': 4,
+ 'printable': u'26240',
+ 'tag': 40965,
+ 'values': [26240]},
+ 'EXIF LightSource': {'field_length': 2,
+ 'field_offset': 368,
+ 'field_type': 3,
+ 'printable': u'Unknown',
+ 'tag': 37384,
+ 'values': [0]},
+ 'EXIF MaxApertureValue': {'field_length': 8,
+ 'field_offset': 772,
+ 'field_type': 5,
+ 'printable': u'18/5',
+ 'tag': 37381,
+ 'values': [[18, 5]]},
+ 'EXIF MeteringMode': {'field_length': 2,
+ 'field_offset': 356,
+ 'field_type': 3,
+ 'printable': u'Pattern',
+ 'tag': 37383,
+ 'values': [5]},
+ 'EXIF Saturation': {'field_length': 2,
+ 'field_offset': 668,
+ 'field_type': 3,
+ 'printable': u'Normal',
+ 'tag': 41993,
+ 'values': [0]},
+ 'EXIF SceneCaptureType': {'field_length': 2,
+ 'field_offset': 632,
+ 'field_type': 3,
+ 'printable': u'Standard',
+ 'tag': 41990,
+ 'values': [0]},
+ 'EXIF SceneType': {'field_length': 1,
+ 'field_offset': 548,
+ 'field_type': 7,
+ 'printable': u'Directly Photographed',
+ 'tag': 41729,
+ 'values': [1]},
+ 'EXIF SensingMethod': {'field_length': 2,
+ 'field_offset': 524,
+ 'field_type': 3,
+ 'printable': u'One-chip color area',
+ 'tag': 41495,
+ 'values': [2]},
+ 'EXIF Sharpness': {'field_length': 2,
+ 'field_offset': 680,
+ 'field_type': 3,
+ 'printable': u'Normal',
+ 'tag': 41994,
+ 'values': [0]},
+ 'EXIF SubSecTime': {'field_length': 3,
+ 'field_offset': 428,
+ 'field_type': 2,
+ 'printable': u'10',
+ 'tag': 37520,
+ 'values': u'10'},
+ 'EXIF SubSecTimeDigitized': {'field_length': 3,
+ 'field_offset': 452,
+ 'field_type': 2,
+ 'printable': u'10',
+ 'tag': 37522,
+ 'values': u'10'},
+ 'EXIF SubSecTimeOriginal': {'field_length': 3,
+ 'field_offset': 440,
+ 'field_type': 2,
+ 'printable': u'10',
+ 'tag': 37521,
+ 'values': u'10'},
+ 'EXIF SubjectDistanceRange': {'field_length': 2,
+ 'field_offset': 692,
+ 'field_type': 3,
+ 'printable': u'0',
+ 'tag': 41996,
+ 'values': [0]},
+ 'EXIF WhiteBalance': {'field_length': 2,
+ 'field_offset': 596,
+ 'field_type': 3,
+ 'printable': u'Auto',
+ 'tag': 41987,
+ 'values': [0]},
+ 'Image DateTime': {'field_length': 20,
+ 'field_offset': 194,
+ 'field_type': 2,
+ 'printable': u'2011:06:22 12:20:33',
+ 'tag': 306,
+ 'values': u'2011:06:22 12:20:33'},
+ 'Image ExifOffset': {'field_length': 4,
+ 'field_offset': 126,
+ 'field_type': 4,
+ 'printable': u'214',
+ 'tag': 34665,
+ 'values': [214]},
+ 'Image Make': {'field_length': 18,
+ 'field_offset': 134,
+ 'field_type': 2,
+ 'printable': u'NIKON CORPORATION',
+ 'tag': 271,
+ 'values': u'NIKON CORPORATION'},
+ 'Image Model': {'field_length': 10,
+ 'field_offset': 152,
+ 'field_type': 2,
+ 'printable': u'NIKON D80',
+ 'tag': 272,
+ 'values': u'NIKON D80'},
+ 'Image Orientation': {'field_length': 2,
+ 'field_offset': 42,
+ 'field_type': 3,
+ 'printable': u'Rotated 90 CCW',
+ 'tag': 274,
+ 'values': [6]},
+ 'Image ResolutionUnit': {'field_length': 2,
+ 'field_offset': 78,
+ 'field_type': 3,
+ 'printable': u'Pixels/Inch',
+ 'tag': 296,
+ 'values': [2]},
+ 'Image Software': {'field_length': 15,
+ 'field_offset': 178,
+ 'field_type': 2,
+ 'printable': u'Shotwell 0.9.3',
+ 'tag': 305,
+ 'values': u'Shotwell 0.9.3'},
+ 'Image XResolution': {'field_length': 8,
+ 'field_offset': 162,
+ 'field_type': 5,
+ 'printable': u'300',
+ 'tag': 282,
+ 'values': [[300, 1]]},
+ 'Image YCbCrPositioning': {'field_length': 2,
+ 'field_offset': 114,
+ 'field_type': 3,
+ 'printable': u'Co-sited',
+ 'tag': 531,
+ 'values': [2]},
+ 'Image YResolution': {'field_length': 8,
+ 'field_offset': 170,
+ 'field_type': 5,
+ 'printable': u'300',
+ 'tag': 283,
+ 'values': [[300, 1]]},
+ 'Thumbnail Compression': {'field_length': 2,
+ 'field_offset': 26280,
+ 'field_type': 3,
+ 'printable': u'JPEG (old-style)',
+ 'tag': 259,
+ 'values': [6]},
+ 'Thumbnail ResolutionUnit': {'field_length': 2,
+ 'field_offset': 26316,
+ 'field_type': 3,
+ 'printable': u'Pixels/Inch',
+ 'tag': 296,
+ 'values': [2]},
+ 'Thumbnail XResolution': {'field_length': 8,
+ 'field_offset': 26360,
+ 'field_type': 5,
+ 'printable': u'300',
+ 'tag': 282,
+ 'values': [[300, 1]]},
+ 'Thumbnail YCbCrPositioning': {'field_length': 2,
+ 'field_offset': 26352,
+ 'field_type': 3,
+ 'printable': u'Co-sited',
+ 'tag': 531,
+ 'values': [2]},
+ 'Thumbnail YResolution': {'field_length': 8,
+ 'field_offset': 26368,
+ 'field_type': 5,
+ 'printable': u'300',
+ 'tag': 283,
+ 'values': [[300, 1]]}}
def test_exif_image_orientation():
diff --git a/mediagoblin/tests/test_mgoblin_app.ini b/mediagoblin/tests/test_mgoblin_app.ini
index 2e876812..535cf1c1 100644
--- a/mediagoblin/tests/test_mgoblin_app.ini
+++ b/mediagoblin/tests/test_mgoblin_app.ini
@@ -3,8 +3,9 @@ direct_remote_path = /test_static/
email_sender_address = "notice@mediagoblin.example.org"
email_debug_mode = true
-# TODO: Switch to using an in-memory database
-sql_engine = "sqlite:///%(here)s/test_user_dev/mediagoblin.db"
+#Runs with an in-memory sqlite db for speed.
+sql_engine = "sqlite://"
+run_migrations = true
# tag parsing
tags_max_length = 50
@@ -12,22 +13,24 @@ tags_max_length = 50
# So we can start to test attachments:
allow_attachments = True
-media_types = mediagoblin.media_types.image, mediagoblin.media_types.pdf
-
[storage:publicstore]
-base_dir = %(here)s/test_user_dev/media/public
+base_dir = %(here)s/user_dev/media/public
base_url = /mgoblin_media/
[storage:queuestore]
-base_dir = %(here)s/test_user_dev/media/queue
+base_dir = %(here)s/user_dev/media/queue
[celery]
CELERY_ALWAYS_EAGER = true
-CELERY_RESULT_DBURI = "sqlite:///%(here)s/test_user_dev/celery.db"
-BROKER_HOST = "sqlite:///%(here)s/test_user_dev/kombu.db"
+CELERY_RESULT_DBURI = "sqlite:///%(here)s/user_dev/celery.db"
+BROKER_HOST = "sqlite:///%(here)s/user_dev/kombu.db"
[plugins]
[[mediagoblin.plugins.api]]
[[mediagoblin.plugins.oauth]]
[[mediagoblin.plugins.httpapiauth]]
[[mediagoblin.plugins.piwigo]]
+[[mediagoblin.plugins.basic_auth]]
+[[mediagoblin.plugins.openid]]
+[[mediagoblin.media_types.image]]
+[[mediagoblin.media_types.pdf]]
diff --git a/mediagoblin/tests/test_misc.py b/mediagoblin/tests/test_misc.py
index 755d863f..43ad0b6d 100644
--- a/mediagoblin/tests/test_misc.py
+++ b/mediagoblin/tests/test_misc.py
@@ -28,8 +28,10 @@ def test_user_deletes_other_comments(test_app):
user_a = fixture_add_user(u"chris_a")
user_b = fixture_add_user(u"chris_b")
- media_a = fixture_media_entry(uploader=user_a.id, save=False)
- media_b = fixture_media_entry(uploader=user_b.id, save=False)
+ media_a = fixture_media_entry(uploader=user_a.id, save=False,
+ expunge=False, fake_upload=False)
+ media_b = fixture_media_entry(uploader=user_b.id, save=False,
+ expunge=False, fake_upload=False)
Session.add(media_a)
Session.add(media_b)
Session.flush()
@@ -79,7 +81,7 @@ def test_user_deletes_other_comments(test_app):
def test_media_deletes_broken_attachment(test_app):
user_a = fixture_add_user(u"chris_a")
- media = fixture_media_entry(uploader=user_a.id, save=False)
+ media = fixture_media_entry(uploader=user_a.id, save=False, expunge=False)
media.attachment_files.append(dict(
name=u"some name",
filepath=[u"does", u"not", u"exist"],
diff --git a/mediagoblin/tests/test_notifications.py b/mediagoblin/tests/test_notifications.py
new file mode 100644
index 00000000..d52b8d5a
--- /dev/null
+++ b/mediagoblin/tests/test_notifications.py
@@ -0,0 +1,151 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import pytest
+
+import urlparse
+
+from mediagoblin.tools import template, mail
+
+from mediagoblin.db.models import Notification, CommentNotification, \
+ CommentSubscription
+from mediagoblin.db.base import Session
+
+from mediagoblin.notifications import mark_comment_notification_seen
+
+from mediagoblin.tests.tools import fixture_add_comment, \
+ fixture_media_entry, fixture_add_user, \
+ fixture_comment_subscription
+
+
+class TestNotifications:
+ @pytest.fixture(autouse=True)
+ def setup(self, test_app):
+ self.test_app = test_app
+
+ # TODO: Possibly abstract into a decorator like:
+ # @as_authenticated_user('chris')
+ self.test_user = fixture_add_user()
+
+ self.current_user = None
+
+ self.login()
+
+ def login(self, username=u'chris', password=u'toast'):
+ response = self.test_app.post(
+ '/auth/login/', {
+ 'username': username,
+ 'password': password})
+
+ response.follow()
+
+ assert urlparse.urlsplit(response.location)[2] == '/'
+ assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT
+
+ ctx = template.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html']
+
+ assert Session.merge(ctx['request'].user).username == username
+
+ self.current_user = ctx['request'].user
+
+ def logout(self):
+ self.test_app.get('/auth/logout/')
+ self.current_user = None
+
+ @pytest.mark.parametrize('wants_email', [True, False])
+ def test_comment_notification(self, wants_email):
+ '''
+ Test
+ - if a notification is created when posting a comment on
+ another users media entry.
+ - that the comment data is consistent and exists.
+
+ '''
+ user = fixture_add_user('otherperson', password='nosreprehto',
+ wants_comment_notification=wants_email)
+
+ user_id = user.id
+
+ media_entry = fixture_media_entry(uploader=user.id, state=u'processed')
+
+ media_entry_id = media_entry.id
+
+ subscription = fixture_comment_subscription(media_entry)
+
+ subscription_id = subscription.id
+
+ media_uri_id = '/u/{0}/m/{1}/'.format(user.username,
+ media_entry.id)
+ media_uri_slug = '/u/{0}/m/{1}/'.format(user.username,
+ media_entry.slug)
+
+ self.test_app.post(
+ media_uri_id + 'comment/add/',
+ {
+ 'comment_content': u'Test comment #42'
+ }
+ )
+
+ notifications = Notification.query.filter_by(
+ user_id=user.id).all()
+
+ assert len(notifications) == 1
+
+ notification = notifications[0]
+
+ assert type(notification) == CommentNotification
+ assert notification.seen == False
+ assert notification.user_id == user.id
+ assert notification.subject.get_author.id == self.test_user.id
+ assert notification.subject.content == u'Test comment #42'
+
+ if wants_email == True:
+ assert mail.EMAIL_TEST_MBOX_INBOX == [
+ {'from': 'notice@mediagoblin.example.org',
+ 'message': 'Content-Type: text/plain; \
+charset="utf-8"\nMIME-Version: 1.0\nContent-Transfer-Encoding: \
+base64\nSubject: GNU MediaGoblin - chris commented on your \
+post\nFrom: notice@mediagoblin.example.org\nTo: \
+otherperson@example.com\n\nSGkgb3RoZXJwZXJzb24sCmNocmlzIGNvbW1lbnRlZCBvbiB5b3VyIHBvc3QgKGh0dHA6Ly9sb2Nh\nbGhvc3Q6ODAvdS9vdGhlcnBlcnNvbi9tL3NvbWUtdGl0bGUvYy8xLyNjb21tZW50KSBhdCBHTlUg\nTWVkaWFHb2JsaW4KClRlc3QgY29tbWVudCAjNDIKCkdOVSBNZWRpYUdvYmxpbg==\n',
+ 'to': [u'otherperson@example.com']}]
+ else:
+ assert mail.EMAIL_TEST_MBOX_INBOX == []
+
+ # Save the ids temporarily because of DetachedInstanceError
+ notification_id = notification.id
+ comment_id = notification.subject.id
+
+ self.logout()
+ self.login('otherperson', 'nosreprehto')
+
+ self.test_app.get(media_uri_slug + '/c/{0}/'.format(comment_id))
+
+ notification = Notification.query.filter_by(id=notification_id).first()
+
+ assert notification.seen == True
+
+ self.test_app.get(media_uri_slug + '/notifications/silence/')
+
+ subscription = CommentSubscription.query.filter_by(id=subscription_id)\
+ .first()
+
+ assert subscription.notify == False
+
+ notifications = Notification.query.filter_by(
+ user_id=user_id).all()
+
+ # User should not have been notified
+ assert len(notifications) == 1
diff --git a/mediagoblin/tests/test_openid.py b/mediagoblin/tests/test_openid.py
new file mode 100644
index 00000000..23a2290e
--- /dev/null
+++ b/mediagoblin/tests/test_openid.py
@@ -0,0 +1,373 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import urlparse
+import pkg_resources
+import pytest
+import mock
+
+openid_consumer = pytest.importorskip(
+ "openid.consumer.consumer")
+
+from mediagoblin import mg_globals
+from mediagoblin.db.base import Session
+from mediagoblin.db.models import User
+from mediagoblin.plugins.openid.models import OpenIDUserURL
+from mediagoblin.tests.tools import get_app, fixture_add_user
+from mediagoblin.tools import template
+
+# App with plugin enabled
+@pytest.fixture()
+def openid_plugin_app(request):
+ return get_app(
+ request,
+ mgoblin_config=pkg_resources.resource_filename(
+ 'mediagoblin.tests.auth_configs',
+ 'openid_appconfig.ini'))
+
+
+class TestOpenIDPlugin(object):
+ def _setup(self, openid_plugin_app, value=True, edit=False, delete=False):
+ if value:
+ response = openid_consumer.SuccessResponse(mock.Mock(), mock.Mock())
+ if edit or delete:
+ response.identity_url = u'http://add.myopenid.com'
+ else:
+ response.identity_url = u'http://real.myopenid.com'
+ self._finish_verification = mock.Mock(return_value=response)
+ else:
+ self._finish_verification = mock.Mock(return_value=False)
+
+ @mock.patch('mediagoblin.plugins.openid.views._response_email', mock.Mock(return_value=None))
+ @mock.patch('mediagoblin.plugins.openid.views._response_nickname', mock.Mock(return_value=None))
+ @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self._finish_verification)
+ def _setup_start(self, openid_plugin_app, edit, delete):
+ if edit:
+ self._start_verification = mock.Mock(return_value=openid_plugin_app.post(
+ '/edit/openid/finish/'))
+ elif delete:
+ self._start_verification = mock.Mock(return_value=openid_plugin_app.post(
+ '/edit/openid/delete/finish/'))
+ else:
+ self._start_verification = mock.Mock(return_value=openid_plugin_app.post(
+ '/auth/openid/login/finish/'))
+ _setup_start(self, openid_plugin_app, edit, delete)
+
+ def test_bad_login(self, openid_plugin_app):
+ """ Test that attempts to login with invalid paramaters"""
+
+ # Test GET request for auth/register page
+ res = openid_plugin_app.get('/auth/register/').follow()
+
+ # Make sure it redirected to the correct place
+ assert urlparse.urlsplit(res.location)[2] == '/auth/openid/login/'
+
+ # Test GET request for auth/login page
+ res = openid_plugin_app.get('/auth/login/')
+ res.follow()
+
+ # Correct redirect?
+ assert urlparse.urlsplit(res.location)[2] == '/auth/openid/login/'
+
+ # Test GET request for auth/openid/register page
+ res = openid_plugin_app.get('/auth/openid/register/')
+ res.follow()
+
+ # Correct redirect?
+ assert urlparse.urlsplit(res.location)[2] == '/auth/openid/login/'
+
+ # Test GET request for auth/openid/login/finish page
+ res = openid_plugin_app.get('/auth/openid/login/finish/')
+ res.follow()
+
+ # Correct redirect?
+ assert urlparse.urlsplit(res.location)[2] == '/auth/openid/login/'
+
+ # Test GET request for auth/openid/login page
+ res = openid_plugin_app.get('/auth/openid/login/')
+
+ # Correct place?
+ assert 'mediagoblin/plugins/openid/login.html' in template.TEMPLATE_TEST_CONTEXT
+
+ # Try to login with an empty form
+ template.clear_test_template_context()
+ openid_plugin_app.post(
+ '/auth/openid/login/', {})
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/openid/login.html']
+ form = context['login_form']
+ assert form.openid.errors == [u'This field is required.']
+
+ # Try to login with wrong form values
+ template.clear_test_template_context()
+ openid_plugin_app.post(
+ '/auth/openid/login/', {
+ 'openid': 'not_a_url.com'})
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/openid/login.html']
+ form = context['login_form']
+ assert form.openid.errors == [u'Please enter a valid url.']
+
+ # Should be no users in the db
+ assert User.query.count() == 0
+
+ # Phony OpenID URl
+ template.clear_test_template_context()
+ openid_plugin_app.post(
+ '/auth/openid/login/', {
+ 'openid': 'http://phoney.myopenid.com/'})
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/openid/login.html']
+ form = context['login_form']
+ assert form.openid.errors == [u'Sorry, the OpenID server could not be found']
+
+ def test_login(self, openid_plugin_app):
+ """Tests that test login and registion with openid"""
+ # Test finish_login redirects correctly when response = False
+ self._setup(openid_plugin_app, False)
+
+ @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self._finish_verification)
+ @mock.patch('mediagoblin.plugins.openid.views._start_verification', self._start_verification)
+ def _test_non_response():
+ template.clear_test_template_context()
+ res = openid_plugin_app.post(
+ '/auth/openid/login/', {
+ 'openid': 'http://phoney.myopenid.com/'})
+ res.follow()
+
+ # Correct Place?
+ assert urlparse.urlsplit(res.location)[2] == '/auth/openid/login/'
+ assert 'mediagoblin/plugins/openid/login.html' in template.TEMPLATE_TEST_CONTEXT
+ _test_non_response()
+
+ # Test login with new openid
+ # Need to clear_test_template_context before calling _setup
+ template.clear_test_template_context()
+ self._setup(openid_plugin_app)
+
+ @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self._finish_verification)
+ @mock.patch('mediagoblin.plugins.openid.views._start_verification', self._start_verification)
+ def _test_new_user():
+ openid_plugin_app.post(
+ '/auth/openid/login/', {
+ 'openid': u'http://real.myopenid.com'})
+
+ # Right place?
+ assert 'mediagoblin/auth/register.html' in template.TEMPLATE_TEST_CONTEXT
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
+ register_form = context['register_form']
+
+ # Register User
+ res = openid_plugin_app.post(
+ '/auth/openid/register/', {
+ 'openid': register_form.openid.data,
+ 'username': u'chris',
+ 'email': u'chris@example.com'})
+ res.follow()
+
+ # Correct place?
+ assert urlparse.urlsplit(res.location)[2] == '/u/chris/'
+ assert 'mediagoblin/user_pages/user.html' in template.TEMPLATE_TEST_CONTEXT
+
+ # No need to test if user is in logged in and verification email
+ # awaits, since openid uses the register_user function which is
+ # tested in test_auth
+
+ # Logout User
+ openid_plugin_app.get('/auth/logout')
+
+ # Get user and detach from session
+ test_user = mg_globals.database.User.query.filter_by(
+ username=u'chris').first()
+ Session.expunge(test_user)
+
+ # Log back in
+ # Could not get it to work by 'POST'ing to /auth/openid/login/
+ template.clear_test_template_context()
+ res = openid_plugin_app.post(
+ '/auth/openid/login/finish/', {
+ 'openid': u'http://real.myopenid.com'})
+ res.follow()
+
+ assert urlparse.urlsplit(res.location)[2] == '/'
+ assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT
+
+ # Make sure user is in the session
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html']
+ session = context['request'].session
+ assert session['user_id'] == unicode(test_user.id)
+
+ _test_new_user()
+
+ # Test register with empty form
+ template.clear_test_template_context()
+ openid_plugin_app.post(
+ '/auth/openid/register/', {})
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
+ register_form = context['register_form']
+
+ assert register_form.openid.errors == [u'This field is required.']
+ assert register_form.email.errors == [u'This field is required.']
+ assert register_form.username.errors == [u'This field is required.']
+
+ # Try to register with existing username and email
+ template.clear_test_template_context()
+ openid_plugin_app.post(
+ '/auth/openid/register/', {
+ 'openid': 'http://real.myopenid.com',
+ 'email': 'chris@example.com',
+ 'username': 'chris'})
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
+ register_form = context['register_form']
+
+ assert register_form.username.errors == [u'Sorry, a user with that name already exists.']
+ assert register_form.email.errors == [u'Sorry, a user with that email address already exists.']
+ assert register_form.openid.errors == [u'Sorry, an account is already registered to that OpenID.']
+
+ def test_add_delete(self, openid_plugin_app):
+ """Test adding and deleting openids"""
+ # Add user
+ test_user = fixture_add_user(password='')
+ openid = OpenIDUserURL()
+ openid.openid_url = 'http://real.myopenid.com'
+ openid.user_id = test_user.id
+ openid.save()
+
+ # Log user in
+ template.clear_test_template_context()
+ self._setup(openid_plugin_app)
+
+ @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self._finish_verification)
+ @mock.patch('mediagoblin.plugins.openid.views._start_verification', self._start_verification)
+ def _login_user():
+ openid_plugin_app.post(
+ '/auth/openid/login/finish/', {
+ 'openid': u'http://real.myopenid.com'})
+
+ _login_user()
+
+ # Try and delete only OpenID url
+ template.clear_test_template_context()
+ res = openid_plugin_app.post(
+ '/edit/openid/delete/', {
+ 'openid': 'http://real.myopenid.com'})
+ assert 'mediagoblin/plugins/openid/delete.html' in template.TEMPLATE_TEST_CONTEXT
+
+ # Add OpenID to user
+ # Empty form
+ template.clear_test_template_context()
+ res = openid_plugin_app.post(
+ '/edit/openid/', {})
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/openid/add.html']
+ form = context['form']
+ assert form.openid.errors == [u'This field is required.']
+
+ # Try with a bad url
+ template.clear_test_template_context()
+ openid_plugin_app.post(
+ '/edit/openid/', {
+ 'openid': u'not_a_url.com'})
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/openid/add.html']
+ form = context['form']
+ assert form.openid.errors == [u'Please enter a valid url.']
+
+ # Try with a url that's already registered
+ template.clear_test_template_context()
+ openid_plugin_app.post(
+ '/edit/openid/', {
+ 'openid': 'http://real.myopenid.com'})
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/openid/add.html']
+ form = context['form']
+ assert form.openid.errors == [u'Sorry, an account is already registered to that OpenID.']
+
+ # Test adding openid to account
+ # Need to clear_test_template_context before calling _setup
+ template.clear_test_template_context()
+ self._setup(openid_plugin_app, edit=True)
+
+ # Need to remove openid_url from db because it was added at setup
+ openid = OpenIDUserURL.query.filter_by(
+ openid_url=u'http://add.myopenid.com')
+ openid.delete()
+
+ @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self._finish_verification)
+ @mock.patch('mediagoblin.plugins.openid.views._start_verification', self._start_verification)
+ def _test_add():
+ # Successful add
+ template.clear_test_template_context()
+ res = openid_plugin_app.post(
+ '/edit/openid/', {
+ 'openid': u'http://add.myopenid.com'})
+ res.follow()
+
+ # Correct place?
+ assert urlparse.urlsplit(res.location)[2] == '/edit/account/'
+ assert 'mediagoblin/edit/edit_account.html' in template.TEMPLATE_TEST_CONTEXT
+
+ # OpenID Added?
+ new_openid = mg_globals.database.OpenIDUserURL.query.filter_by(
+ openid_url=u'http://add.myopenid.com').first()
+ assert new_openid
+
+ _test_add()
+
+ # Test deleting openid from account
+ # Need to clear_test_template_context before calling _setup
+ template.clear_test_template_context()
+ self._setup(openid_plugin_app, delete=True)
+
+ # Need to add OpenID back to user because it was deleted during
+ # patch
+ openid = OpenIDUserURL()
+ openid.openid_url = 'http://add.myopenid.com'
+ openid.user_id = test_user.id
+ openid.save()
+
+ @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self._finish_verification)
+ @mock.patch('mediagoblin.plugins.openid.views._start_verification', self._start_verification)
+ def _test_delete(self, test_user):
+ # Delete openid from user
+ # Create another user to test deleting OpenID that doesn't belong to them
+ new_user = fixture_add_user(username='newman')
+ openid = OpenIDUserURL()
+ openid.openid_url = 'http://realfake.myopenid.com/'
+ openid.user_id = new_user.id
+ openid.save()
+
+ # Try and delete OpenID url that isn't the users
+ template.clear_test_template_context()
+ res = openid_plugin_app.post(
+ '/edit/openid/delete/', {
+ 'openid': 'http://realfake.myopenid.com/'})
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/openid/delete.html']
+ form = context['form']
+ assert form.openid.errors == [u'That OpenID is not registered to this account.']
+
+ # Delete OpenID
+ # Kind of weird to POST to delete/finish
+ template.clear_test_template_context()
+ res = openid_plugin_app.post(
+ '/edit/openid/delete/finish/', {
+ 'openid': u'http://add.myopenid.com'})
+ res.follow()
+
+ # Correct place?
+ assert urlparse.urlsplit(res.location)[2] == '/edit/account/'
+ assert 'mediagoblin/edit/edit_account.html' in template.TEMPLATE_TEST_CONTEXT
+
+ # OpenID deleted?
+ new_openid = mg_globals.database.OpenIDUserURL.query.filter_by(
+ openid_url=u'http://add.myopenid.com').first()
+ assert not new_openid
+
+ _test_delete(self, test_user)
diff --git a/mediagoblin/tests/test_paste.ini b/mediagoblin/tests/test_paste.ini
index 91ecbb84..a9595432 100644
--- a/mediagoblin/tests/test_paste.ini
+++ b/mediagoblin/tests/test_paste.ini
@@ -6,6 +6,8 @@ use = egg:Paste#urlmap
/ = mediagoblin
/mgoblin_media/ = publicstore_serve
/test_static/ = mediagoblin_static
+/theme_static/ = theme_static
+/plugin_static/ = plugin_static
[app:mediagoblin]
use = egg:mediagoblin#app
@@ -13,12 +15,22 @@ config = %(here)s/mediagoblin.ini
[app:publicstore_serve]
use = egg:Paste#static
-document_root = %(here)s/test_user_dev/media/public
+document_root = %(here)s/user_dev/media/public
[app:mediagoblin_static]
use = egg:Paste#static
document_root = %(here)s/mediagoblin/static/
+[app:theme_static]
+use = egg:Paste#static
+document_root = %(here)s/user_dev/theme_static/
+cache_max_age = 86400
+
+[app:plugin_static]
+use = egg:Paste#static
+document_root = %(here)s/user_dev/plugin_static/
+cache_max_age = 86400
+
[celery]
CELERY_ALWAYS_EAGER = true
diff --git a/mediagoblin/tests/test_piwigo.py b/mediagoblin/tests/test_piwigo.py
index 18f95057..16ad0111 100644
--- a/mediagoblin/tests/test_piwigo.py
+++ b/mediagoblin/tests/test_piwigo.py
@@ -44,11 +44,13 @@ class Test_PWG(object):
def test_session(self):
resp = self.do_post("pwg.session.login",
{"username": u"nouser", "password": "wrong"})
- assert resp.body == XML_PREFIX + '<rsp stat="ok">0</rsp>'
+ assert resp.body == XML_PREFIX \
+ + '<rsp stat="fail"><err code="999" msg="Invalid username/password"/></rsp>'
resp = self.do_post("pwg.session.login",
{"username": self.username, "password": "wrong"})
- assert resp.body == XML_PREFIX + '<rsp stat="ok">0</rsp>'
+ assert resp.body == XML_PREFIX \
+ + '<rsp stat="fail"><err code="999" msg="Invalid username/password"/></rsp>'
resp = self.do_get("pwg.session.getStatus")
assert resp.body == XML_PREFIX \
@@ -56,7 +58,7 @@ class Test_PWG(object):
resp = self.do_post("pwg.session.login",
{"username": self.username, "password": self.password})
- assert resp.body == XML_PREFIX + '<rsp stat="ok">1</rsp>'
+ assert resp.body == XML_PREFIX + '<rsp stat="ok">1</rsp>'
resp = self.do_get("pwg.session.getStatus")
assert resp.body == XML_PREFIX \
diff --git a/mediagoblin/tests/test_pluginapi.py b/mediagoblin/tests/test_pluginapi.py
index 809b5ce9..eae0ce15 100644
--- a/mediagoblin/tests/test_pluginapi.py
+++ b/mediagoblin/tests/test_pluginapi.py
@@ -14,6 +14,8 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import os
+import json
import sys
from configobj import ConfigObj
@@ -24,7 +26,10 @@ from validate import VdtTypeError
from mediagoblin import mg_globals
from mediagoblin.init.plugins import setup_plugins
from mediagoblin.init.config import read_mediagoblin_config
+from mediagoblin.gmg_commands.assetlink import link_plugin_assets
from mediagoblin.tools import pluginapi
+from mediagoblin.tests.tools import get_app
+from mediagoblin.tools.common import CollectingPrinter
def with_cleanup(*modules_to_delete):
@@ -323,3 +328,139 @@ def test_plugin_config():
# the callables thing shouldn't really have anything though.
assert len(config['plugins'][
'mediagoblin.tests.testplugins.callables1']) == 0
+
+
+@pytest.fixture()
+def context_modified_app(request):
+ """
+ Get a MediaGoblin app fixture using appconfig_context_modified.ini
+ """
+ return get_app(
+ request,
+ mgoblin_config=pkg_resources.resource_filename(
+ 'mediagoblin.tests', 'appconfig_context_modified.ini'))
+
+
+def test_modify_context(context_modified_app):
+ """
+ Test that we can modify both the view/template specific and
+ global contexts for templates.
+ """
+ # Specific thing passed into a page
+ result = context_modified_app.get("/modify_context/specific/")
+ assert result.body.strip() == """Specific page!
+
+specific thing: in yer specificpage
+global thing: globally appended!
+something: orother
+doubleme: happyhappy"""
+
+ # General test, should have global context variable only
+ result = context_modified_app.get("/modify_context/")
+ assert result.body.strip() == """General page!
+
+global thing: globally appended!
+lol: cats
+doubleme: joyjoy"""
+
+
+@pytest.fixture()
+def static_plugin_app(request):
+ """
+ Get a MediaGoblin app fixture using appconfig_static_plugin.ini
+ """
+ return get_app(
+ request,
+ mgoblin_config=pkg_resources.resource_filename(
+ 'mediagoblin.tests', 'appconfig_static_plugin.ini'))
+
+
+def test_plugin_assetlink(static_plugin_app):
+ """
+ Test that the assetlink command works correctly
+ """
+ linked_assets_dir = mg_globals.app_config['plugin_linked_assets_dir']
+ plugin_link_dir = os.path.join(
+ linked_assets_dir.rstrip(os.path.sep),
+ 'staticstuff')
+
+ plugin_statics = pluginapi.hook_runall("static_setup")
+ assert len(plugin_statics) == 1
+ plugin_static = plugin_statics[0]
+
+ def run_assetlink():
+ printer = CollectingPrinter()
+
+ link_plugin_assets(
+ plugin_static, linked_assets_dir, printer)
+
+ return printer
+
+ # it shouldn't exist yet
+ assert not os.path.lexists(plugin_link_dir)
+
+ # link dir doesn't exist, link it
+ result = run_assetlink().collection[0]
+ assert result == \
+ 'Linked asset directory for plugin "staticstuff":\n %s\nto:\n %s\n' % (
+ plugin_static.file_path.rstrip(os.path.sep),
+ plugin_link_dir)
+ assert os.path.lexists(plugin_link_dir)
+ assert os.path.islink(plugin_link_dir)
+ assert os.path.realpath(plugin_link_dir) == plugin_static.file_path
+
+ # link dir exists, leave it alone
+ # (and it should exist still since we just ran it..)
+ result = run_assetlink().collection[0]
+ assert result == 'Skipping "staticstuff"; already set up.\n'
+ assert os.path.lexists(plugin_link_dir)
+ assert os.path.islink(plugin_link_dir)
+ assert os.path.realpath(plugin_link_dir) == plugin_static.file_path
+
+ # link dir exists, is a symlink to somewhere else (re-link)
+ junk_file_path = os.path.join(
+ linked_assets_dir.rstrip(os.path.sep),
+ 'junk.txt')
+ with file(junk_file_path, 'w') as junk_file:
+ junk_file.write('barf')
+
+ os.unlink(plugin_link_dir)
+ os.symlink(junk_file_path, plugin_link_dir)
+
+ result = run_assetlink().combined_string
+ assert result == """Old link found for "staticstuff"; removing.
+Linked asset directory for plugin "staticstuff":
+ %s
+to:
+ %s
+""" % (plugin_static.file_path.rstrip(os.path.sep), plugin_link_dir)
+ assert os.path.lexists(plugin_link_dir)
+ assert os.path.islink(plugin_link_dir)
+ assert os.path.realpath(plugin_link_dir) == plugin_static.file_path
+
+ # link dir exists, but is a non-symlink
+ os.unlink(plugin_link_dir)
+ with file(plugin_link_dir, 'w') as clobber_file:
+ clobber_file.write('clobbered!')
+
+ result = run_assetlink().collection[0]
+ assert result == 'Could not link "staticstuff": %s exists and is not a symlink\n' % (
+ plugin_link_dir)
+
+ with file(plugin_link_dir, 'r') as clobber_file:
+ assert clobber_file.read() == 'clobbered!'
+
+
+def test_plugin_staticdirect(static_plugin_app):
+ """
+ Test that the staticdirect utilities pull up the right things
+ """
+ result = json.loads(
+ static_plugin_app.get('/staticstuff/').body)
+
+ assert len(result) == 2
+
+ assert result['mgoblin_bunny_pic'] == '/test_static/images/bunny_pic.png'
+ assert result['plugin_bunny_css'] == \
+ '/plugin_static/staticstuff/css/bunnify.css'
+
diff --git a/mediagoblin/tests/test_submission.py b/mediagoblin/tests/test_submission.py
index 162b2d19..ac941063 100644
--- a/mediagoblin/tests/test_submission.py
+++ b/mediagoblin/tests/test_submission.py
@@ -26,7 +26,7 @@ from mediagoblin.tests.tools import fixture_add_user
from mediagoblin import mg_globals
from mediagoblin.db.models import MediaEntry
from mediagoblin.tools import template
-from mediagoblin.media_types.image import MEDIA_MANAGER as img_MEDIA_MANAGER
+from mediagoblin.media_types.image import ImageMediaManager
from mediagoblin.media_types.pdf.processing import check_prerequisites as pdf_check_prerequisites
from .resources import GOOD_JPG, GOOD_PNG, EVIL_FILE, EVIL_JPG, EVIL_PNG, \
@@ -77,7 +77,7 @@ class TestSubmission:
return {'upload_files': [('file', filename)]}
def check_comments(self, request, media_id, count):
- comments = request.db.MediaComment.find({'media_entry': media_id})
+ comments = request.db.MediaComment.query.filter_by(media_entry=media_id)
assert count == len(list(comments))
def test_missing_fields(self):
@@ -122,7 +122,7 @@ class TestSubmission:
assert 'mediagoblin/user_pages/user.html' in context
def check_media(self, request, find_data, count=None):
- media = MediaEntry.find(find_data)
+ media = MediaEntry.query.filter_by(**find_data)
if count is not None:
assert media.count() == count
if count == 0:
@@ -219,7 +219,7 @@ class TestSubmission:
media = self.check_media(request, {'title': u'Balanced Goblin'}, 1)
assert media.media_type == u'mediagoblin.media_types.image'
- assert isinstance(media.media_manager, img_MEDIA_MANAGER)
+ assert isinstance(media.media_manager, ImageMediaManager)
assert media.media_manager.entry == media
@@ -240,8 +240,8 @@ class TestSubmission:
request = context['request']
- media = request.db.MediaEntry.find_one({
- u'title': u'UNIQUE_TITLE_PLS_DONT_CREATE_OTHER_MEDIA_WITH_THIS_TITLE'})
+ media = request.db.MediaEntry.query.filter_by(
+ title=u'UNIQUE_TITLE_PLS_DONT_CREATE_OTHER_MEDIA_WITH_THIS_TITLE').first()
assert media.media_type == 'mediagoblin.media_types.image'
@@ -252,7 +252,7 @@ class TestSubmission:
response, context = self.do_post({'title': title}, do_follow=True,
**self.upload_data(filename))
self.check_url(response, '/u/{0}/'.format(self.test_user.username))
- entry = mg_globals.database.MediaEntry.find_one({'title': title})
+ entry = mg_globals.database.MediaEntry.query.filter_by(title=title).first()
assert entry.state == 'failed'
assert entry.fail_error == u'mediagoblin.processing:BadMediaFail'
diff --git a/mediagoblin/tests/testplugins/modify_context/__init__.py b/mediagoblin/tests/testplugins/modify_context/__init__.py
new file mode 100644
index 00000000..164e66c1
--- /dev/null
+++ b/mediagoblin/tests/testplugins/modify_context/__init__.py
@@ -0,0 +1,55 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+from mediagoblin.tools import pluginapi
+import pkg_resources
+
+
+def append_to_specific_context(context):
+ context['specific_page_append'] = 'in yer specificpage'
+ return context
+
+def append_to_global_context(context):
+ context['global_append'] = 'globally appended!'
+ return context
+
+def double_doubleme(context):
+ if 'doubleme' in context:
+ context['doubleme'] = context['doubleme'] * 2
+ return context
+
+
+def setup_plugin():
+ routes = [
+ ('modify_context.specific_page',
+ '/modify_context/specific/',
+ 'mediagoblin.tests.testplugins.modify_context.views:specific'),
+ ('modify_context.general_page',
+ '/modify_context/',
+ 'mediagoblin.tests.testplugins.modify_context.views:general')]
+
+ pluginapi.register_routes(routes)
+ pluginapi.register_template_path(
+ pkg_resources.resource_filename(
+ 'mediagoblin.tests.testplugins.modify_context', 'templates'))
+
+
+hooks = {
+ 'setup': setup_plugin,
+ ('modify_context.specific_page',
+ 'contextplugin/specific.html'): append_to_specific_context,
+ 'template_global_context': append_to_global_context,
+ 'template_context_prerender': double_doubleme}
diff --git a/mediagoblin/tests/testplugins/modify_context/templates/contextplugin/general.html b/mediagoblin/tests/testplugins/modify_context/templates/contextplugin/general.html
new file mode 100644
index 00000000..9cf96d3e
--- /dev/null
+++ b/mediagoblin/tests/testplugins/modify_context/templates/contextplugin/general.html
@@ -0,0 +1,5 @@
+General page!
+
+global thing: {{ global_append }}
+lol: {{ lol }}
+doubleme: {{ doubleme }}
diff --git a/mediagoblin/tests/testplugins/modify_context/templates/contextplugin/specific.html b/mediagoblin/tests/testplugins/modify_context/templates/contextplugin/specific.html
new file mode 100644
index 00000000..5b1b4c4a
--- /dev/null
+++ b/mediagoblin/tests/testplugins/modify_context/templates/contextplugin/specific.html
@@ -0,0 +1,6 @@
+Specific page!
+
+specific thing: {{ specific_page_append }}
+global thing: {{ global_append }}
+something: {{ something }}
+doubleme: {{ doubleme }}
diff --git a/mediagoblin/tests/testplugins/modify_context/views.py b/mediagoblin/tests/testplugins/modify_context/views.py
new file mode 100644
index 00000000..701ec6f9
--- /dev/null
+++ b/mediagoblin/tests/testplugins/modify_context/views.py
@@ -0,0 +1,33 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+from mediagoblin.tools.response import render_to_response
+
+
+def specific(request):
+ return render_to_response(
+ request,
+ 'contextplugin/specific.html',
+ {"something": "orother",
+ "doubleme": "happy"})
+
+
+def general(request):
+ return render_to_response(
+ request,
+ 'contextplugin/general.html',
+ {"lol": "cats",
+ "doubleme": "joy"})
diff --git a/mediagoblin/tests/testplugins/staticstuff/__init__.py b/mediagoblin/tests/testplugins/staticstuff/__init__.py
new file mode 100644
index 00000000..a2591646
--- /dev/null
+++ b/mediagoblin/tests/testplugins/staticstuff/__init__.py
@@ -0,0 +1,36 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+from mediagoblin.tools.staticdirect import PluginStatic
+from mediagoblin.tools import pluginapi
+from pkg_resources import resource_filename
+
+def setup_plugin():
+ routes = [
+ ('staticstuff.static_demo',
+ '/staticstuff/',
+ 'mediagoblin.tests.testplugins.staticstuff.views:static_demo')]
+
+ pluginapi.register_routes(routes)
+
+
+hooks = {
+ 'setup': setup_plugin,
+ 'static_setup': lambda: PluginStatic(
+ 'staticstuff',
+ resource_filename(
+ 'mediagoblin.tests.testplugins.staticstuff',
+ 'static'))}
diff --git a/mediagoblin/tests/testplugins/staticstuff/static/css/bunnify.css b/mediagoblin/tests/testplugins/staticstuff/static/css/bunnify.css
new file mode 100644
index 00000000..1294ab8a
--- /dev/null
+++ b/mediagoblin/tests/testplugins/staticstuff/static/css/bunnify.css
@@ -0,0 +1,4 @@
+body {
+ background-color: #5edcf1;
+ color: #eb8add;
+} \ No newline at end of file
diff --git a/mediagoblin/tests/testplugins/staticstuff/views.py b/mediagoblin/tests/testplugins/staticstuff/views.py
new file mode 100644
index 00000000..34a5e8cb
--- /dev/null
+++ b/mediagoblin/tests/testplugins/staticstuff/views.py
@@ -0,0 +1,28 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import json
+
+from werkzeug import Response
+
+
+def static_demo(request):
+ return Response(json.dumps({
+ # this does not exist, but we'll pretend it does ;)
+ 'mgoblin_bunny_pic': request.staticdirect(
+ 'images/bunny_pic.png'),
+ 'plugin_bunny_css': request.staticdirect(
+ 'css/bunnify.css', 'staticstuff')}))
diff --git a/mediagoblin/tests/tools.py b/mediagoblin/tests/tools.py
index 794ed940..98361adc 100644
--- a/mediagoblin/tests/tools.py
+++ b/mediagoblin/tests/tools.py
@@ -15,23 +15,22 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import sys
import os
import pkg_resources
import shutil
-from functools import wraps
from paste.deploy import loadapp
from webtest import TestApp
from mediagoblin import mg_globals
-from mediagoblin.db.models import User, MediaEntry, Collection
+from mediagoblin.db.models import User, MediaEntry, Collection, MediaComment, \
+ CommentSubscription, CommentNotification
from mediagoblin.tools import testing
from mediagoblin.init.config import read_mediagoblin_config
from mediagoblin.db.base import Session
from mediagoblin.meddleware import BaseMeddleware
-from mediagoblin.auth.lib import bcrypt_gen_password_hash
+from mediagoblin.auth import gen_password_hash
from mediagoblin.gmg_commands.dbupdate import run_dbupdate
@@ -40,8 +39,6 @@ TEST_SERVER_CONFIG = pkg_resources.resource_filename(
'mediagoblin.tests', 'test_paste.ini')
TEST_APP_CONFIG = pkg_resources.resource_filename(
'mediagoblin.tests', 'test_mgoblin_app.ini')
-TEST_USER_DEV = pkg_resources.resource_filename(
- 'mediagoblin.tests', 'test_user_dev')
USER_DEV_DIRECTORIES_TO_SETUP = ['media/public', 'media/queue']
@@ -103,7 +100,7 @@ def get_app(request, paste_config=None, mgoblin_config=None):
# This is the directory we're copying the paste/mgoblin config stuff into
run_dir = request.config._tmpdirhandler.mktemp(
'mgoblin_app', numbered=True)
- user_dev_dir = run_dir.mkdir('test_user_dev').strpath
+ user_dev_dir = run_dir.mkdir('user_dev').strpath
new_paste_config = run_dir.join('paste.ini').strpath
new_mgoblin_config = run_dir.join('mediagoblin.ini').strpath
@@ -167,13 +164,13 @@ def assert_db_meets_expected(db, expected):
for collection_name, collection_data in expected.iteritems():
collection = db[collection_name]
for expected_document in collection_data:
- document = collection.find_one({'id': expected_document['id']})
+ document = collection.query.filter_by(id=expected_document['id']).first()
assert document is not None # make sure it exists
assert document == expected_document # make sure it matches
def fixture_add_user(username=u'chris', password=u'toast',
- active_user=True):
+ active_user=True, wants_comment_notification=True):
# Reuse existing user or create a new one
test_user = User.query.filter_by(username=username).first()
if test_user is None:
@@ -181,11 +178,13 @@ def fixture_add_user(username=u'chris', password=u'toast',
test_user.username = username
test_user.email = username + u'@example.com'
if password is not None:
- test_user.pw_hash = bcrypt_gen_password_hash(password)
+ test_user.pw_hash = gen_password_hash(password)
if active_user:
test_user.email_verified = True
test_user.status = u'active'
+ test_user.wants_comment_notification = wants_comment_notification
+
test_user.save()
# Reload
@@ -197,19 +196,79 @@ def fixture_add_user(username=u'chris', password=u'toast',
return test_user
+def fixture_comment_subscription(entry, notify=True, send_email=None):
+ if send_email is None:
+ uploader = User.query.filter_by(id=entry.uploader).first()
+ send_email = uploader.wants_comment_notification
+
+ cs = CommentSubscription(
+ media_entry_id=entry.id,
+ user_id=entry.uploader,
+ notify=notify,
+ send_email=send_email)
+
+ cs.save()
+
+ cs = CommentSubscription.query.filter_by(id=cs.id).first()
+
+ Session.expunge(cs)
+
+ return cs
+
+
+def fixture_add_comment_notification(entry_id, subject_id, user_id,
+ seen=False):
+ cn = CommentNotification(user_id=user_id,
+ seen=seen,
+ subject_id=subject_id)
+ cn.save()
+
+ cn = CommentNotification.query.filter_by(id=cn.id).first()
+
+ Session.expunge(cn)
+
+ return cn
+
+
def fixture_media_entry(title=u"Some title", slug=None,
- uploader=None, save=True, gen_slug=True):
+ uploader=None, save=True, gen_slug=True,
+ state=u'unprocessed', fake_upload=True,
+ expunge=True):
+ """
+ Add a media entry for testing purposes.
+
+ Caution: if you're adding multiple entries with fake_upload=True,
+ make sure you save between them... otherwise you'll hit an
+ IntegrityError from multiple newly-added-MediaEntries adding
+ FileKeynames at once. :)
+ """
+ if uploader is None:
+ uploader = fixture_add_user().id
+
entry = MediaEntry()
entry.title = title
entry.slug = slug
- entry.uploader = uploader or fixture_add_user().id
+ entry.uploader = uploader
entry.media_type = u'image'
+ entry.state = state
+
+ if fake_upload:
+ entry.media_files = {'thumb': ['a', 'b', 'c.jpg'],
+ 'medium': ['d', 'e', 'f.png'],
+ 'original': ['g', 'h', 'i.png']}
+ entry.media_type = u'mediagoblin.media_types.image'
if gen_slug:
entry.generate_slug()
+
if save:
entry.save()
+ if expunge:
+ entry = MediaEntry.query.filter_by(id=entry.id).first()
+
+ Session.expunge(entry)
+
return entry
@@ -232,3 +291,26 @@ def fixture_add_collection(name=u"My first Collection", user=None):
Session.expunge(coll)
return coll
+
+def fixture_add_comment(author=None, media_entry=None, comment=None):
+ if author is None:
+ author = fixture_add_user().id
+
+ if media_entry is None:
+ media_entry = fixture_media_entry().id
+
+ if comment is None:
+ comment = \
+ 'Auto-generated test comment by user #{0} on media #{0}'.format(
+ author, media_entry)
+
+ comment = MediaComment(author=author,
+ media_entry=media_entry,
+ content=comment)
+
+ comment.save()
+
+ Session.expunge(comment)
+
+ return comment
+
diff --git a/mediagoblin/tools/exif.py b/mediagoblin/tools/exif.py
index d0f9d0a6..6b3639e8 100644
--- a/mediagoblin/tools/exif.py
+++ b/mediagoblin/tools/exif.py
@@ -134,7 +134,7 @@ def _ratio_to_list(ratio):
def get_useful(tags):
- return dict((key, tag) for (key, tag) in tags.iteritems() if key in USEFUL_TAGS)
+ return dict((key, tag) for (key, tag) in tags.iteritems())
def get_gps_data(tags):
diff --git a/mediagoblin/tools/mail.py b/mediagoblin/tools/mail.py
index 4fa02ce5..0fabc5a9 100644
--- a/mediagoblin/tools/mail.py
+++ b/mediagoblin/tools/mail.py
@@ -16,7 +16,7 @@
import smtplib
from email.MIMEText import MIMEText
-from mediagoblin import mg_globals
+from mediagoblin import mg_globals, messages
from mediagoblin.tools import common
### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -90,7 +90,12 @@ def send_email(from_addr, to_addrs, subject, message_body):
if common.TESTS_ENABLED or mg_globals.app_config['email_debug_mode']:
mhost = FakeMhost()
elif not mg_globals.app_config['email_debug_mode']:
- mhost = smtplib.SMTP(
+ if mg_globals.app_config['email_smtp_use_ssl']:
+ smtp_init = smtplib.SMTP_SSL
+ else:
+ smtp_init = smtplib.SMTP
+
+ mhost = smtp_init(
mg_globals.app_config['email_smtp_host'],
mg_globals.app_config['email_smtp_port'])
@@ -135,3 +140,16 @@ def normalize_email(email):
return None
email = "@".join((em_user, em_dom.lower()))
return email
+
+
+def email_debug_message(request):
+ """
+ If the server is running in email debug mode (which is
+ the current default), give a debug message to the user
+ so that they have an idea where to find their email.
+ """
+ if mg_globals.app_config['email_debug_mode']:
+ # DEBUG message, no need to translate
+ messages.add_message(request, messages.DEBUG,
+ u"This instance is running in email debug mode. "
+ u"The email will be on the console of the server process.")
diff --git a/mediagoblin/tools/response.py b/mediagoblin/tools/response.py
index aaf31d0b..0be1f835 100644
--- a/mediagoblin/tools/response.py
+++ b/mediagoblin/tools/response.py
@@ -77,7 +77,7 @@ def render_http_exception(request, exc, description):
elif stock_desc and exc.code == 404:
return render_404(request)
- return render_error(request, title=exc.args[0],
+ return render_error(request, title='{0} {1}'.format(exc.code, exc.name),
err_msg=description,
status=exc.code)
diff --git a/mediagoblin/tools/session.py b/mediagoblin/tools/session.py
index fdc32523..a57f69cc 100644
--- a/mediagoblin/tools/session.py
+++ b/mediagoblin/tools/session.py
@@ -17,10 +17,12 @@
import itsdangerous
import logging
-import crypto
+from mediagoblin.tools import crypto
_log = logging.getLogger(__name__)
+MAX_AGE = 30 * 24 * 60 * 60
+
class Session(dict):
def __init__(self, *args, **kwargs):
self.send_new_cookie = False
@@ -64,5 +66,10 @@ class SessionManager(object):
elif not session:
response.delete_cookie(self.cookie_name)
else:
+ if session.get('stay_logged_in', False):
+ max_age = MAX_AGE
+ else:
+ max_age = None
+
response.set_cookie(self.cookie_name, self.signer.dumps(session),
- httponly=True)
+ max_age=max_age, httponly=True)
diff --git a/mediagoblin/tools/staticdirect.py b/mediagoblin/tools/staticdirect.py
index 31abc566..ef8b20d0 100644
--- a/mediagoblin/tools/staticdirect.py
+++ b/mediagoblin/tools/staticdirect.py
@@ -61,3 +61,41 @@ class StaticDirect(object):
def get(self, filepath, domain=None):
return '%s/%s' % (
self.domains[domain], filepath.lstrip('/'))
+
+
+class PluginStatic(object):
+ """Pass this into the ``'static_setup'`` hook to register your
+ plugin's static directory.
+
+ This has two mandatory attributes that you must pass in on class
+ init:
+ - name: this name will be both used for lookup in "urlgen" for
+ your plugin's static resources and for the subdirectory that
+ it'll be "mounted" to for serving via your web browser. It
+ *MUST* be unique. If writing a plugin bundled with MediaGoblin
+ please use the pattern 'coreplugin__foo' where 'foo' is your
+ plugin name. All external plugins should use their modulename,
+ so if your plugin is 'mg_bettertags' you should also call this
+ name 'mg_bettertags'.
+ - file_path: the directory your plugin's static resources are
+ located in. It's recommended that you use
+ pkg_resources.resource_filename() for this.
+
+ An example of using this::
+
+ from pkg_resources import resource_filename
+ from mediagoblin.tools.staticdirect import PluginStatic
+
+ hooks = {
+ 'static_setup': lambda: PluginStatic(
+ 'mg_bettertags',
+ resource_filename('mg_bettertags', 'static'))
+ }
+
+ """
+ def __init__(self, name, file_path):
+ self.name = name
+ self.file_path = file_path
+
+ def __call__(self):
+ return self
diff --git a/mediagoblin/tools/template.py b/mediagoblin/tools/template.py
index 54aeac92..615ce129 100644
--- a/mediagoblin/tools/template.py
+++ b/mediagoblin/tools/template.py
@@ -27,7 +27,7 @@ from mediagoblin import messages
from mediagoblin import _version
from mediagoblin.tools import common
from mediagoblin.tools.translate import set_thread_locale
-from mediagoblin.tools.pluginapi import get_hook_templates
+from mediagoblin.tools.pluginapi import get_hook_templates, hook_transform
from mediagoblin.tools.timesince import timesince
from mediagoblin.meddleware.csrf import render_csrf_form_token
@@ -71,6 +71,7 @@ def get_jinja_env(template_loader, locale):
template_env.globals['app_config'] = mg_globals.app_config
template_env.globals['global_config'] = mg_globals.global_config
template_env.globals['version'] = _version.__version__
+ template_env.globals['auth'] = mg_globals.app.auth
template_env.filters['urlencode'] = url_quote_plus
@@ -80,6 +81,9 @@ def get_jinja_env(template_loader, locale):
# allow for hooking up plugin templates
template_env.globals['get_hook_templates'] = get_hook_templates
+ template_env.globals = hook_transform(
+ 'template_global_context', template_env.globals)
+
if exists(locale):
SETUP_JINJA_ENVS[locale] = template_env
@@ -103,6 +107,20 @@ def render_template(request, template_path, context):
rendered_csrf_token = render_csrf_form_token(request)
if rendered_csrf_token is not None:
context['csrf_token'] = render_csrf_form_token(request)
+
+ # allow plugins to do things to the context
+ if request.controller_name:
+ context = hook_transform(
+ (request.controller_name, template_path),
+ context)
+
+ # More evil: allow plugins to possibly do something to the context
+ # in every request ever with access to the request and other
+ # variables. Note: this is slower than using
+ # template_global_context
+ context = hook_transform(
+ 'template_context_prerender', context)
+
rendered = template.render(context)
if common.TESTS_ENABLED:
diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py
index 738cc054..596d4c20 100644
--- a/mediagoblin/user_pages/views.py
+++ b/mediagoblin/user_pages/views.py
@@ -25,8 +25,9 @@ from mediagoblin.tools.response import render_to_response, render_404, \
from mediagoblin.tools.translate import pass_to_ugettext as _
from mediagoblin.tools.pagination import Pagination
from mediagoblin.user_pages import forms as user_forms
-from mediagoblin.user_pages.lib import (send_comment_email,
- add_media_to_collection)
+from mediagoblin.user_pages.lib import add_media_to_collection
+from mediagoblin.notifications import trigger_notification, \
+ add_comment_subscription, mark_comment_notification_seen
from mediagoblin.decorators import (uses_pagination, get_user_media_entry,
get_media_entry_by_id,
@@ -34,6 +35,7 @@ from mediagoblin.decorators import (uses_pagination, get_user_media_entry,
get_user_collection, get_user_collection_item, active_user_from_url)
from werkzeug.contrib.atom import AtomFeed
+from werkzeug.exceptions import MethodNotAllowed
_log = logging.getLogger(__name__)
@@ -110,6 +112,7 @@ def user_gallery(request, page, url_user=None):
'media_entries': media_entries,
'pagination': pagination})
+
MEDIA_COMMENTS_PER_PAGE = 50
@@ -121,6 +124,9 @@ def media_home(request, media, page, **kwargs):
"""
comment_id = request.matchdict.get('comment', None)
if comment_id:
+ if request.user:
+ mark_comment_notification_seen(comment_id, request.user)
+
pagination = Pagination(
page, media.get_comments(
mg_globals.app_config['comments_ascending']),
@@ -136,7 +142,7 @@ def media_home(request, media, page, **kwargs):
comment_form = user_forms.MediaCommentForm(request.form)
- media_template_name = media.media_manager['display_template']
+ media_template_name = media.media_manager.display_template
return render_to_response(
request,
@@ -154,7 +160,8 @@ def media_post_comment(request, media):
"""
recieves POST from a MediaEntry() comment form, saves the comment.
"""
- assert request.method == 'POST'
+ if not request.method == 'POST':
+ raise MethodNotAllowed()
comment = request.db.MediaComment()
comment.media_entry = media.id
@@ -179,11 +186,9 @@ def media_post_comment(request, media):
request, messages.SUCCESS,
_('Your comment has been posted!'))
- media_uploader = media.get_uploader
- #don't send email if you comment on your own post
- if (comment.author != media_uploader and
- media_uploader.wants_comment_notification):
- send_comment_email(media_uploader, comment, media, request)
+ trigger_notification(comment, media, request)
+
+ add_comment_subscription(request.user, media)
return redirect_obj(request, media)
diff --git a/paste.ini b/paste.ini
index 4c6397fa..3c7eb177 100644
--- a/paste.ini
+++ b/paste.ini
@@ -14,6 +14,7 @@ use = egg:Paste#urlmap
/mgoblin_media/ = publicstore_serve
/mgoblin_static/ = mediagoblin_static
/theme_static/ = theme_static
+/plugin_static/ = plugin_static
[app:mediagoblin]
use = egg:mediagoblin#app
@@ -56,6 +57,11 @@ use = egg:Paste#static
document_root = %(here)s/user_dev/theme_static/
cache_max_age = 86400
+[app:plugin_static]
+use = egg:Paste#static
+document_root = %(here)s/user_dev/plugin_static/
+cache_max_age = 86400
+
[filter:errors]
use = egg:mediagoblin#errors
debug = false
diff --git a/setup.py b/setup.py
index 312de2f8..14a9a24f 100644
--- a/setup.py
+++ b/setup.py
@@ -45,19 +45,19 @@ setup(
'PasteScript',
'wtforms',
'py-bcrypt',
- 'pytest',
+ 'pytest>=2.3.1',
'pytest-xdist',
'werkzeug>=0.7',
'celery==2.5.3',
'kombu==2.1.7',
'jinja2',
'sphinx',
- 'Babel',
+ 'Babel<1.0',
'argparse',
'webtest<2',
'ConfigObj',
'Markdown',
- 'sqlalchemy>=0.7.0',
+ 'sqlalchemy>=0.8.0',
'sqlalchemy-migrate',
'mock',
'itsdangerous',