aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AUTHORS4
-rw-r--r--MANIFEST.in1
-rw-r--r--docs/source/plugindocs/trim_whitespace.rst1
-rw-r--r--docs/source/siteadmin/codebase.rst2
-rw-r--r--docs/source/siteadmin/deploying.rst6
-rw-r--r--docs/source/siteadmin/media-types.rst49
-rw-r--r--docs/source/siteadmin/relnotes.rst93
-rwxr-xr-xextlib/exif/EXIF.py219
-rw-r--r--extlib/exif/changes.txt131
-rw-r--r--extlib/thingiview.js/LICENSE165
-rw-r--r--extlib/thingiview.js/Three.js202
-rw-r--r--extlib/thingiview.js/binaryReader.js126
-rw-r--r--extlib/thingiview.js/plane.js62
-rw-r--r--extlib/thingiview.js/stats.js2
-rw-r--r--extlib/thingiview.js/thingiloader.js318
-rw-r--r--extlib/thingiview.js/thingiview.js898
-rw-r--r--extlib/video-js/LGPLv3-LICENSE.txt165
-rw-r--r--extlib/video-js/demo.html23
-rw-r--r--extlib/video-js/video-js.css427
-rw-r--r--extlib/video-js/video-js.min.css2
-rw-r--r--extlib/video-js/video-js.pngbin7460 -> 8235 bytes
-rw-r--r--extlib/video-js/video-js.swfbin9612 -> 0 bytes
-rw-r--r--extlib/video-js/video.js3744
-rw-r--r--extlib/video-js/video.min.js4
-rw-r--r--mediagoblin/_version.py2
-rw-r--r--mediagoblin/admin/views.py21
-rw-r--r--mediagoblin/app.py74
-rw-r--r--mediagoblin/auth/lib.py4
-rw-r--r--mediagoblin/auth/views.py45
-rw-r--r--mediagoblin/config_spec.ini3
-rw-r--r--mediagoblin/db/__init__.py12
-rw-r--r--mediagoblin/db/base.py (renamed from mediagoblin/db/sql/base.py)37
-rw-r--r--mediagoblin/db/extratypes.py (renamed from mediagoblin/db/sql/extratypes.py)0
-rw-r--r--mediagoblin/db/migration_tools.py (renamed from mediagoblin/db/sql/util.py)73
-rw-r--r--mediagoblin/db/migrations.py (renamed from mediagoblin/db/sql/migrations.py)76
-rw-r--r--mediagoblin/db/mixin.py35
-rw-r--r--mediagoblin/db/models.py (renamed from mediagoblin/db/sql/models.py)98
-rw-r--r--mediagoblin/db/models_v0.py (renamed from mediagoblin/db/sql/models_v0.py)5
-rw-r--r--mediagoblin/db/mongo/indexes.py146
-rw-r--r--mediagoblin/db/mongo/migrations.py208
-rw-r--r--mediagoblin/db/mongo/models.py310
-rw-r--r--mediagoblin/db/mongo/open.py82
-rw-r--r--mediagoblin/db/mongo/util.py318
-rw-r--r--mediagoblin/db/open.py75
-rw-r--r--mediagoblin/db/sql/convert.py282
-rw-r--r--mediagoblin/db/sql/open.py78
-rw-r--r--mediagoblin/db/sql_switch.py1
-rw-r--r--mediagoblin/db/util.py73
-rw-r--r--mediagoblin/decorators.py107
-rw-r--r--mediagoblin/edit/lib.py2
-rw-r--r--mediagoblin/edit/routing.py8
-rw-r--r--mediagoblin/edit/views.py88
-rw-r--r--mediagoblin/gmg_commands/__init__.py13
-rw-r--r--mediagoblin/gmg_commands/dbupdate.py10
-rw-r--r--mediagoblin/gmg_commands/import_export.py5
-rw-r--r--mediagoblin/gmg_commands/migrate.py75
-rw-r--r--mediagoblin/gmg_commands/shell.py17
-rw-r--r--mediagoblin/gmg_commands/users.py2
-rw-r--r--mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.mobin21970 -> 22564 bytes
-rw-r--r--mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.po353
-rw-r--r--mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.mobin20976 -> 22314 bytes
-rw-r--r--mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.po632
-rw-r--r--mediagoblin/i18n/da/LC_MESSAGES/mediagoblin.mobin20701 -> 21386 bytes
-rw-r--r--mediagoblin/i18n/da/LC_MESSAGES/mediagoblin.po456
-rw-r--r--mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.mobin21755 -> 22702 bytes
-rw-r--r--mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.po509
-rw-r--r--mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po347
-rw-r--r--mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.mobin21898 -> 22387 bytes
-rw-r--r--mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.po415
-rw-r--r--mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.mobin22501 -> 23107 bytes
-rw-r--r--mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.po373
-rw-r--r--mediagoblin/i18n/fa/LC_MESSAGES/mediagoblin.mobin21733 -> 22210 bytes
-rw-r--r--mediagoblin/i18n/fa/LC_MESSAGES/mediagoblin.po351
-rw-r--r--mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.mobin21640 -> 23218 bytes
-rw-r--r--mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.po546
-rw-r--r--mediagoblin/i18n/he/LC_MESSAGES/mediagoblin.mobin0 -> 24165 bytes
-rw-r--r--mediagoblin/i18n/he/LC_MESSAGES/mediagoblin.po1091
-rw-r--r--mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.mobin20746 -> 21386 bytes
-rw-r--r--mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.po349
-rw-r--r--mediagoblin/i18n/is_IS/LC_MESSAGES/mediagoblin.mobin0 -> 23175 bytes
-rw-r--r--mediagoblin/i18n/is_IS/LC_MESSAGES/mediagoblin.po1090
-rw-r--r--mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.mobin21803 -> 22407 bytes
-rw-r--r--mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.po359
-rw-r--r--mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.mobin21315 -> 21955 bytes
-rw-r--r--mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.po351
-rw-r--r--mediagoblin/i18n/ko_KR/LC_MESSAGES/mediagoblin.mobin0 -> 23379 bytes
-rw-r--r--mediagoblin/i18n/ko_KR/LC_MESSAGES/mediagoblin.po1090
-rw-r--r--mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.mobin21219 -> 21850 bytes
-rw-r--r--mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.po357
-rw-r--r--mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.mobin20502 -> 20935 bytes
-rw-r--r--mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.po531
-rw-r--r--mediagoblin/i18n/pl/LC_MESSAGES/mediagoblin.mobin21592 -> 22222 bytes
-rw-r--r--mediagoblin/i18n/pl/LC_MESSAGES/mediagoblin.po363
-rw-r--r--mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.mobin20965 -> 21560 bytes
-rw-r--r--mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.po355
-rw-r--r--mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.mobin22190 -> 22885 bytes
-rw-r--r--mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.po367
-rw-r--r--mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.mobin27975 -> 28560 bytes
-rw-r--r--mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.po377
-rw-r--r--mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.mobin22081 -> 22277 bytes
-rw-r--r--mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.po572
-rw-r--r--mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.mobin20929 -> 21566 bytes
-rw-r--r--mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.po353
-rw-r--r--mediagoblin/i18n/sq/LC_MESSAGES/mediagoblin.mobin21681 -> 22754 bytes
-rw-r--r--mediagoblin/i18n/sq/LC_MESSAGES/mediagoblin.po492
-rw-r--r--mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.mobin20842 -> 21482 bytes
-rw-r--r--mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.po349
-rw-r--r--mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.mobin21063 -> 21712 bytes
-rw-r--r--mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.po355
-rw-r--r--mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.mobin20988 -> 21628 bytes
-rw-r--r--mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.po349
-rw-r--r--mediagoblin/i18n/zh_TW.Big5/LC_MESSAGES/mediagoblin.mobin20786 -> 21426 bytes
-rw-r--r--mediagoblin/i18n/zh_TW.Big5/LC_MESSAGES/mediagoblin.po349
-rw-r--r--mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.mobin20866 -> 20709 bytes
-rw-r--r--mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.po650
-rw-r--r--mediagoblin/init/__init__.py12
-rw-r--r--mediagoblin/listings/routing.py2
-rw-r--r--mediagoblin/listings/views.py12
-rw-r--r--mediagoblin/meddleware/csrf.py16
-rw-r--r--mediagoblin/media_types/__init__.py19
-rw-r--r--mediagoblin/media_types/ascii/models.py7
-rw-r--r--mediagoblin/media_types/ascii/processing.py13
-rw-r--r--mediagoblin/media_types/audio/models.py7
-rw-r--r--mediagoblin/media_types/audio/processing.py26
-rw-r--r--mediagoblin/media_types/image/models.py9
-rw-r--r--mediagoblin/media_types/image/processing.py26
-rw-r--r--mediagoblin/media_types/stl/__init__.py (renamed from mediagoblin/db/sql/fake.py)36
-rw-r--r--mediagoblin/media_types/stl/assets/blender_render.blendbin0 -> 401296 bytes
-rw-r--r--mediagoblin/media_types/stl/assets/blender_render.py84
-rw-r--r--mediagoblin/media_types/stl/migrations.py (renamed from mediagoblin/db/mongo/__init__.py)2
-rw-r--r--mediagoblin/media_types/stl/model_loader.py134
-rw-r--r--mediagoblin/media_types/stl/models.py49
-rw-r--r--mediagoblin/media_types/stl/processing.py190
-rw-r--r--mediagoblin/media_types/video/models.py7
-rw-r--r--mediagoblin/media_types/video/processing.py22
-rw-r--r--mediagoblin/media_types/video/transcoders.py16
-rw-r--r--mediagoblin/mg_globals.py7
-rw-r--r--mediagoblin/plugins/api/tools.py19
-rw-r--r--mediagoblin/plugins/api/views.py57
-rw-r--r--mediagoblin/plugins/httpapiauth/__init__.py2
-rw-r--r--mediagoblin/plugins/oauth/migrations.py4
-rw-r--r--mediagoblin/plugins/oauth/models.py4
-rw-r--r--mediagoblin/plugins/oauth/views.py19
-rw-r--r--mediagoblin/processing/__init__.py6
-rw-r--r--mediagoblin/processing/task.py19
-rw-r--r--mediagoblin/routing.py49
-rw-r--r--mediagoblin/static/css/base.css58
l---------mediagoblin/static/extlib/video-js1
l---------mediagoblin/static/js/extlib/video-js1
-rw-r--r--mediagoblin/submit/lib.py105
-rw-r--r--mediagoblin/submit/routing.py2
-rw-r--r--mediagoblin/submit/views.py89
-rw-r--r--mediagoblin/templates/mediagoblin/admin/panel.html6
-rw-r--r--mediagoblin/templates/mediagoblin/base.html26
-rw-r--r--mediagoblin/templates/mediagoblin/bits/logo.html (renamed from mediagoblin/db/sql/__init__.py)10
-rw-r--r--mediagoblin/templates/mediagoblin/edit/attachments.html15
-rw-r--r--mediagoblin/templates/mediagoblin/edit/delete_account.html43
-rw-r--r--mediagoblin/templates/mediagoblin/edit/edit.html2
-rw-r--r--mediagoblin/templates/mediagoblin/edit/edit_account.html4
-rw-r--r--mediagoblin/templates/mediagoblin/edit/edit_profile.html5
-rw-r--r--mediagoblin/templates/mediagoblin/media_displays/stl.html150
-rw-r--r--mediagoblin/templates/mediagoblin/media_displays/video.html46
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/collection.html8
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html2
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/collection_list.html56
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/media.html28
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/media_collect.html2
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html2
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/processing_panel.html6
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/user.html17
-rw-r--r--mediagoblin/templates/mediagoblin/utils/collection_gallery.html18
-rw-r--r--mediagoblin/templates/mediagoblin/utils/object_gallery.html4
-rw-r--r--mediagoblin/tests/__init__.py4
-rw-r--r--mediagoblin/tests/test_api.py104
-rw-r--r--mediagoblin/tests/test_auth.py31
-rw-r--r--mediagoblin/tests/test_csrf_middleware.py25
-rw-r--r--mediagoblin/tests/test_edit.py191
-rw-r--r--mediagoblin/tests/test_exif.py19
-rw-r--r--mediagoblin/tests/test_globals.py5
-rw-r--r--mediagoblin/tests/test_http_callback.py6
-rw-r--r--mediagoblin/tests/test_messages.py13
-rw-r--r--mediagoblin/tests/test_mgoblin_app.ini2
-rw-r--r--mediagoblin/tests/test_misc.py12
-rw-r--r--mediagoblin/tests/test_oauth.py17
-rw-r--r--mediagoblin/tests/test_sql_migrations.py33
-rw-r--r--mediagoblin/tests/test_storage.py9
-rw-r--r--mediagoblin/tests/test_submission.py35
-rw-r--r--mediagoblin/tests/test_tags.py6
-rw-r--r--mediagoblin/tests/test_tests.py22
-rw-r--r--mediagoblin/tests/test_util.py14
-rw-r--r--mediagoblin/tests/test_workbench.py34
-rw-r--r--mediagoblin/tests/tools.py23
-rw-r--r--mediagoblin/themes/airy/assets/css/airy.css6
-rw-r--r--mediagoblin/themes/airy/templates/mediagoblin/base.html94
-rw-r--r--mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html (renamed from mediagoblin/gmg_commands/mongosql.py)21
-rw-r--r--mediagoblin/tools/exif.py3
-rw-r--r--mediagoblin/tools/pagination.py15
-rw-r--r--mediagoblin/tools/request.py12
-rw-r--r--mediagoblin/tools/response.py55
-rw-r--r--mediagoblin/tools/routing.py66
-rw-r--r--mediagoblin/tools/template.py35
-rw-r--r--mediagoblin/tools/translate.py42
-rw-r--r--mediagoblin/tools/url.py15
-rw-r--r--mediagoblin/user_pages/lib.py2
-rw-r--r--mediagoblin/user_pages/routing.py13
-rw-r--r--mediagoblin/user_pages/views.py359
-rw-r--r--mediagoblin/views.py6
-rw-r--r--mediagoblin/webfinger/routing.py2
-rw-r--r--mediagoblin/workbench.py27
-rwxr-xr-xruntests.sh39
-rw-r--r--setup.py6
211 files changed, 14287 insertions, 11877 deletions
diff --git a/AUTHORS b/AUTHORS
index 9205fc02..64956ad4 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -8,6 +8,7 @@ variety of different ways and this software wouldn't exist without them.
Thank you!
* Aaron Williamson
+* Aeva Ntsc
* Alejandro Villanueva
* Aleksandar Micovic
* Alex Camelio
@@ -17,12 +18,15 @@ Thank you!
* Chris Moylan
* Christopher Allan Webber
* Daniel Neel
+* Duncan Paterson
* Deb Nicholson
* Elrond of Samba TNG
+* Emily O'Leary
* Jakob Kramer
* Jef van Schendel
* Joar Wandborg
* Karen Rustad
+* Kuno Woudt
* Mark Holmquist
* Matt Lee
* Nathan Yergler
diff --git a/MANIFEST.in b/MANIFEST.in
index acaa1fdd..b3ae7b75 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -4,3 +4,4 @@ recursive-include mediagoblin/static *.js *.css *.png *.svg *.ico
recursive-include mediagoblin/tests *.ini
recursive-include docs *.rst *.html
include mediagoblin/config_spec.ini
+graft extlib
diff --git a/docs/source/plugindocs/trim_whitespace.rst b/docs/source/plugindocs/trim_whitespace.rst
new file mode 100644
index 00000000..eb38e0e5
--- /dev/null
+++ b/docs/source/plugindocs/trim_whitespace.rst
@@ -0,0 +1 @@
+.. include:: ../../../mediagoblin/plugins/trim_whitespace/README.rst
diff --git a/docs/source/siteadmin/codebase.rst b/docs/source/siteadmin/codebase.rst
index 22f4e18b..73e938e7 100644
--- a/docs/source/siteadmin/codebase.rst
+++ b/docs/source/siteadmin/codebase.rst
@@ -65,7 +65,7 @@ Software Stack
`Paste Script <http://pythonpaste.org/script/>`_: we'll use this for
configuring and launching the application
- * `WebOb <http://pythonpaste.org/webob/>`_: nice abstraction layer
+ * `werkzeug <http://werkzeug.pocoo.org/>`_: nice abstraction layer
from HTTP requests, responses and WSGI bits
* `Beaker <http://beaker.groovie.org/>`_: for handling sessions and
diff --git a/docs/source/siteadmin/deploying.rst b/docs/source/siteadmin/deploying.rst
index 0eb67be4..91406f96 100644
--- a/docs/source/siteadmin/deploying.rst
+++ b/docs/source/siteadmin/deploying.rst
@@ -191,6 +191,12 @@ codebase, you should also run::
./bin/python setup.py develop --upgrade && ./bin/gmg dbupdate
+Note: If you are running an active site, depending on your server
+configuration, you may need to stop it first or the dbupdate command
+may hang (and it's certainly a good idea to restart it after the
+update)
+
+
Deploy MediaGoblin Services
---------------------------
diff --git a/docs/source/siteadmin/media-types.rst b/docs/source/siteadmin/media-types.rst
index 5653217f..8fbce5e4 100644
--- a/docs/source/siteadmin/media-types.rst
+++ b/docs/source/siteadmin/media-types.rst
@@ -43,6 +43,15 @@ video media types, then the list would look like this::
media_types = mediagoblin.media_types.image, mediagoblin.media_types.video
+Note that after enabling new media types, you must run dbupdate like so::
+
+ ./bin/gmg dbupdate
+
+If you are running an active site, depending on your server
+configuration, you may need to stop it first (and it's certainly a
+good idea to restart it after the update).
+
+
How does MediaGoblin decide which media type to use for a file?
===============================================================
@@ -68,6 +77,13 @@ 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.
+
+Run::
+
+ ./bin/gmg dbupdate
+
Now you should be able to submit videos, and mediagoblin should
transcode them.
@@ -108,8 +124,13 @@ Then install ``scikits.audiolab`` for the spectrograms::
./bin/pip install scikits.audiolab
Add ``mediagoblin.media_types.audio`` to the ``media_types`` list in your
-``mediagoblin_local.ini`` and restart MediaGoblin. You should now be able to
-upload and listen to audio files!
+``mediagoblin_local.ini`` and restart MediaGoblin.
+
+Run::
+
+ ./bin/gmg dbupdate
+
+You should now be able to upload and listen to audio files!
Ascii art
@@ -131,4 +152,28 @@ the list would look like this::
media_types = mediagoblin.media_types.image, mediagoblin.media_types.ascii
+Run::
+
+ ./bin/gmg dbupdate
+
Now any .txt file you uploaded will be processed as ascii art!
+
+
+STL / 3d model support
+======================
+
+To enable the "STL" 3d model support plugin, first make sure you have
+a recentish `Blender <http://blender.org>`_ installed and available on
+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
+``mediagoblin_local.ini`` and restart MediaGoblin.
+
+Run::
+
+ ./bin/gmg dbupdate
+
+You should now be able to upload .obj and .stl files and MediaGoblin
+will be able to present them to your wide audience of admirers!
diff --git a/docs/source/siteadmin/relnotes.rst b/docs/source/siteadmin/relnotes.rst
index 56267eb1..7d480d90 100644
--- a/docs/source/siteadmin/relnotes.rst
+++ b/docs/source/siteadmin/relnotes.rst
@@ -19,6 +19,93 @@ 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.
+WIP
+=====
+
+**New features**
+
+**Other changed**
+
+* Plugin writers: Internal restructuring led to mediagoblin.db.sql* be
+ mediagoblin.db.* starting from 0.3.3
+
+* Dependency list has been reduced not requireing the "webob" package anymore.
+
+0.3.2
+=====
+
+This will be the last release that is capable of converting from an earlier
+MongoDB-based MediaGoblin instance to the newer SQL-based system.
+
+**Do this to upgrade**
+
+1. Make sure to run ``bin/gmg dbupdate`` after upgrading.
+
+
+**New features**
+
+* **3d model support!**
+
+ You can now upload STL and OBJ files and display them in
+ MediaGoblin. Requires a recent-ish Blender; for details see:
+ :ref:`deploying-chapter`
+
+* **trim_whitespace**
+
+ We bundle the optional plugin trim_whitespace which reduces the size
+ of the delivered html output by reducing redundant whitespace.
+
+ See :ref:`core-plugin-section` for plugin documentation
+
+* **A new API!**
+
+ It isn't well documented yet but we do have an API. There is an
+ `android application in progress <https://gitorious.org/mediagoblin/mediagoblin-android>`_
+ which makes use of it, and there are some demo applications between
+ `automgtic <https://github.com/jwandborg/automgtic>`_, an
+ automatic media uploader for your desktop
+ and `OMGMG <https://github.com/jwandborg/omgmg>`_, an example of
+ a web application hooking up to the API.
+
+ This is a plugin, so you have to enable it in your mediagoblin
+ config file by adding a section under [plugins] like::
+
+ [plugins]
+ [[mediagoblin.plugins.api]]
+
+ Note that the API works but is not nailed down... the way it is
+ called may change in future releases.
+
+* **OAuth login support**
+
+ For applications that use OAuth to connect to the API.
+
+ This is a plugin, so you have to enable it in your mediagoblin
+ config file by adding a section under [plugins] like::
+
+ [plugins]
+ [[mediagoblin.plugins.oauth]]
+
+* **Collections**
+
+ We now have user-curated collections support. These are arbitrary
+ galleries that are customizable by users. You can add media to
+ these by clicking on the paperclip icon when logged in and looking
+ at a media entry.
+
+* **OpenStreetMap licensing display improvements**
+
+ More accurate display of OSM licensing, and less disruptive: you
+ click to "expand" the display of said licensing.
+
+ Geolocation is also now on by default.
+
+* **Miscelaneous visual improvements**
+
+ We've made a number of small visual improvements including newer and
+ nicer looking thumbnails and improved checkbox placement.
+
+
0.3.1
=====
@@ -49,12 +136,6 @@ carefully, or at least skim over it.
See :ref:`core-plugin-section` for plugin documentation
-* **trim_whitespace**
-
- We bundle the optional plugin trim_whitespace which reduces the size
- of the delivered html output by reducing redundant whitespace.
-
- See :ref:`core-plugin-section` for plugin documentation
0.3.0
=====
diff --git a/extlib/exif/EXIF.py b/extlib/exif/EXIF.py
index ed4192af..a188154e 100755
--- a/extlib/exif/EXIF.py
+++ b/extlib/exif/EXIF.py
@@ -1,8 +1,10 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
-# Library to extract EXIF information from digital camera image files
-# http://sourceforge.net/projects/exif-py/
+#
+# Library to extract EXIF information from digital camera image files.
+# https://github.com/ianare/exif-py
+#
#
# VERSION 1.1.0
#
@@ -22,7 +24,6 @@
#
# These 2 are useful when you are retrieving a large list of images
#
-#
# To return an error on invalid tags,
# pass the -s or --strict argument, or as
# tags = EXIF.process_file(f, strict=True)
@@ -48,7 +49,7 @@
# 'EXIF DateTimeOriginal', 'Image Orientation', 'MakerNote FocusMode'
#
# Copyright (c) 2002-2007 Gene Cash All rights reserved
-# Copyright (c) 2007-2008 Ianaré Sévi All rights reserved
+# Copyright (c) 2007-2012 Ianaré Sévi All rights reserved
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -102,7 +103,7 @@ def make_string_uc(seq):
seq = seq[8:]
# Of course, this is only correct if ASCII, and the standard explicitly
# allows JIS and Unicode.
- return make_string(seq)
+ return make_string( make_string(seq) )
# field type descriptions as (length, abbreviation, full name) tuples
FIELD_TYPES = (
@@ -171,9 +172,9 @@ EXIF_TAGS = {
3: 'Rotated 180',
4: 'Mirrored vertical',
5: 'Mirrored horizontal then rotated 90 CCW',
- 6: 'Rotated 90 CW',
+ 6: 'Rotated 90 CCW',
7: 'Mirrored horizontal then rotated 90 CW',
- 8: 'Rotated 90 CCW'}),
+ 8: 'Rotated 90 CW'}),
0x0115: ('SamplesPerPixel', ),
0x0116: ('RowsPerStrip', ),
0x0117: ('StripByteCounts', ),
@@ -251,40 +252,54 @@ EXIF_TAGS = {
2: 'CenterWeightedAverage',
3: 'Spot',
4: 'MultiSpot',
- 5: 'Pattern'}),
+ 5: 'Pattern',
+ 6: 'Partial',
+ 255: 'other'}),
0x9208: ('LightSource',
{0: 'Unknown',
1: 'Daylight',
2: 'Fluorescent',
- 3: 'Tungsten',
- 9: 'Fine Weather',
- 10: 'Flash',
+ 3: 'Tungsten (incandescent light)',
+ 4: 'Flash',
+ 9: 'Fine weather',
+ 10: 'Cloudy weather',
11: 'Shade',
- 12: 'Daylight Fluorescent',
- 13: 'Day White Fluorescent',
- 14: 'Cool White Fluorescent',
- 15: 'White Fluorescent',
- 17: 'Standard Light A',
- 18: 'Standard Light B',
- 19: 'Standard Light C',
+ 12: 'Daylight fluorescent (D 5700 - 7100K)',
+ 13: 'Day white fluorescent (N 4600 - 5400K)',
+ 14: 'Cool white fluorescent (W 3900 - 4500K)',
+ 15: 'White fluorescent (WW 3200 - 3700K)',
+ 17: 'Standard light A',
+ 18: 'Standard light B',
+ 19: 'Standard light C',
20: 'D55',
21: 'D65',
22: 'D75',
- 255: 'Other'}),
+ 23: 'D50',
+ 24: 'ISO studio tungsten',
+ 255: 'other light source',}),
0x9209: ('Flash',
- {0: 'No',
- 1: 'Fired',
- 5: 'Fired (?)', # no return sensed
- 7: 'Fired (!)', # return sensed
- 9: 'Fill Fired',
- 13: 'Fill Fired (?)',
- 15: 'Fill Fired (!)',
- 16: 'Off',
- 24: 'Auto Off',
- 25: 'Auto Fired',
- 29: 'Auto Fired (?)',
- 31: 'Auto Fired (!)',
- 32: 'Not Available'}),
+ {0: 'Flash did not fire',
+ 1: 'Flash fired',
+ 5: 'Strobe return light not detected',
+ 7: 'Strobe return light detected',
+ 9: 'Flash fired, compulsory flash mode',
+ 13: 'Flash fired, compulsory flash mode, return light not detected',
+ 15: 'Flash fired, compulsory flash mode, return light detected',
+ 16: 'Flash did not fire, compulsory flash mode',
+ 24: 'Flash did not fire, auto mode',
+ 25: 'Flash fired, auto mode',
+ 29: 'Flash fired, auto mode, return light not detected',
+ 31: 'Flash fired, auto mode, return light detected',
+ 32: 'No flash function',
+ 65: 'Flash fired, red-eye reduction mode',
+ 69: 'Flash fired, red-eye reduction mode, return light not detected',
+ 71: 'Flash fired, red-eye reduction mode, return light detected',
+ 73: 'Flash fired, compulsory flash mode, red-eye reduction mode',
+ 77: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected',
+ 79: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light detected',
+ 89: 'Flash fired, auto mode, red-eye reduction mode',
+ 93: 'Flash fired, auto mode, return light not detected, red-eye reduction mode',
+ 95: 'Flash fired, auto mode, return light detected, red-eye reduction mode'}),
0x920A: ('FocalLength', ),
0x9214: ('SubjectArea', ),
0x927C: ('MakerNote', ),
@@ -410,7 +425,10 @@ GPS_TAGS = {
0x0018: ('GPSDestBearing', ),
0x0019: ('GPSDestDistanceRef', ),
0x001A: ('GPSDestDistance', ),
+ 0x001B: ('GPSProcessingMethod', ),
+ 0x001C: ('GPSAreaInformation', ),
0x001D: ('GPSDate', ),
+ 0x001E: ('GPSDifferential', ),
}
# Ignore these tags when quick processing
@@ -1231,10 +1249,17 @@ class IFD_Tag:
return self.printable
def __repr__(self):
- return '(0x%04X) %s=%s @ %d' % (self.tag,
+ try:
+ s= '(0x%04X) %s=%s @ %d' % (self.tag,
FIELD_TYPES[self.field_type][2],
self.printable,
self.field_offset)
+ except:
+ s= '(%s) %s=%s @ %s' % (str(self.tag),
+ FIELD_TYPES[self.field_type][2],
+ self.printable,
+ str(self.field_offset))
+ return s
# class that handles an EXIF header
class EXIF_header:
@@ -1283,7 +1308,11 @@ class EXIF_header:
# return pointer to next IFD
def next_IFD(self, ifd):
entries=self.s2n(ifd, 2)
- return self.s2n(ifd+2+12*entries, 4)
+ next_ifd = self.s2n(ifd+2+12*entries, 4)
+ if next_ifd == ifd:
+ return 0
+ else:
+ return next_ifd
# return list of IFDs in header
def list_IFDs(self):
@@ -1348,14 +1377,15 @@ class EXIF_header:
# special case: null-terminated ASCII string
# XXX investigate
# sometimes gets too big to fit in int value
- if count != 0 and count < (2**31):
- self.file.seek(self.offset + offset)
- values = self.file.read(count)
- #print values
- # Drop any garbage after a null.
- values = values.split('\x00', 1)[0]
- else:
- values = ''
+ if count != 0: # and count < (2**31): # 2E31 is hardware dependant. --gd
+ try:
+ self.file.seek(self.offset + offset)
+ values = self.file.read(count)
+ #print values
+ # Drop any garbage after a null.
+ values = values.split('\x00', 1)[0]
+ except OverflowError:
+ values = ''
else:
values = []
signed = (field_type in [6, 8, 9, 10])
@@ -1567,7 +1597,8 @@ class EXIF_header:
dict=MAKERNOTE_CANON_TAGS)
for i in (('MakerNote Tag 0x0001', MAKERNOTE_CANON_TAG_0x001),
('MakerNote Tag 0x0004', MAKERNOTE_CANON_TAG_0x004)):
- self.canon_decode_tag(self.tags[i[0]].values, i[1])
+ if i[0] in self.tags:
+ self.canon_decode_tag(self.tags[i[0]].values, i[1])
return
@@ -1613,26 +1644,124 @@ def process_file(f, stop_tag='UNDEF', details=True, strict=False, debug=False):
offset = 0
elif data[0:2] == '\xFF\xD8':
# it's a JPEG file
+ if debug: print "JPEG format recognized data[0:2] == '0xFFD8'."
+ base = 2
while data[2] == '\xFF' and data[6:10] in ('JFIF', 'JFXX', 'OLYM', 'Phot'):
+ if debug: print "data[2] == 0xxFF data[3]==%x and data[6:10] = %s"%(ord(data[3]),data[6:10])
length = ord(data[4])*256+ord(data[5])
+ if debug: print "Length offset is",length
f.read(length-8)
# fake an EXIF beginning of file
+ # I don't think this is used. --gd
data = '\xFF\x00'+f.read(10)
fake_exif = 1
- if data[2] == '\xFF' and data[6:10] == 'Exif':
+ if base>2:
+ if debug: print "added to base "
+ base = base + length + 4 -2
+ else:
+ if debug: print "added to zero "
+ base = length + 4
+ if debug: print "Set segment base to",base
+
+ # Big ugly patch to deal with APP2 (or other) data coming before APP1
+ f.seek(0)
+ data = f.read(base+4000) # in theory, this could be insufficient since 64K is the maximum size--gd
+ # base = 2
+ while 1:
+ if debug: print "Segment base 0x%X" % base
+ if data[base:base+2]=='\xFF\xE1':
+ # APP1
+ if debug: print "APP1 at base",hex(base)
+ if debug: print "Length",hex(ord(data[base+2])), hex(ord(data[base+3]))
+ if debug: print "Code",data[base+4:base+8]
+ if data[base+4:base+8] == "Exif":
+ if debug: print "Decrement base by",2,"to get to pre-segment header (for compatibility with later code)"
+ base = base-2
+ break
+ if debug: print "Increment base by",ord(data[base+2])*256+ord(data[base+3])+2
+ base=base+ord(data[base+2])*256+ord(data[base+3])+2
+ elif data[base:base+2]=='\xFF\xE0':
+ # APP0
+ if debug: print "APP0 at base",hex(base)
+ if debug: print "Length",hex(ord(data[base+2])), hex(ord(data[base+3]))
+ if debug: print "Code",data[base+4:base+8]
+ if debug: print "Increment base by",ord(data[base+2])*256+ord(data[base+3])+2
+ base=base+ord(data[base+2])*256+ord(data[base+3])+2
+ elif data[base:base+2]=='\xFF\xE2':
+ # APP2
+ if debug: print "APP2 at base",hex(base)
+ if debug: print "Length",hex(ord(data[base+2])), hex(ord(data[base+3]))
+ if debug: print "Code",data[base+4:base+8]
+ if debug: print "Increment base by",ord(data[base+2])*256+ord(data[base+3])+2
+ base=base+ord(data[base+2])*256+ord(data[base+3])+2
+ elif data[base:base+2]=='\xFF\xEE':
+ # APP14
+ if debug: print "APP14 Adobe segment at base",hex(base)
+ if debug: print "Length",hex(ord(data[base+2])), hex(ord(data[base+3]))
+ if debug: print "Code",data[base+4:base+8]
+ if debug: print "Increment base by",ord(data[base+2])*256+ord(data[base+3])+2
+ print "There is useful EXIF-like data here, but we have no parser for it."
+ base=base+ord(data[base+2])*256+ord(data[base+3])+2
+ elif data[base:base+2]=='\xFF\xDB':
+ if debug: print "JPEG image data at base",hex(base),"No more segments are expected."
+ # sys.exit(0)
+ break
+ elif data[base:base+2]=='\xFF\xD8':
+ # APP12
+ if debug: print "FFD8 segment at base",hex(base)
+ if debug: print "Got",hex(ord(data[base])), hex(ord(data[base+1])),"and", data[4+base:10+base], "instead."
+ if debug: print "Length",hex(ord(data[base+2])), hex(ord(data[base+3]))
+ if debug: print "Code",data[base+4:base+8]
+ if debug: print "Increment base by",ord(data[base+2])*256+ord(data[base+3])+2
+ base=base+ord(data[base+2])*256+ord(data[base+3])+2
+ elif data[base:base+2]=='\xFF\xEC':
+ # APP12
+ if debug: print "APP12 XMP (Ducky) or Pictureinfo segment at base",hex(base)
+ if debug: print "Got",hex(ord(data[base])), hex(ord(data[base+1])),"and", data[4+base:10+base], "instead."
+ if debug: print "Length",hex(ord(data[base+2])), hex(ord(data[base+3]))
+ if debug: print "Code",data[base+4:base+8]
+ if debug: print "Increment base by",ord(data[base+2])*256+ord(data[base+3])+2
+ print "There is useful EXIF-like data here (quality, comment, copyright), but we have no parser for it."
+ base=base+ord(data[base+2])*256+ord(data[base+3])+2
+ else:
+ try:
+ if debug: print "Unexpected/unhandled segment type or file content."
+ if debug: print "Got",hex(ord(data[base])), hex(ord(data[base+1])),"and", data[4+base:10+base], "instead."
+ if debug: print "Increment base by",ord(data[base+2])*256+ord(data[base+3])+2
+ except: pass
+ try: base=base+ord(data[base+2])*256+ord(data[base+3])+2
+ except: pass
+
+ f.seek(base+12)
+ if data[2+base] == '\xFF' and data[6+base:10+base] == 'Exif':
# detected EXIF header
offset = f.tell()
endian = f.read(1)
+ #HACK TEST: endian = 'M'
+ elif data[2+base] == '\xFF' and data[6+base:10+base+1] == 'Ducky':
+ # detected Ducky header.
+ if debug: print "EXIF-like header (normally 0xFF and code):",hex(ord(data[2+base])) , "and", data[6+base:10+base+1]
+ offset = f.tell()
+ endian = f.read(1)
+ elif data[2+base] == '\xFF' and data[6+base:10+base+1] == 'Adobe':
+ # detected APP14 (Adobe)
+ if debug: print "EXIF-like header (normally 0xFF and code):",hex(ord(data[2+base])) , "and", data[6+base:10+base+1]
+ offset = f.tell()
+ endian = f.read(1)
else:
# no EXIF information
+ if debug: print "No EXIF header expected data[2+base]==0xFF and data[6+base:10+base]===Exif (or Duck)"
+ if debug: print " but got",hex(ord(data[2+base])) , "and", data[6+base:10+base+1]
return {}
else:
# file format not recognized
+ if debug: print "file format not recognized"
return {}
# deal with the EXIF info we found
if debug:
- print {'I': 'Intel', 'M': 'Motorola'}[endian], 'format'
+ print "Endian format is ",endian
+ print {'I': 'Intel', 'M': 'Motorola', '\x01':'Adobe Ducky', 'd':'XMP/Adobe unknown' }[endian], 'format'
hdr = EXIF_header(f, endian, offset, fake_exif, strict, debug)
ifd_list = hdr.list_IFDs()
ctr = 0
diff --git a/extlib/exif/changes.txt b/extlib/exif/changes.txt
new file mode 100644
index 00000000..d1b18e6c
--- /dev/null
+++ b/extlib/exif/changes.txt
@@ -0,0 +1,131 @@
+~ EXIF.py Changelog ~
+
+2012-11-30 - Gregory Dudek (date of merge).
+Patches and changes:
+ Overflow error fixes added (related to 2**31 size)
+ GPS tags added.
+
+2012-09-26 - Ianaré Sévi
+Merge patches:
+ Add GPS tags
+ Add better endian debug info
+
+2012-06-13 - Ianaré Sévi
+Merge patches:
+ Support malformed last IFD by fhats
+ Light source, Flash and Metering mode dictionaries update by gryfik
+
+2008-07-31 - Ianaré Sévi
+Wikipedia Commons hunt for suitable test case images,
+testing new code additions.
+
+2008-07-09 - Stephen H. Olson
+Fix a problem with reading MakerNotes out of NEF files.
+Add some more Nikon MakerNote tags.
+
+2008-07-08 - Stephen H. Olson
+An error check for large tags totally borked MakerNotes.
+ With Nikon anyway, valid MakerNotes can be pretty big.
+Add error check for a crash caused by nikon_ev_bias being
+ called with the wrong args.
+Drop any garbage after a null character in string
+ (patch from Andrew McNabb <amcnabb@google.com>).
+
+2008-02-12 - Ianaré Sévi
+Fix crash on invalid MakerNote
+Fix crash on huge Makernote (temp fix)
+Add printIM tag 0xC4A5, needs decoding info
+Add 0x9C9B-F range of tags
+Add a bunch of tag definitions from:
+ http://owl.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html
+Add 'strict' variable and command line option
+
+2008-01-18 - Gunter Ohrner
+Add 'GPSDate' tag
+
+2007-12-12 - Ianaré Sévi
+Fix quick option on certain image types
+Add note on tag naming in documentation
+
+2007-11-30 - Ianaré Sévi
+Changed -s option to -t
+Put changelog into separate file
+
+2007-10-28 - Ianaré Sévi
+Merged changes from MoinMoin:ReimarBauer
+Added command line option for debug, stop
+processing on tag.
+
+2007-09-27 - Ianaré Sévi
+Add some Olympus Makernote tags.
+
+2007-09-26 - Stephen H. Olson
+Don't error out on invalid Olympus 'SpecialMode'.
+Add a few more Olympus/Minolta tags.
+
+2007-09-22 - Stephen H. Olson
+Don't error on invalid string
+Improved Nikon MakerNote support
+
+2007-05-03 - Martin Stone <mj_stone@users.sourceforge.net>
+Fix for inverted detailed flag and Photoshop header
+
+2007-03-24 - Ianaré Sévi
+Can now ignore MakerNotes Tags for faster processing.
+
+2007-01-18 - Ianaré Sévi <ianare@gmail.com>
+Fixed a couple errors and assuming maintenance of the library.
+
+2006-08-04 MoinMoin:ReimarBauer
+Added an optional parameter name to process_file and dump_IFD. Using this parameter the
+loop is breaked after that tag_name is processed.
+some PEP8 changes
+
+---------------------------- original notices -------------------------
+
+Contains code from "exifdump.py" originally written by Thierry Bousch
+<bousch@topo.math.u-psud.fr> and released into the public domain.
+
+Updated and turned into general-purpose library by Gene Cash
+
+Patch Contributors:
+* Simon J. Gerraty <sjg@crufty.net>
+s2n fix & orientation decode
+* John T. Riedl <riedl@cs.umn.edu>
+Added support for newer Nikon type 3 Makernote format for D70 and some
+other Nikon cameras.
+* Joerg Schaefer <schaeferj@gmx.net>
+Fixed subtle bug when faking an EXIF header, which affected maker notes
+using relative offsets, and a fix for Nikon D100.
+
+1999-08-21 TB Last update by Thierry Bousch to his code.
+
+2002-01-17 CEC Discovered code on web.
+ Commented everything.
+ Made small code improvements.
+ Reformatted for readability.
+
+2002-01-19 CEC Added ability to read TIFFs and JFIF-format JPEGs.
+ Added ability to extract JPEG formatted thumbnail.
+ Added ability to read GPS IFD (not tested).
+ Converted IFD data structure to dictionaries indexed by
+ tag name.
+ Factored into library returning dictionary of IFDs plus
+ thumbnail, if any.
+
+2002-01-20 CEC Added MakerNote processing logic.
+ Added Olympus MakerNote.
+ Converted data structure to single-level dictionary, avoiding
+ tag name collisions by prefixing with IFD name. This makes
+ it much easier to use.
+2002-01-23 CEC Trimmed nulls from end of string values.
+
+2002-01-25 CEC Discovered JPEG thumbnail in Olympus TIFF MakerNote.
+
+2002-01-26 CEC Added ability to extract TIFF thumbnails.
+ Added Nikon, Fujifilm, Casio MakerNotes.
+
+2003-11-30 CEC Fixed problem with canon_decode_tag() not creating an
+ IFD_Tag() object.
+
+2004-02-15 CEC Finally fixed bit shift warning by converting Y to 0L.
diff --git a/extlib/thingiview.js/LICENSE b/extlib/thingiview.js/LICENSE
new file mode 100644
index 00000000..65c5ca88
--- /dev/null
+++ b/extlib/thingiview.js/LICENSE
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/extlib/thingiview.js/Three.js b/extlib/thingiview.js/Three.js
new file mode 100644
index 00000000..5c21380c
--- /dev/null
+++ b/extlib/thingiview.js/Three.js
@@ -0,0 +1,202 @@
+// Three.js r32 - http://github.com/mrdoob/three.js
+var THREE=THREE||{};THREE.Color=function(a){this.autoUpdate=true;this.setHex(a)};
+THREE.Color.prototype={setRGB:function(a,c,d){this.r=a;this.g=c;this.b=d;if(this.autoUpdate){this.updateHex();this.updateStyleString()}},setHex:function(a){this.hex=~~a&16777215;if(this.autoUpdate){this.updateRGBA();this.updateStyleString()}},updateHex:function(){this.hex=~~(this.r*255)<<16^~~(this.g*255)<<8^~~(this.b*255)},updateRGBA:function(){this.r=(this.hex>>16&255)/255;this.g=(this.hex>>8&255)/255;this.b=(this.hex&255)/255},updateStyleString:function(){this.__styleString="rgb("+~~(this.r*255)+
+","+~~(this.g*255)+","+~~(this.b*255)+")"},clone:function(){return new THREE.Color(this.hex)},toString:function(){return"THREE.Color ( r: "+this.r+", g: "+this.g+", b: "+this.b+", hex: "+this.hex+" )"}};THREE.Vector2=function(a,c){this.x=a||0;this.y=c||0};
+THREE.Vector2.prototype={set:function(a,c){this.x=a;this.y=c;return this},copy:function(a){this.x=a.x;this.y=a.y;return this},addSelf:function(a){this.x+=a.x;this.y+=a.y;return this},add:function(a,c){this.x=a.x+c.x;this.y=a.y+c.y;return this},subSelf:function(a){this.x-=a.x;this.y-=a.y;return this},sub:function(a,c){this.x=a.x-c.x;this.y=a.y-c.y;return this},multiplyScalar:function(a){this.x*=a;this.y*=a;return this},unit:function(){this.multiplyScalar(1/this.length());return this},length:function(){return Math.sqrt(this.x*
+this.x+this.y*this.y)},lengthSq:function(){return this.x*this.x+this.y*this.y},negate:function(){this.x=-this.x;this.y=-this.y;return this},clone:function(){return new THREE.Vector2(this.x,this.y)},toString:function(){return"THREE.Vector2 ("+this.x+", "+this.y+")"}};THREE.Vector3=function(a,c,d){this.x=a||0;this.y=c||0;this.z=d||0};
+THREE.Vector3.prototype={set:function(a,c,d){this.x=a;this.y=c;this.z=d;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;return this},add:function(a,c){this.x=a.x+c.x;this.y=a.y+c.y;this.z=a.z+c.z;return this},addSelf:function(a){this.x+=a.x;this.y+=a.y;this.z+=a.z;return this},addScalar:function(a){this.x+=a;this.y+=a;this.z+=a;return this},sub:function(a,c){this.x=a.x-c.x;this.y=a.y-c.y;this.z=a.z-c.z;return this},subSelf:function(a){this.x-=a.x;this.y-=a.y;this.z-=a.z;return this},
+cross:function(a,c){this.x=a.y*c.z-a.z*c.y;this.y=a.z*c.x-a.x*c.z;this.z=a.x*c.y-a.y*c.x;return this},crossSelf:function(a){var c=this.x,d=this.y,e=this.z;this.x=d*a.z-e*a.y;this.y=e*a.x-c*a.z;this.z=c*a.y-d*a.x;return this},multiply:function(a,c){this.x=a.x*c.x;this.y=a.y*c.y;this.z=a.z*c.z;return this},multiplySelf:function(a){this.x*=a.x;this.y*=a.y;this.z*=a.z;return this},multiplyScalar:function(a){this.x*=a;this.y*=a;this.z*=a;return this},divideSelf:function(a){this.x/=a.x;this.y/=a.y;this.z/=
+a.z;return this},divideScalar:function(a){this.x/=a;this.y/=a;this.z/=a;return this},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z},distanceTo:function(a){var c=this.x-a.x,d=this.y-a.y;a=this.z-a.z;return Math.sqrt(c*c+d*d+a*a)},distanceToSquared:function(a){var c=this.x-a.x,d=this.y-a.y;a=this.z-a.z;return c*c+d*d+a*a},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z},negate:function(){this.x=
+-this.x;this.y=-this.y;this.z=-this.z;return this},normalize:function(){var a=Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z);a>0?this.multiplyScalar(1/a):this.set(0,0,0);return this},setLength:function(a){return this.normalize().multiplyScalar(a)},isZero:function(){return Math.abs(this.x)<1.0E-4&&Math.abs(this.y)<1.0E-4&&Math.abs(this.z)<1.0E-4},clone:function(){return new THREE.Vector3(this.x,this.y,this.z)},toString:function(){return"THREE.Vector3 ( "+this.x+", "+this.y+", "+this.z+" )"}};
+THREE.Vector4=function(a,c,d,e){this.x=a||0;this.y=c||0;this.z=d||0;this.w=e||1};
+THREE.Vector4.prototype={set:function(a,c,d,e){this.x=a;this.y=c;this.z=d;this.w=e;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=a.w||1;return this},add:function(a,c){this.x=a.x+c.x;this.y=a.y+c.y;this.z=a.z+c.z;this.w=a.w+c.w;return this},addSelf:function(a){this.x+=a.x;this.y+=a.y;this.z+=a.z;this.w+=a.w;return this},sub:function(a,c){this.x=a.x-c.x;this.y=a.y-c.y;this.z=a.z-c.z;this.w=a.w-c.w;return this},subSelf:function(a){this.x-=a.x;this.y-=a.y;this.z-=a.z;this.w-=a.w;
+return this},multiplyScalar:function(a){this.x*=a;this.y*=a;this.z*=a;this.w*=a;return this},divideScalar:function(a){this.x/=a;this.y/=a;this.z/=a;this.w/=a;return this},lerpSelf:function(a,c){this.x+=(a.x-this.x)*c;this.y+=(a.y-this.y)*c;this.z+=(a.z-this.z)*c;this.w+=(a.w-this.w)*c},clone:function(){return new THREE.Vector4(this.x,this.y,this.z,this.w)},toString:function(){return"THREE.Vector4 ("+this.x+", "+this.y+", "+this.z+", "+this.w+")"}};
+THREE.Ray=function(a,c){this.origin=a||new THREE.Vector3;this.direction=c||new THREE.Vector3};
+THREE.Ray.prototype={intersectScene:function(a){var c,d,e=a.objects,g=[];a=0;for(c=e.length;a<c;a++){d=e[a];if(d instanceof THREE.Mesh)g=g.concat(this.intersectObject(d))}g.sort(function(h,o){return h.distance-o.distance});return g},intersectObject:function(a){function c(K,p,U,F){F=F.clone().subSelf(p);U=U.clone().subSelf(p);var f=K.clone().subSelf(p);K=F.dot(F);p=F.dot(U);F=F.dot(f);var j=U.dot(U);U=U.dot(f);f=1/(K*j-p*p);j=(j*F-p*U)*f;K=(K*U-p*F)*f;return j>0&&K>0&&j+K<1}var d,e,g,h,o,b,i,k,y,z,
+u,x=a.geometry,H=x.vertices,J=[];d=0;for(e=x.faces.length;d<e;d++){g=x.faces[d];z=this.origin.clone();u=this.direction.clone();h=a.matrix.multiplyVector3(H[g.a].position.clone());o=a.matrix.multiplyVector3(H[g.b].position.clone());b=a.matrix.multiplyVector3(H[g.c].position.clone());i=g instanceof THREE.Face4?a.matrix.multiplyVector3(H[g.d].position.clone()):null;k=a.rotationMatrix.multiplyVector3(g.normal.clone());y=u.dot(k);if(y<0){k=k.dot((new THREE.Vector3).sub(h,z))/y;z=z.addSelf(u.multiplyScalar(k));
+if(g instanceof THREE.Face3){if(c(z,h,o,b)){g={distance:this.origin.distanceTo(z),point:z,face:g,object:a};J.push(g)}}else if(g instanceof THREE.Face4)if(c(z,h,o,i)||c(z,o,b,i)){g={distance:this.origin.distanceTo(z),point:z,face:g,object:a};J.push(g)}}}return J}};
+THREE.Rectangle=function(){function a(){h=e-c;o=g-d}var c,d,e,g,h,o,b=true;this.getX=function(){return c};this.getY=function(){return d};this.getWidth=function(){return h};this.getHeight=function(){return o};this.getLeft=function(){return c};this.getTop=function(){return d};this.getRight=function(){return e};this.getBottom=function(){return g};this.set=function(i,k,y,z){b=false;c=i;d=k;e=y;g=z;a()};this.addPoint=function(i,k){if(b){b=false;c=i;d=k;e=i;g=k}else{c=c<i?c:i;d=d<k?d:k;e=e>i?e:i;g=g>k?
+g:k}a()};this.add3Points=function(i,k,y,z,u,x){if(b){b=false;c=i<y?i<u?i:u:y<u?y:u;d=k<z?k<x?k:x:z<x?z:x;e=i>y?i>u?i:u:y>u?y:u;g=k>z?k>x?k:x:z>x?z:x}else{c=i<y?i<u?i<c?i:c:u<c?u:c:y<u?y<c?y:c:u<c?u:c;d=k<z?k<x?k<d?k:d:x<d?x:d:z<x?z<d?z:d:x<d?x:d;e=i>y?i>u?i>e?i:e:u>e?u:e:y>u?y>e?y:e:u>e?u:e;g=k>z?k>x?k>g?k:g:x>g?x:g:z>x?z>g?z:g:x>g?x:g}a()};this.addRectangle=function(i){if(b){b=false;c=i.getLeft();d=i.getTop();e=i.getRight();g=i.getBottom()}else{c=c<i.getLeft()?c:i.getLeft();d=d<i.getTop()?d:i.getTop();
+e=e>i.getRight()?e:i.getRight();g=g>i.getBottom()?g:i.getBottom()}a()};this.inflate=function(i){c-=i;d-=i;e+=i;g+=i;a()};this.minSelf=function(i){c=c>i.getLeft()?c:i.getLeft();d=d>i.getTop()?d:i.getTop();e=e<i.getRight()?e:i.getRight();g=g<i.getBottom()?g:i.getBottom();a()};this.instersects=function(i){return Math.min(e,i.getRight())-Math.max(c,i.getLeft())>=0&&Math.min(g,i.getBottom())-Math.max(d,i.getTop())>=0};this.empty=function(){b=true;g=e=d=c=0;a()};this.isEmpty=function(){return b};this.toString=
+function(){return"THREE.Rectangle ( left: "+c+", right: "+e+", top: "+d+", bottom: "+g+", width: "+h+", height: "+o+" )"}};THREE.Matrix3=function(){this.m=[]};THREE.Matrix3.prototype={transpose:function(){var a,c=this.m;a=c[1];c[1]=c[3];c[3]=a;a=c[2];c[2]=c[6];c[6]=a;a=c[5];c[5]=c[7];c[7]=a;return this}};
+THREE.Matrix4=function(a,c,d,e,g,h,o,b,i,k,y,z,u,x,H,J){this.n11=a||1;this.n12=c||0;this.n13=d||0;this.n14=e||0;this.n21=g||0;this.n22=h||1;this.n23=o||0;this.n24=b||0;this.n31=i||0;this.n32=k||0;this.n33=y||1;this.n34=z||0;this.n41=u||0;this.n42=x||0;this.n43=H||0;this.n44=J||1;this.flat=Array(16);this.m33=new THREE.Matrix3};
+THREE.Matrix4.prototype={identity:function(){this.n11=1;this.n21=this.n14=this.n13=this.n12=0;this.n22=1;this.n32=this.n31=this.n24=this.n23=0;this.n33=1;this.n43=this.n42=this.n41=this.n34=0;this.n44=1;return this},set:function(a,c,d,e,g,h,o,b,i,k,y,z,u,x,H,J){this.n11=a;this.n12=c;this.n13=d;this.n14=e;this.n21=g;this.n22=h;this.n23=o;this.n24=b;this.n31=i;this.n32=k;this.n33=y;this.n34=z;this.n41=u;this.n42=x;this.n43=H;this.n44=J;return this},copy:function(a){this.n11=a.n11;this.n12=a.n12;this.n13=
+a.n13;this.n14=a.n14;this.n21=a.n21;this.n22=a.n22;this.n23=a.n23;this.n24=a.n24;this.n31=a.n31;this.n32=a.n32;this.n33=a.n33;this.n34=a.n34;this.n41=a.n41;this.n42=a.n42;this.n43=a.n43;this.n44=a.n44;return this},lookAt:function(a,c,d){var e=THREE.Matrix4.__tmpVec1,g=THREE.Matrix4.__tmpVec2,h=THREE.Matrix4.__tmpVec3;h.sub(a,c).normalize();e.cross(d,h).normalize();g.cross(h,e).normalize();this.n11=e.x;this.n12=e.y;this.n13=e.z;this.n14=-e.dot(a);this.n21=g.x;this.n22=g.y;this.n23=g.z;this.n24=-g.dot(a);
+this.n31=h.x;this.n32=h.y;this.n33=h.z;this.n34=-h.dot(a);this.n43=this.n42=this.n41=0;this.n44=1;return this},multiplyVector3:function(a){var c=a.x,d=a.y,e=a.z,g=1/(this.n41*c+this.n42*d+this.n43*e+this.n44);a.x=(this.n11*c+this.n12*d+this.n13*e+this.n14)*g;a.y=(this.n21*c+this.n22*d+this.n23*e+this.n24)*g;a.z=(this.n31*c+this.n32*d+this.n33*e+this.n34)*g;return a},multiplyVector4:function(a){var c=a.x,d=a.y,e=a.z,g=a.w;a.x=this.n11*c+this.n12*d+this.n13*e+this.n14*g;a.y=this.n21*c+this.n22*d+this.n23*
+e+this.n24*g;a.z=this.n31*c+this.n32*d+this.n33*e+this.n34*g;a.w=this.n41*c+this.n42*d+this.n43*e+this.n44*g;return a},crossVector:function(a){var c=new THREE.Vector4;c.x=this.n11*a.x+this.n12*a.y+this.n13*a.z+this.n14*a.w;c.y=this.n21*a.x+this.n22*a.y+this.n23*a.z+this.n24*a.w;c.z=this.n31*a.x+this.n32*a.y+this.n33*a.z+this.n34*a.w;c.w=a.w?this.n41*a.x+this.n42*a.y+this.n43*a.z+this.n44*a.w:1;return c},multiply:function(a,c){var d=a.n11,e=a.n12,g=a.n13,h=a.n14,o=a.n21,b=a.n22,i=a.n23,k=a.n24,y=a.n31,
+z=a.n32,u=a.n33,x=a.n34,H=a.n41,J=a.n42,K=a.n43,p=a.n44,U=c.n11,F=c.n12,f=c.n13,j=c.n14,q=c.n21,l=c.n22,r=c.n23,C=c.n24,m=c.n31,t=c.n32,v=c.n33,s=c.n34,n=c.n41,E=c.n42,A=c.n43,O=c.n44;this.n11=d*U+e*q+g*m+h*n;this.n12=d*F+e*l+g*t+h*E;this.n13=d*f+e*r+g*v+h*A;this.n14=d*j+e*C+g*s+h*O;this.n21=o*U+b*q+i*m+k*n;this.n22=o*F+b*l+i*t+k*E;this.n23=o*f+b*r+i*v+k*A;this.n24=o*j+b*C+i*s+k*O;this.n31=y*U+z*q+u*m+x*n;this.n32=y*F+z*l+u*t+x*E;this.n33=y*f+z*r+u*v+x*A;this.n34=y*j+z*C+u*s+x*O;this.n41=H*U+J*q+
+K*m+p*n;this.n42=H*F+J*l+K*t+p*E;this.n43=H*f+J*r+K*v+p*A;this.n44=H*j+J*C+K*s+p*O;return this},multiplySelf:function(a){var c=this.n11,d=this.n12,e=this.n13,g=this.n14,h=this.n21,o=this.n22,b=this.n23,i=this.n24,k=this.n31,y=this.n32,z=this.n33,u=this.n34,x=this.n41,H=this.n42,J=this.n43,K=this.n44,p=a.n11,U=a.n21,F=a.n31,f=a.n41,j=a.n12,q=a.n22,l=a.n32,r=a.n42,C=a.n13,m=a.n23,t=a.n33,v=a.n43,s=a.n14,n=a.n24,E=a.n34;a=a.n44;this.n11=c*p+d*U+e*F+g*f;this.n12=c*j+d*q+e*l+g*r;this.n13=c*C+d*m+e*t+g*
+v;this.n14=c*s+d*n+e*E+g*a;this.n21=h*p+o*U+b*F+i*f;this.n22=h*j+o*q+b*l+i*r;this.n23=h*C+o*m+b*t+i*v;this.n24=h*s+o*n+b*E+i*a;this.n31=k*p+y*U+z*F+u*f;this.n32=k*j+y*q+z*l+u*r;this.n33=k*C+y*m+z*t+u*v;this.n34=k*s+y*n+z*E+u*a;this.n41=x*p+H*U+J*F+K*f;this.n42=x*j+H*q+J*l+K*r;this.n43=x*C+H*m+J*t+K*v;this.n44=x*s+H*n+J*E+K*a;return this},multiplyScalar:function(a){this.n11*=a;this.n12*=a;this.n13*=a;this.n14*=a;this.n21*=a;this.n22*=a;this.n23*=a;this.n24*=a;this.n31*=a;this.n32*=a;this.n33*=a;this.n34*=
+a;this.n41*=a;this.n42*=a;this.n43*=a;this.n44*=a;return this},determinant:function(){var a=this.n11,c=this.n12,d=this.n13,e=this.n14,g=this.n21,h=this.n22,o=this.n23,b=this.n24,i=this.n31,k=this.n32,y=this.n33,z=this.n34,u=this.n41,x=this.n42,H=this.n43,J=this.n44;return e*o*k*u-d*b*k*u-e*h*y*u+c*b*y*u+d*h*z*u-c*o*z*u-e*o*i*x+d*b*i*x+e*g*y*x-a*b*y*x-d*g*z*x+a*o*z*x+e*h*i*H-c*b*i*H-e*g*k*H+a*b*k*H+c*g*z*H-a*h*z*H-d*h*i*J+c*o*i*J+d*g*k*J-a*o*k*J-c*g*y*J+a*h*y*J},transpose:function(){function a(c,d,
+e){var g=c[d];c[d]=c[e];c[e]=g}a(this,"n21","n12");a(this,"n31","n13");a(this,"n32","n23");a(this,"n41","n14");a(this,"n42","n24");a(this,"n43","n34");return this},clone:function(){var a=new THREE.Matrix4;a.n11=this.n11;a.n12=this.n12;a.n13=this.n13;a.n14=this.n14;a.n21=this.n21;a.n22=this.n22;a.n23=this.n23;a.n24=this.n24;a.n31=this.n31;a.n32=this.n32;a.n33=this.n33;a.n34=this.n34;a.n41=this.n41;a.n42=this.n42;a.n43=this.n43;a.n44=this.n44;return a},flatten:function(){var a=this.flat;a[0]=this.n11;
+a[1]=this.n21;a[2]=this.n31;a[3]=this.n41;a[4]=this.n12;a[5]=this.n22;a[6]=this.n32;a[7]=this.n42;a[8]=this.n13;a[9]=this.n23;a[10]=this.n33;a[11]=this.n43;a[12]=this.n14;a[13]=this.n24;a[14]=this.n34;a[15]=this.n44;return a},setTranslation:function(a,c,d){this.set(1,0,0,a,0,1,0,c,0,0,1,d,0,0,0,1);return this},setScale:function(a,c,d){this.set(a,0,0,0,0,c,0,0,0,0,d,0,0,0,0,1);return this},setRotX:function(a){var c=Math.cos(a);a=Math.sin(a);this.set(1,0,0,0,0,c,-a,0,0,a,c,0,0,0,0,1);return this},setRotY:function(a){var c=
+Math.cos(a);a=Math.sin(a);this.set(c,0,a,0,0,1,0,0,-a,0,c,0,0,0,0,1);return this},setRotZ:function(a){var c=Math.cos(a);a=Math.sin(a);this.set(c,-a,0,0,a,c,0,0,0,0,1,0,0,0,0,1);return this},setRotAxis:function(a,c){var d=Math.cos(c),e=Math.sin(c),g=1-d,h=a.x,o=a.y,b=a.z,i=g*h,k=g*o;this.set(i*h+d,i*o-e*b,i*b+e*o,0,i*o+e*b,k*o+d,k*b-e*h,0,i*b-e*o,k*b+e*h,g*b*b+d,0,0,0,0,1);return this},toString:function(){return"| "+this.n11+" "+this.n12+" "+this.n13+" "+this.n14+" |\n| "+this.n21+" "+this.n22+" "+
+this.n23+" "+this.n24+" |\n| "+this.n31+" "+this.n32+" "+this.n33+" "+this.n34+" |\n| "+this.n41+" "+this.n42+" "+this.n43+" "+this.n44+" |"}};THREE.Matrix4.translationMatrix=function(a,c,d){var e=new THREE.Matrix4;e.setTranslation(a,c,d);return e};THREE.Matrix4.scaleMatrix=function(a,c,d){var e=new THREE.Matrix4;e.setScale(a,c,d);return e};THREE.Matrix4.rotationXMatrix=function(a){var c=new THREE.Matrix4;c.setRotX(a);return c};
+THREE.Matrix4.rotationYMatrix=function(a){var c=new THREE.Matrix4;c.setRotY(a);return c};THREE.Matrix4.rotationZMatrix=function(a){var c=new THREE.Matrix4;c.setRotZ(a);return c};THREE.Matrix4.rotationAxisAngleMatrix=function(a,c){var d=new THREE.Matrix4;d.setRotAxis(a,c);return d};
+THREE.Matrix4.makeInvert=function(a){var c=a.n11,d=a.n12,e=a.n13,g=a.n14,h=a.n21,o=a.n22,b=a.n23,i=a.n24,k=a.n31,y=a.n32,z=a.n33,u=a.n34,x=a.n41,H=a.n42,J=a.n43,K=a.n44,p=new THREE.Matrix4;p.n11=b*u*H-i*z*H+i*y*J-o*u*J-b*y*K+o*z*K;p.n12=g*z*H-e*u*H-g*y*J+d*u*J+e*y*K-d*z*K;p.n13=e*i*H-g*b*H+g*o*J-d*i*J-e*o*K+d*b*K;p.n14=g*b*y-e*i*y-g*o*z+d*i*z+e*o*u-d*b*u;p.n21=i*z*x-b*u*x-i*k*J+h*u*J+b*k*K-h*z*K;p.n22=e*u*x-g*z*x+g*k*J-c*u*J-e*k*K+c*z*K;p.n23=g*b*x-e*i*x-g*h*J+c*i*J+e*h*K-c*b*K;p.n24=e*i*k-g*b*k+
+g*h*z-c*i*z-e*h*u+c*b*u;p.n31=o*u*x-i*y*x+i*k*H-h*u*H-o*k*K+h*y*K;p.n32=g*y*x-d*u*x-g*k*H+c*u*H+d*k*K-c*y*K;p.n33=e*i*x-g*o*x+g*h*H-c*i*H-d*h*K+c*o*K;p.n34=g*o*k-d*i*k-g*h*y+c*i*y+d*h*u-c*o*u;p.n41=b*y*x-o*z*x-b*k*H+h*z*H+o*k*J-h*y*J;p.n42=d*z*x-e*y*x+e*k*H-c*z*H-d*k*J+c*y*J;p.n43=e*o*x-d*b*x-e*h*H+c*b*H+d*h*J-c*o*J;p.n44=d*b*k-e*o*k+e*h*y-c*b*y-d*h*z+c*o*z;p.multiplyScalar(1/a.determinant());return p};
+THREE.Matrix4.makeInvert3x3=function(a){var c=a.flatten();a=a.m33;var d=a.m,e=c[10]*c[5]-c[6]*c[9],g=-c[10]*c[1]+c[2]*c[9],h=c[6]*c[1]-c[2]*c[5],o=-c[10]*c[4]+c[6]*c[8],b=c[10]*c[0]-c[2]*c[8],i=-c[6]*c[0]+c[2]*c[4],k=c[9]*c[4]-c[5]*c[8],y=-c[9]*c[0]+c[1]*c[8],z=c[5]*c[0]-c[1]*c[4];c=c[0]*e+c[1]*o+c[2]*k;if(c==0)throw"matrix not invertible";c=1/c;d[0]=c*e;d[1]=c*g;d[2]=c*h;d[3]=c*o;d[4]=c*b;d[5]=c*i;d[6]=c*k;d[7]=c*y;d[8]=c*z;return a};
+THREE.Matrix4.makeFrustum=function(a,c,d,e,g,h){var o,b,i;o=new THREE.Matrix4;b=2*g/(c-a);i=2*g/(e-d);a=(c+a)/(c-a);d=(e+d)/(e-d);e=-(h+g)/(h-g);g=-2*h*g/(h-g);o.n11=b;o.n12=0;o.n13=a;o.n14=0;o.n21=0;o.n22=i;o.n23=d;o.n24=0;o.n31=0;o.n32=0;o.n33=e;o.n34=g;o.n41=0;o.n42=0;o.n43=-1;o.n44=0;return o};THREE.Matrix4.makePerspective=function(a,c,d,e){var g;a=d*Math.tan(a*Math.PI/360);g=-a;return THREE.Matrix4.makeFrustum(g*c,a*c,g,a,d,e)};
+THREE.Matrix4.makeOrtho=function(a,c,d,e,g,h){var o,b,i,k;o=new THREE.Matrix4;b=c-a;i=d-e;k=h-g;a=(c+a)/b;d=(d+e)/i;g=(h+g)/k;o.n11=2/b;o.n12=0;o.n13=0;o.n14=-a;o.n21=0;o.n22=2/i;o.n23=0;o.n24=-d;o.n31=0;o.n32=0;o.n33=-2/k;o.n34=-g;o.n41=0;o.n42=0;o.n43=0;o.n44=1;return o};THREE.Matrix4.__tmpVec1=new THREE.Vector3;THREE.Matrix4.__tmpVec2=new THREE.Vector3;THREE.Matrix4.__tmpVec3=new THREE.Vector3;
+THREE.Vertex=function(a,c){this.position=a||new THREE.Vector3;this.positionWorld=new THREE.Vector3;this.positionScreen=new THREE.Vector4;this.normal=c||new THREE.Vector3;this.normalWorld=new THREE.Vector3;this.normalScreen=new THREE.Vector3;this.tangent=new THREE.Vector4;this.__visible=true};THREE.Vertex.prototype={toString:function(){return"THREE.Vertex ( position: "+this.position+", normal: "+this.normal+" )"}};
+THREE.Face3=function(a,c,d,e,g){this.a=a;this.b=c;this.c=d;this.centroid=new THREE.Vector3;this.normal=e instanceof THREE.Vector3?e:new THREE.Vector3;this.vertexNormals=e instanceof Array?e:[];this.materials=g instanceof Array?g:[g]};THREE.Face3.prototype={toString:function(){return"THREE.Face3 ( "+this.a+", "+this.b+", "+this.c+" )"}};
+THREE.Face4=function(a,c,d,e,g,h){this.a=a;this.b=c;this.c=d;this.d=e;this.centroid=new THREE.Vector3;this.normal=g instanceof THREE.Vector3?g:new THREE.Vector3;this.vertexNormals=g instanceof Array?g:[];this.materials=h instanceof Array?h:[h]};THREE.Face4.prototype={toString:function(){return"THREE.Face4 ( "+this.a+", "+this.b+", "+this.c+" "+this.d+" )"}};THREE.UV=function(a,c){this.u=a||0;this.v=c||0};
+THREE.UV.prototype={copy:function(a){this.u=a.u;this.v=a.v},toString:function(){return"THREE.UV ("+this.u+", "+this.v+")"}};THREE.Geometry=function(){this.vertices=[];this.faces=[];this.uvs=[];this.boundingSphere=this.boundingBox=null;this.geometryChunks={};this.hasTangents=false};
+THREE.Geometry.prototype={computeCentroids:function(){var a,c,d;a=0;for(c=this.faces.length;a<c;a++){d=this.faces[a];d.centroid.set(0,0,0);if(d instanceof THREE.Face3){d.centroid.addSelf(this.vertices[d.a].position);d.centroid.addSelf(this.vertices[d.b].position);d.centroid.addSelf(this.vertices[d.c].position);d.centroid.divideScalar(3)}else if(d instanceof THREE.Face4){d.centroid.addSelf(this.vertices[d.a].position);d.centroid.addSelf(this.vertices[d.b].position);d.centroid.addSelf(this.vertices[d.c].position);
+d.centroid.addSelf(this.vertices[d.d].position);d.centroid.divideScalar(4)}}},computeFaceNormals:function(a){var c,d,e,g,h,o,b=new THREE.Vector3,i=new THREE.Vector3;e=0;for(g=this.vertices.length;e<g;e++){h=this.vertices[e];h.normal.set(0,0,0)}e=0;for(g=this.faces.length;e<g;e++){h=this.faces[e];if(a&&h.vertexNormals.length){b.set(0,0,0);c=0;for(d=h.normal.length;c<d;c++)b.addSelf(h.vertexNormals[c]);b.divideScalar(3)}else{c=this.vertices[h.a];d=this.vertices[h.b];o=this.vertices[h.c];b.sub(o.position,
+d.position);i.sub(c.position,d.position);b.crossSelf(i)}b.isZero()||b.normalize();h.normal.copy(b)}},computeVertexNormals:function(){var a,c,d,e;if(this.__tmpVertices==undefined){e=this.__tmpVertices=Array(this.vertices.length);a=0;for(c=this.vertices.length;a<c;a++)e[a]=new THREE.Vector3;a=0;for(c=this.faces.length;a<c;a++){d=this.faces[a];if(d instanceof THREE.Face3)d.vertexNormals=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];else if(d instanceof THREE.Face4)d.vertexNormals=[new THREE.Vector3,
+new THREE.Vector3,new THREE.Vector3,new THREE.Vector3]}}else{e=this.__tmpVertices;a=0;for(c=this.vertices.length;a<c;a++)e[a].set(0,0,0)}a=0;for(c=this.faces.length;a<c;a++){d=this.faces[a];if(d instanceof THREE.Face3){e[d.a].addSelf(d.normal);e[d.b].addSelf(d.normal);e[d.c].addSelf(d.normal)}else if(d instanceof THREE.Face4){e[d.a].addSelf(d.normal);e[d.b].addSelf(d.normal);e[d.c].addSelf(d.normal);e[d.d].addSelf(d.normal)}}a=0;for(c=this.vertices.length;a<c;a++)e[a].normalize();a=0;for(c=this.faces.length;a<
+c;a++){d=this.faces[a];if(d instanceof THREE.Face3){d.vertexNormals[0].copy(e[d.a]);d.vertexNormals[1].copy(e[d.b]);d.vertexNormals[2].copy(e[d.c])}else if(d instanceof THREE.Face4){d.vertexNormals[0].copy(e[d.a]);d.vertexNormals[1].copy(e[d.b]);d.vertexNormals[2].copy(e[d.c]);d.vertexNormals[3].copy(e[d.d])}}},computeTangents:function(){function a(s,n,E,A,O,N,G){h=s.vertices[n].position;o=s.vertices[E].position;b=s.vertices[A].position;i=g[O];k=g[N];y=g[G];z=o.x-h.x;u=b.x-h.x;x=o.y-h.y;H=b.y-h.y;
+J=o.z-h.z;K=b.z-h.z;p=k.u-i.u;U=y.u-i.u;F=k.v-i.v;f=y.v-i.v;j=1/(p*f-U*F);r.set((f*z-F*u)*j,(f*x-F*H)*j,(f*J-F*K)*j);C.set((p*u-U*z)*j,(p*H-U*x)*j,(p*K-U*J)*j);q[n].addSelf(r);q[E].addSelf(r);q[A].addSelf(r);l[n].addSelf(C);l[E].addSelf(C);l[A].addSelf(C)}var c,d,e,g,h,o,b,i,k,y,z,u,x,H,J,K,p,U,F,f,j,q=[],l=[],r=new THREE.Vector3,C=new THREE.Vector3,m=new THREE.Vector3,t=new THREE.Vector3,v=new THREE.Vector3;c=0;for(d=this.vertices.length;c<d;c++){q[c]=new THREE.Vector3;l[c]=new THREE.Vector3}c=0;
+for(d=this.faces.length;c<d;c++){e=this.faces[c];g=this.uvs[c];if(e instanceof THREE.Face3){a(this,e.a,e.b,e.c,0,1,2);this.vertices[e.a].normal.copy(e.vertexNormals[0]);this.vertices[e.b].normal.copy(e.vertexNormals[1]);this.vertices[e.c].normal.copy(e.vertexNormals[2])}else if(e instanceof THREE.Face4){a(this,e.a,e.b,e.c,0,1,2);a(this,e.a,e.b,e.d,0,1,3);this.vertices[e.a].normal.copy(e.vertexNormals[0]);this.vertices[e.b].normal.copy(e.vertexNormals[1]);this.vertices[e.c].normal.copy(e.vertexNormals[2]);
+this.vertices[e.d].normal.copy(e.vertexNormals[3])}}c=0;for(d=this.vertices.length;c<d;c++){v.copy(this.vertices[c].normal);e=q[c];m.copy(e);m.subSelf(v.multiplyScalar(v.dot(e))).normalize();t.cross(this.vertices[c].normal,e);e=t.dot(l[c]);e=e<0?-1:1;this.vertices[c].tangent.set(m.x,m.y,m.z,e)}this.hasTangents=true},computeBoundingBox:function(){var a;if(this.vertices.length>0){this.boundingBox={x:[this.vertices[0].position.x,this.vertices[0].position.x],y:[this.vertices[0].position.y,this.vertices[0].position.y],
+z:[this.vertices[0].position.z,this.vertices[0].position.z]};for(var c=1,d=this.vertices.length;c<d;c++){a=this.vertices[c];if(a.position.x<this.boundingBox.x[0])this.boundingBox.x[0]=a.position.x;else if(a.position.x>this.boundingBox.x[1])this.boundingBox.x[1]=a.position.x;if(a.position.y<this.boundingBox.y[0])this.boundingBox.y[0]=a.position.y;else if(a.position.y>this.boundingBox.y[1])this.boundingBox.y[1]=a.position.y;if(a.position.z<this.boundingBox.z[0])this.boundingBox.z[0]=a.position.z;else if(a.position.z>
+this.boundingBox.z[1])this.boundingBox.z[1]=a.position.z}}},computeBoundingSphere:function(){for(var a=this.boundingSphere===null?0:this.boundingSphere.radius,c=0,d=this.vertices.length;c<d;c++)a=Math.max(a,this.vertices[c].position.length());this.boundingSphere={radius:a}},sortFacesByMaterial:function(){function a(y){var z=[];c=0;for(d=y.length;c<d;c++)y[c]==undefined?z.push("undefined"):z.push(y[c].toString());return z.join("_")}var c,d,e,g,h,o,b,i,k={};e=0;for(g=this.faces.length;e<g;e++){h=this.faces[e];
+o=h.materials;b=a(o);if(k[b]==undefined)k[b]={hash:b,counter:0};i=k[b].hash+"_"+k[b].counter;if(this.geometryChunks[i]==undefined)this.geometryChunks[i]={faces:[],materials:o,vertices:0};h=h instanceof THREE.Face3?3:4;if(this.geometryChunks[i].vertices+h>65535){k[b].counter+=1;i=k[b].hash+"_"+k[b].counter;if(this.geometryChunks[i]==undefined)this.geometryChunks[i]={faces:[],materials:o,vertices:0}}this.geometryChunks[i].faces.push(e);this.geometryChunks[i].vertices+=h}},toString:function(){return"THREE.Geometry ( vertices: "+
+this.vertices+", faces: "+this.faces+", uvs: "+this.uvs+" )"}};
+THREE.Camera=function(a,c,d,e){this.fov=a;this.aspect=c;this.near=d;this.far=e;this.position=new THREE.Vector3;this.target={position:new THREE.Vector3};this.autoUpdateMatrix=true;this.projectionMatrix=null;this.matrix=new THREE.Matrix4;this.up=new THREE.Vector3(0,1,0);this.tmpVec=new THREE.Vector3;this.translateX=function(g){this.tmpVec.sub(this.target.position,this.position).normalize().multiplyScalar(g);this.tmpVec.crossSelf(this.up);this.position.addSelf(this.tmpVec);this.target.position.addSelf(this.tmpVec)};
+this.translateZ=function(g){this.tmpVec.sub(this.target.position,this.position).normalize().multiplyScalar(g);this.position.subSelf(this.tmpVec);this.target.position.subSelf(this.tmpVec)};this.updateMatrix=function(){this.matrix.lookAt(this.position,this.target.position,this.up)};this.updateProjectionMatrix=function(){this.projectionMatrix=THREE.Matrix4.makePerspective(this.fov,this.aspect,this.near,this.far)};this.updateProjectionMatrix()};
+THREE.Camera.prototype={toString:function(){return"THREE.Camera ( "+this.position+", "+this.target.position+" )"}};THREE.Light=function(a){this.color=new THREE.Color(a)};THREE.AmbientLight=function(a){THREE.Light.call(this,a)};THREE.AmbientLight.prototype=new THREE.Light;THREE.AmbientLight.prototype.constructor=THREE.AmbientLight;THREE.DirectionalLight=function(a,c){THREE.Light.call(this,a);this.position=new THREE.Vector3(0,1,0);this.intensity=c||1};THREE.DirectionalLight.prototype=new THREE.Light;
+THREE.DirectionalLight.prototype.constructor=THREE.DirectionalLight;THREE.PointLight=function(a,c){THREE.Light.call(this,a);this.position=new THREE.Vector3;this.intensity=c||1};THREE.PointLight.prototype=new THREE.Light;THREE.PointLight.prototype.constructor=THREE.PointLight;
+THREE.Object3D=function(){this.id=THREE.Object3DCounter.value++;this.position=new THREE.Vector3;this.rotation=new THREE.Vector3;this.scale=new THREE.Vector3(1,1,1);this.matrix=new THREE.Matrix4;this.rotationMatrix=new THREE.Matrix4;this.tmpMatrix=new THREE.Matrix4;this.screen=new THREE.Vector3;this.visible=this.autoUpdateMatrix=true};
+THREE.Object3D.prototype={updateMatrix:function(){var a=this.position,c=this.rotation,d=this.scale,e=this.tmpMatrix;this.matrix.setTranslation(a.x,a.y,a.z);this.rotationMatrix.setRotX(c.x);if(c.y!=0){e.setRotY(c.y);this.rotationMatrix.multiplySelf(e)}if(c.z!=0){e.setRotZ(c.z);this.rotationMatrix.multiplySelf(e)}this.matrix.multiplySelf(this.rotationMatrix);if(d.x!=0||d.y!=0||d.z!=0){e.setScale(d.x,d.y,d.z);this.matrix.multiplySelf(e)}}};THREE.Object3DCounter={value:0};
+THREE.Particle=function(a){THREE.Object3D.call(this);this.materials=a instanceof Array?a:[a];this.autoUpdateMatrix=false};THREE.Particle.prototype=new THREE.Object3D;THREE.Particle.prototype.constructor=THREE.Particle;THREE.ParticleSystem=function(a,c){THREE.Object3D.call(this);this.geometry=a;this.materials=c instanceof Array?c:[c];this.autoUpdateMatrix=false};THREE.ParticleSystem.prototype=new THREE.Object3D;THREE.ParticleSystem.prototype.constructor=THREE.ParticleSystem;
+THREE.Line=function(a,c,d){THREE.Object3D.call(this);this.geometry=a;this.materials=c instanceof Array?c:[c];this.type=d!=undefined?d:THREE.LineStrip};THREE.LineStrip=0;THREE.LinePieces=1;THREE.Line.prototype=new THREE.Object3D;THREE.Line.prototype.constructor=THREE.Line;THREE.Mesh=function(a,c){THREE.Object3D.call(this);this.geometry=a;this.materials=c instanceof Array?c:[c];this.overdraw=this.doubleSided=this.flipSided=false;this.geometry.boundingSphere||this.geometry.computeBoundingSphere()};
+THREE.Mesh.prototype=new THREE.Object3D;THREE.Mesh.prototype.constructor=THREE.Mesh;THREE.FlatShading=0;THREE.SmoothShading=1;THREE.NormalBlending=0;THREE.AdditiveBlending=1;THREE.SubtractiveBlending=2;
+THREE.LineBasicMaterial=function(a){this.color=new THREE.Color(16777215);this.opacity=1;this.blending=THREE.NormalBlending;this.linewidth=1;this.linejoin=this.linecap="round";if(a){a.color!==undefined&&this.color.setHex(a.color);if(a.opacity!==undefined)this.opacity=a.opacity;if(a.blending!==undefined)this.blending=a.blending;if(a.linewidth!==undefined)this.linewidth=a.linewidth;if(a.linecap!==undefined)this.linecap=a.linecap;if(a.linejoin!==undefined)this.linejoin=a.linejoin}};
+THREE.LineBasicMaterial.prototype={toString:function(){return"THREE.LineBasicMaterial (<br/>color: "+this.color+"<br/>opacity: "+this.opacity+"<br/>blending: "+this.blending+"<br/>linewidth: "+this.linewidth+"<br/>linecap: "+this.linecap+"<br/>linejoin: "+this.linejoin+"<br/>)"}};
+THREE.MeshBasicMaterial=function(a){this.id=THREE.MeshBasicMaterialCounter.value++;this.color=new THREE.Color(16777215);this.env_map=this.map=null;this.combine=THREE.MultiplyOperation;this.reflectivity=1;this.refraction_ratio=0.98;this.fog=true;this.opacity=1;this.shading=THREE.SmoothShading;this.blending=THREE.NormalBlending;this.wireframe=false;this.wireframe_linewidth=1;this.wireframe_linejoin=this.wireframe_linecap="round";if(a){a.color!==undefined&&this.color.setHex(a.color);if(a.map!==undefined)this.map=
+a.map;if(a.env_map!==undefined)this.env_map=a.env_map;if(a.combine!==undefined)this.combine=a.combine;if(a.reflectivity!==undefined)this.reflectivity=a.reflectivity;if(a.refraction_ratio!==undefined)this.refraction_ratio=a.refraction_ratio;if(a.fog!==undefined)this.fog=a.fog;if(a.opacity!==undefined)this.opacity=a.opacity;if(a.shading!==undefined)this.shading=a.shading;if(a.blending!==undefined)this.blending=a.blending;if(a.wireframe!==undefined)this.wireframe=a.wireframe;if(a.wireframe_linewidth!==
+undefined)this.wireframe_linewidth=a.wireframe_linewidth;if(a.wireframe_linecap!==undefined)this.wireframe_linecap=a.wireframe_linecap;if(a.wireframe_linejoin!==undefined)this.wireframe_linejoin=a.wireframe_linejoin}};
+THREE.MeshBasicMaterial.prototype={toString:function(){return"THREE.MeshBasicMaterial (<br/>id: "+this.id+"<br/>color: "+this.color+"<br/>map: "+this.map+"<br/>env_map: "+this.env_map+"<br/>combine: "+this.combine+"<br/>reflectivity: "+this.reflectivity+"<br/>refraction_ratio: "+this.refraction_ratio+"<br/>opacity: "+this.opacity+"<br/>blending: "+this.blending+"<br/>wireframe: "+this.wireframe+"<br/>wireframe_linewidth: "+this.wireframe_linewidth+"<br/>wireframe_linecap: "+this.wireframe_linecap+
+"<br/>wireframe_linejoin: "+this.wireframe_linejoin+"<br/>)"}};THREE.MeshBasicMaterialCounter={value:0};
+THREE.MeshLambertMaterial=function(a){this.id=THREE.MeshLambertMaterialCounter.value++;this.color=new THREE.Color(16777215);this.env_map=this.map=null;this.combine=THREE.MultiplyOperation;this.reflectivity=1;this.refraction_ratio=0.98;this.fog=true;this.opacity=1;this.shading=THREE.SmoothShading;this.blending=THREE.NormalBlending;this.wireframe=false;this.wireframe_linewidth=1;this.wireframe_linejoin=this.wireframe_linecap="round";if(a){a.color!==undefined&&this.color.setHex(a.color);if(a.map!==undefined)this.map=
+a.map;if(a.env_map!==undefined)this.env_map=a.env_map;if(a.combine!==undefined)this.combine=a.combine;if(a.reflectivity!==undefined)this.reflectivity=a.reflectivity;if(a.refraction_ratio!==undefined)this.refraction_ratio=a.refraction_ratio;if(a.fog!==undefined)this.fog=a.fog;if(a.opacity!==undefined)this.opacity=a.opacity;if(a.shading!==undefined)this.shading=a.shading;if(a.blending!==undefined)this.blending=a.blending;if(a.wireframe!==undefined)this.wireframe=a.wireframe;if(a.wireframe_linewidth!==
+undefined)this.wireframe_linewidth=a.wireframe_linewidth;if(a.wireframe_linecap!==undefined)this.wireframe_linecap=a.wireframe_linecap;if(a.wireframe_linejoin!==undefined)this.wireframe_linejoin=a.wireframe_linejoin}};
+THREE.MeshLambertMaterial.prototype={toString:function(){return"THREE.MeshLambertMaterial (<br/>id: "+this.id+"<br/>color: "+this.color+"<br/>map: "+this.map+"<br/>env_map: "+this.env_map+"<br/>combine: "+this.combine+"<br/>reflectivity: "+this.reflectivity+"<br/>refraction_ratio: "+this.refraction_ratio+"<br/>opacity: "+this.opacity+"<br/>shading: "+this.shading+"<br/>blending: "+this.blending+"<br/>wireframe: "+this.wireframe+"<br/>wireframe_linewidth: "+this.wireframe_linewidth+"<br/>wireframe_linecap: "+
+this.wireframe_linecap+"<br/>wireframe_linejoin: "+this.wireframe_linejoin+"<br/> )"}};THREE.MeshLambertMaterialCounter={value:0};
+THREE.MeshPhongMaterial=function(a){this.id=THREE.MeshPhongMaterialCounter.value++;this.color=new THREE.Color(16777215);this.ambient=new THREE.Color(328965);this.specular=new THREE.Color(1118481);this.shininess=30;this.env_map=this.specular_map=this.map=null;this.combine=THREE.MultiplyOperation;this.reflectivity=1;this.refraction_ratio=0.98;this.fog=true;this.opacity=1;this.shading=THREE.SmoothShading;this.blending=THREE.NormalBlending;this.wireframe=false;this.wireframe_linewidth=1;this.wireframe_linejoin=
+this.wireframe_linecap="round";if(a){if(a.color!==undefined)this.color=new THREE.Color(a.color);if(a.ambient!==undefined)this.ambient=new THREE.Color(a.ambient);if(a.specular!==undefined)this.specular=new THREE.Color(a.specular);if(a.shininess!==undefined)this.shininess=a.shininess;if(a.map!==undefined)this.map=a.map;if(a.specular_map!==undefined)this.specular_map=a.specular_map;if(a.env_map!==undefined)this.env_map=a.env_map;if(a.combine!==undefined)this.combine=a.combine;if(a.reflectivity!==undefined)this.reflectivity=
+a.reflectivity;if(a.refraction_ratio!==undefined)this.refraction_ratio=a.refraction_ratio;if(a.fog!==undefined)this.fog=a.fog;if(a.opacity!==undefined)this.opacity=a.opacity;if(a.shading!==undefined)this.shading=a.shading;if(a.blending!==undefined)this.blending=a.blending;if(a.wireframe!==undefined)this.wireframe=a.wireframe;if(a.wireframe_linewidth!==undefined)this.wireframe_linewidth=a.wireframe_linewidth;if(a.wireframe_linecap!==undefined)this.wireframe_linecap=a.wireframe_linecap;if(a.wireframe_linejoin!==
+undefined)this.wireframe_linejoin=a.wireframe_linejoin}};
+THREE.MeshPhongMaterial.prototype={toString:function(){return"THREE.MeshPhongMaterial (<br/>id: "+this.id+"<br/>color: "+this.color+"<br/>ambient: "+this.ambient+"<br/>specular: "+this.specular+"<br/>shininess: "+this.shininess+"<br/>map: "+this.map+"<br/>specular_map: "+this.specular_map+"<br/>env_map: "+this.env_map+"<br/>combine: "+this.combine+"<br/>reflectivity: "+this.reflectivity+"<br/>refraction_ratio: "+this.refraction_ratio+"<br/>opacity: "+this.opacity+"<br/>shading: "+this.shading+"<br/>wireframe: "+
+this.wireframe+"<br/>wireframe_linewidth: "+this.wireframe_linewidth+"<br/>wireframe_linecap: "+this.wireframe_linecap+"<br/>wireframe_linejoin: "+this.wireframe_linejoin+"<br/>)"}};THREE.MeshPhongMaterialCounter={value:0};
+THREE.MeshDepthMaterial=function(a){this.opacity=1;this.shading=THREE.SmoothShading;this.blending=THREE.NormalBlending;this.wireframe=false;this.wireframe_linewidth=1;this.wireframe_linejoin=this.wireframe_linecap="round";if(a){if(a.opacity!==undefined)this.opacity=a.opacity;if(a.blending!==undefined)this.blending=a.blending}};THREE.MeshDepthMaterial.prototype={toString:function(){return"THREE.MeshDepthMaterial"}};
+THREE.MeshNormalMaterial=function(a){this.opacity=1;this.shading=THREE.FlatShading;this.blending=THREE.NormalBlending;if(a){if(a.opacity!==undefined)this.opacity=a.opacity;if(a.shading!==undefined)this.shading=a.shading;if(a.blending!==undefined)this.blending=a.blending}};THREE.MeshNormalMaterial.prototype={toString:function(){return"THREE.MeshNormalMaterial"}};THREE.MeshFaceMaterial=function(){};THREE.MeshFaceMaterial.prototype={toString:function(){return"THREE.MeshFaceMaterial"}};
+THREE.MeshShaderMaterial=function(a){this.id=THREE.MeshShaderMaterialCounter.value++;this.vertex_shader=this.fragment_shader="void main() {}";this.uniforms={};this.opacity=1;this.shading=THREE.SmoothShading;this.blending=THREE.NormalBlending;this.wireframe=false;this.wireframe_linewidth=1;this.wireframe_linejoin=this.wireframe_linecap="round";if(a){if(a.fragment_shader!==undefined)this.fragment_shader=a.fragment_shader;if(a.vertex_shader!==undefined)this.vertex_shader=a.vertex_shader;if(a.uniforms!==
+undefined)this.uniforms=a.uniforms;if(a.shading!==undefined)this.shading=a.shading;if(a.blending!==undefined)this.blending=a.blending;if(a.wireframe!==undefined)this.wireframe=a.wireframe;if(a.wireframe_linewidth!==undefined)this.wireframe_linewidth=a.wireframe_linewidth;if(a.wireframe_linecap!==undefined)this.wireframe_linecap=a.wireframe_linecap;if(a.wireframe_linejoin!==undefined)this.wireframe_linejoin=a.wireframe_linejoin}};
+THREE.MeshShaderMaterial.prototype={toString:function(){return"THREE.MeshShaderMaterial (<br/>id: "+this.id+"<br/>blending: "+this.blending+"<br/>wireframe: "+this.wireframe+"<br/>wireframe_linewidth: "+this.wireframe_linewidth+"<br/>wireframe_linecap: "+this.wireframe_linecap+"<br/>wireframe_linejoin: "+this.wireframe_linejoin+"<br/>)"}};THREE.MeshShaderMaterialCounter={value:0};
+THREE.ParticleBasicMaterial=function(a){this.color=new THREE.Color(16777215);this.map=null;this.opacity=1;this.blending=THREE.NormalBlending;this.offset=new THREE.Vector2;if(a){a.color!==undefined&&this.color.setHex(a.color);if(a.map!==undefined)this.map=a.map;if(a.opacity!==undefined)this.opacity=a.opacity;if(a.blending!==undefined)this.blending=a.blending}};
+THREE.ParticleBasicMaterial.prototype={toString:function(){return"THREE.ParticleBasicMaterial (<br/>color: "+this.color+"<br/>map: "+this.map+"<br/>opacity: "+this.opacity+"<br/>blending: "+this.blending+"<br/>)"}};THREE.ParticleCircleMaterial=function(a){this.color=new THREE.Color(16777215);this.opacity=1;this.blending=THREE.NormalBlending;if(a){a.color!==undefined&&this.color.setHex(a.color);if(a.opacity!==undefined)this.opacity=a.opacity;if(a.blending!==undefined)this.blending=a.blending}};
+THREE.ParticleCircleMaterial.prototype={toString:function(){return"THREE.ParticleCircleMaterial (<br/>color: "+this.color+"<br/>opacity: "+this.opacity+"<br/>blending: "+this.blending+"<br/>)"}};THREE.ParticleDOMMaterial=function(a){this.domElement=a};THREE.ParticleDOMMaterial.prototype={toString:function(){return"THREE.ParticleDOMMaterial ( domElement: "+this.domElement+" )"}};
+THREE.Texture=function(a,c,d,e,g,h){this.image=a;this.mapping=c!==undefined?c:new THREE.UVMapping;this.wrap_s=d!==undefined?d:THREE.ClampToEdgeWrapping;this.wrap_t=e!==undefined?e:THREE.ClampToEdgeWrapping;this.mag_filter=g!==undefined?g:THREE.LinearFilter;this.min_filter=h!==undefined?h:THREE.LinearMipMapLinearFilter};
+THREE.Texture.prototype={clone:function(){return new THREE.Texture(this.image,this.mapping,this.wrap_s,this.wrap_t,this.mag_filter,this.min_filter)},toString:function(){return"THREE.Texture (<br/>image: "+this.image+"<br/>wrap_s: "+this.wrap_s+"<br/>wrap_t: "+this.wrap_t+"<br/>mag_filter: "+this.mag_filter+"<br/>min_filter: "+this.min_filter+"<br/>)"}};THREE.MultiplyOperation=0;THREE.MixOperation=1;THREE.RepeatWrapping=0;THREE.ClampToEdgeWrapping=1;THREE.MirroredRepeatWrapping=2;
+THREE.NearestFilter=3;THREE.NearestMipMapNearestFilter=4;THREE.NearestMipMapLinearFilter=5;THREE.LinearFilter=6;THREE.LinearMipMapNearestFilter=7;THREE.LinearMipMapLinearFilter=8;THREE.ByteType=9;THREE.UnsignedByteType=10;THREE.ShortType=11;THREE.UnsignedShortType=12;THREE.IntType=13;THREE.UnsignedIntType=14;THREE.FloatType=15;THREE.AlphaFormat=16;THREE.RGBFormat=17;THREE.RGBAFormat=18;THREE.LuminanceFormat=19;THREE.LuminanceAlphaFormat=20;
+THREE.RenderTarget=function(a,c,d){this.width=a;this.height=c;d=d||{};this.wrap_s=d.wrap_s!==undefined?d.wrap_s:THREE.ClampToEdgeWrapping;this.wrap_t=d.wrap_t!==undefined?d.wrap_t:THREE.ClampToEdgeWrapping;this.mag_filter=d.mag_filter!==undefined?d.mag_filter:THREE.LinearFilter;this.min_filter=d.min_filter!==undefined?d.min_filter:THREE.LinearMipMapLinearFilter;this.format=d.format!==undefined?d.format:THREE.RGBFormat;this.type=d.type!==undefined?d.type:THREE.UnsignedByteType};
+var Uniforms={clone:function(a){var c,d,e,g={};for(c in a){g[c]={};for(d in a[c]){e=a[c][d];g[c][d]=e instanceof THREE.Color||e instanceof THREE.Vector3||e instanceof THREE.Texture?e.clone():e}}return g},merge:function(a){var c,d,e,g={};for(c=0;c<a.length;c++){e=this.clone(a[c]);for(d in e)g[d]=e[d]}return g}};THREE.CubeReflectionMapping=function(){};THREE.CubeRefractionMapping=function(){};THREE.LatitudeReflectionMapping=function(){};THREE.LatitudeRefractionMapping=function(){};
+THREE.SphericalReflectionMapping=function(){};THREE.SphericalRefractionMapping=function(){};THREE.UVMapping=function(){};
+THREE.Scene=function(){this.objects=[];this.lights=[];this.fog=null;this.addObject=function(a){this.objects.indexOf(a)===-1&&this.objects.push(a)};this.removeObject=function(a){a=this.objects.indexOf(a);a!==-1&&this.objects.splice(a,1)};this.addLight=function(a){this.lights.indexOf(a)===-1&&this.lights.push(a)};this.removeLight=function(a){a=this.lights.indexOf(a);a!==-1&&this.lights.splice(a,1)};this.toString=function(){return"THREE.Scene ( "+this.objects+" )"}};
+THREE.Fog=function(a,c,d){this.color=new THREE.Color(a);this.near=c||1;this.far=d||1E3};THREE.FogExp2=function(a,c){this.color=new THREE.Color(a);this.density=c||2.5E-4};
+THREE.Projector=function(){function a(l,r){return r.z-l.z}function c(l,r){var C=0,m=1,t=l.z+l.w,v=r.z+r.w,s=-l.z+l.w,n=-r.z+r.w;if(t>=0&&v>=0&&s>=0&&n>=0)return true;else if(t<0&&v<0||s<0&&n<0)return false;else{if(t<0)C=Math.max(C,t/(t-v));else if(v<0)m=Math.min(m,t/(t-v));if(s<0)C=Math.max(C,s/(s-n));else if(n<0)m=Math.min(m,s/(s-n));if(m<C)return false;else{l.lerpSelf(r,C);r.lerpSelf(l,1-m);return true}}}var d,e,g=[],h,o,b,i=[],k,y,z=[],u,x,H=[],J=new THREE.Vector4,K=new THREE.Vector4,p=new THREE.Matrix4,
+U=new THREE.Matrix4,F=[],f=new THREE.Vector4,j=new THREE.Vector4,q;this.projectObjects=function(l,r,C){var m=[],t,v;e=0;p.multiply(r.projectionMatrix,r.matrix);F[0]=new THREE.Vector4(p.n41-p.n11,p.n42-p.n12,p.n43-p.n13,p.n44-p.n14);F[1]=new THREE.Vector4(p.n41+p.n11,p.n42+p.n12,p.n43+p.n13,p.n44+p.n14);F[2]=new THREE.Vector4(p.n41+p.n21,p.n42+p.n22,p.n43+p.n23,p.n44+p.n24);F[3]=new THREE.Vector4(p.n41-p.n21,p.n42-p.n22,p.n43-p.n23,p.n44-p.n24);F[4]=new THREE.Vector4(p.n41-p.n31,p.n42-p.n32,p.n43-
+p.n33,p.n44-p.n34);F[5]=new THREE.Vector4(p.n41+p.n31,p.n42+p.n32,p.n43+p.n33,p.n44+p.n34);r=0;for(t=F.length;r<t;r++){v=F[r];v.divideScalar(Math.sqrt(v.x*v.x+v.y*v.y+v.z*v.z))}t=l.objects;l=0;for(r=t.length;l<r;l++){v=t[l];var s;if(!(s=!v.visible)){if(s=v instanceof THREE.Mesh){a:{s=void 0;for(var n=v.position,E=-v.geometry.boundingSphere.radius*Math.max(v.scale.x,Math.max(v.scale.y,v.scale.z)),A=0;A<6;A++){s=F[A].x*n.x+F[A].y*n.y+F[A].z*n.z+F[A].w;if(s<=E){s=false;break a}}s=true}s=!s}s=s}if(!s){d=
+g[e]=g[e]||new THREE.RenderableObject;J.copy(v.position);p.multiplyVector3(J);d.object=v;d.z=J.z;m.push(d);e++}}C&&m.sort(a);return m};this.projectScene=function(l,r,C){var m=[],t=r.near,v=r.far,s,n,E,A,O,N,G,W,P,I,L,V,S,w,M,Q;b=y=x=0;r.autoUpdateMatrix&&r.updateMatrix();p.multiply(r.projectionMatrix,r.matrix);N=this.projectObjects(l,r,true);l=0;for(s=N.length;l<s;l++){G=N[l].object;if(G.visible){G.autoUpdateMatrix&&G.updateMatrix();W=G.matrix;P=G.rotationMatrix;I=G.materials;L=G.overdraw;if(G instanceof
+THREE.Mesh){V=G.geometry;S=V.vertices;n=0;for(E=S.length;n<E;n++){w=S[n];w.positionWorld.copy(w.position);W.multiplyVector3(w.positionWorld);A=w.positionScreen;A.copy(w.positionWorld);p.multiplyVector4(A);A.x/=A.w;A.y/=A.w;w.__visible=A.z>t&&A.z<v}V=V.faces;n=0;for(E=V.length;n<E;n++){w=V[n];if(w instanceof THREE.Face3){A=S[w.a];O=S[w.b];M=S[w.c];if(A.__visible&&O.__visible&&M.__visible)if(G.doubleSided||G.flipSided!=(M.positionScreen.x-A.positionScreen.x)*(O.positionScreen.y-A.positionScreen.y)-
+(M.positionScreen.y-A.positionScreen.y)*(O.positionScreen.x-A.positionScreen.x)<0){h=i[b]=i[b]||new THREE.RenderableFace3;h.v1.positionWorld.copy(A.positionWorld);h.v2.positionWorld.copy(O.positionWorld);h.v3.positionWorld.copy(M.positionWorld);h.v1.positionScreen.copy(A.positionScreen);h.v2.positionScreen.copy(O.positionScreen);h.v3.positionScreen.copy(M.positionScreen);h.normalWorld.copy(w.normal);P.multiplyVector3(h.normalWorld);h.centroidWorld.copy(w.centroid);W.multiplyVector3(h.centroidWorld);
+h.centroidScreen.copy(h.centroidWorld);p.multiplyVector3(h.centroidScreen);M=w.vertexNormals;q=h.vertexNormalsWorld;A=0;for(O=M.length;A<O;A++){Q=q[A]=q[A]||new THREE.Vector3;Q.copy(M[A]);P.multiplyVector3(Q)}h.z=h.centroidScreen.z;h.meshMaterials=I;h.faceMaterials=w.materials;h.overdraw=L;if(G.geometry.uvs[n]){h.uvs[0]=G.geometry.uvs[n][0];h.uvs[1]=G.geometry.uvs[n][1];h.uvs[2]=G.geometry.uvs[n][2]}m.push(h);b++}}else if(w instanceof THREE.Face4){A=S[w.a];O=S[w.b];M=S[w.c];Q=S[w.d];if(A.__visible&&
+O.__visible&&M.__visible&&Q.__visible)if(G.doubleSided||G.flipSided!=((Q.positionScreen.x-A.positionScreen.x)*(O.positionScreen.y-A.positionScreen.y)-(Q.positionScreen.y-A.positionScreen.y)*(O.positionScreen.x-A.positionScreen.x)<0||(O.positionScreen.x-M.positionScreen.x)*(Q.positionScreen.y-M.positionScreen.y)-(O.positionScreen.y-M.positionScreen.y)*(Q.positionScreen.x-M.positionScreen.x)<0)){h=i[b]=i[b]||new THREE.RenderableFace3;h.v1.positionWorld.copy(A.positionWorld);h.v2.positionWorld.copy(O.positionWorld);
+h.v3.positionWorld.copy(Q.positionWorld);h.v1.positionScreen.copy(A.positionScreen);h.v2.positionScreen.copy(O.positionScreen);h.v3.positionScreen.copy(Q.positionScreen);h.normalWorld.copy(w.normal);P.multiplyVector3(h.normalWorld);h.centroidWorld.copy(w.centroid);W.multiplyVector3(h.centroidWorld);h.centroidScreen.copy(h.centroidWorld);p.multiplyVector3(h.centroidScreen);h.z=h.centroidScreen.z;h.meshMaterials=I;h.faceMaterials=w.materials;h.overdraw=L;if(G.geometry.uvs[n]){h.uvs[0]=G.geometry.uvs[n][0];
+h.uvs[1]=G.geometry.uvs[n][1];h.uvs[2]=G.geometry.uvs[n][3]}m.push(h);b++;o=i[b]=i[b]||new THREE.RenderableFace3;o.v1.positionWorld.copy(O.positionWorld);o.v2.positionWorld.copy(M.positionWorld);o.v3.positionWorld.copy(Q.positionWorld);o.v1.positionScreen.copy(O.positionScreen);o.v2.positionScreen.copy(M.positionScreen);o.v3.positionScreen.copy(Q.positionScreen);o.normalWorld.copy(h.normalWorld);o.centroidWorld.copy(h.centroidWorld);o.centroidScreen.copy(h.centroidScreen);o.z=o.centroidScreen.z;o.meshMaterials=
+I;o.faceMaterials=w.materials;o.overdraw=L;if(G.geometry.uvs[n]){o.uvs[0]=G.geometry.uvs[n][1];o.uvs[1]=G.geometry.uvs[n][2];o.uvs[2]=G.geometry.uvs[n][3]}m.push(o);b++}}}}else if(G instanceof THREE.Line){U.multiply(p,W);S=G.geometry.vertices;w=S[0];w.positionScreen.copy(w.position);U.multiplyVector4(w.positionScreen);n=1;for(E=S.length;n<E;n++){A=S[n];A.positionScreen.copy(A.position);U.multiplyVector4(A.positionScreen);O=S[n-1];f.copy(A.positionScreen);j.copy(O.positionScreen);if(c(f,j)){f.multiplyScalar(1/
+f.w);j.multiplyScalar(1/j.w);k=z[y]=z[y]||new THREE.RenderableLine;k.v1.positionScreen.copy(f);k.v2.positionScreen.copy(j);k.z=Math.max(f.z,j.z);k.materials=G.materials;m.push(k);y++}}}else if(G instanceof THREE.Particle){K.set(G.position.x,G.position.y,G.position.z,1);p.multiplyVector4(K);K.z/=K.w;if(K.z>0&&K.z<1){u=H[x]=H[x]||new THREE.RenderableParticle;u.x=K.x/K.w;u.y=K.y/K.w;u.z=K.z;u.rotation=G.rotation.z;u.scale.x=G.scale.x*Math.abs(u.x-(K.x+r.projectionMatrix.n11)/(K.w+r.projectionMatrix.n14));
+u.scale.y=G.scale.y*Math.abs(u.y-(K.y+r.projectionMatrix.n22)/(K.w+r.projectionMatrix.n24));u.materials=G.materials;m.push(u);x++}}}}C&&m.sort(a);return m};this.unprojectVector=function(l,r){var C=THREE.Matrix4.makeInvert(r.matrix);C.multiplySelf(THREE.Matrix4.makeInvert(r.projectionMatrix));C.multiplyVector3(l);return l}};
+THREE.DOMRenderer=function(){THREE.Renderer.call(this);var a=null,c=new THREE.Projector,d,e,g,h;this.domElement=document.createElement("div");this.setSize=function(o,b){d=o;e=b;g=d/2;h=e/2};this.render=function(o,b){var i,k,y,z,u,x,H,J;a=c.projectScene(o,b);i=0;for(k=a.length;i<k;i++){u=a[i];if(u instanceof THREE.RenderableParticle){H=u.x*g+g;J=u.y*h+h;y=0;for(z=u.material.length;y<z;y++){x=u.material[y];if(x instanceof THREE.ParticleDOMMaterial){x=x.domElement;x.style.left=H+"px";x.style.top=J+"px"}}}}}};
+THREE.CanvasRenderer=function(){function a(ea){if(u!=ea)k.globalAlpha=u=ea}function c(ea){if(x!=ea){switch(ea){case THREE.NormalBlending:k.globalCompositeOperation="source-over";break;case THREE.AdditiveBlending:k.globalCompositeOperation="lighter";break;case THREE.SubtractiveBlending:k.globalCompositeOperation="darker"}x=ea}}var d=null,e=new THREE.Projector,g=document.createElement("canvas"),h,o,b,i,k=g.getContext("2d"),y=new THREE.Color(0),z=0,u=1,x=0,H=null,J=null,K=1,p,U,F,f,j,q,l,r,C,m=new THREE.Color,
+t=new THREE.Color,v=new THREE.Color,s=new THREE.Color,n=new THREE.Color,E,A,O,N,G,W,P,I,L,V=new THREE.Rectangle,S=new THREE.Rectangle,w=new THREE.Rectangle,M=false,Q=new THREE.Color,da=new THREE.Color,ba=new THREE.Color,Z=new THREE.Color,ja=Math.PI*2,Y=new THREE.Vector3,qa,ka,fa,ha,sa,ua,va=16;qa=document.createElement("canvas");qa.width=qa.height=2;ka=qa.getContext("2d");ka.fillStyle="rgba(0,0,0,1)";ka.fillRect(0,0,2,2);fa=ka.getImageData(0,0,2,2);ha=fa.data;sa=document.createElement("canvas");sa.width=
+sa.height=va;ua=sa.getContext("2d");ua.translate(-va/2,-va/2);ua.scale(va,va);va--;this.domElement=g;this.sortElements=this.sortObjects=this.autoClear=true;this.setSize=function(ea,ra){h=ea;o=ra;b=h/2;i=o/2;g.width=h;g.height=o;V.set(-b,-i,b,i);u=1;x=0;J=H=null;K=1};this.setClearColor=function(ea,ra){y.setHex(ea);z=ra;S.set(-b,-i,b,i);k.setTransform(1,0,0,-1,b,i);this.clear()};this.clear=function(){if(!S.isEmpty()){S.inflate(1);S.minSelf(V);if(y.hex==0&&z==0)k.clearRect(S.getX(),S.getY(),S.getWidth(),
+S.getHeight());else{c(THREE.NormalBlending);a(1);k.fillStyle="rgba("+Math.floor(y.r*255)+","+Math.floor(y.g*255)+","+Math.floor(y.b*255)+","+z+")";k.fillRect(S.getX(),S.getY(),S.getWidth(),S.getHeight())}S.empty()}};this.render=function(ea,ra){function Ma(B){var X,T,D,R=B.lights;da.setRGB(0,0,0);ba.setRGB(0,0,0);Z.setRGB(0,0,0);B=0;for(X=R.length;B<X;B++){T=R[B];D=T.color;if(T instanceof THREE.AmbientLight){da.r+=D.r;da.g+=D.g;da.b+=D.b}else if(T instanceof THREE.DirectionalLight){ba.r+=D.r;ba.g+=
+D.g;ba.b+=D.b}else if(T instanceof THREE.PointLight){Z.r+=D.r;Z.g+=D.g;Z.b+=D.b}}}function Aa(B,X,T,D){var R,$,ca,ga,ia=B.lights;B=0;for(R=ia.length;B<R;B++){$=ia[B];ca=$.color;ga=$.intensity;if($ instanceof THREE.DirectionalLight){$=T.dot($.position)*ga;if($>0){D.r+=ca.r*$;D.g+=ca.g*$;D.b+=ca.b*$}}else if($ instanceof THREE.PointLight){Y.sub($.position,X);Y.normalize();$=T.dot(Y)*ga;if($>0){D.r+=ca.r*$;D.g+=ca.g*$;D.b+=ca.b*$}}}}function Na(B,X,T){if(T.opacity!=0){a(T.opacity);c(T.blending);var D,
+R,$,ca,ga,ia;if(T instanceof THREE.ParticleBasicMaterial){if(T.map){ca=T.map;ga=ca.width>>1;ia=ca.height>>1;R=X.scale.x*b;$=X.scale.y*i;T=R*ga;D=$*ia;w.set(B.x-T,B.y-D,B.x+T,B.y+D);if(V.instersects(w)){k.save();k.translate(B.x,B.y);k.rotate(-X.rotation);k.scale(R,-$);k.translate(-ga,-ia);k.drawImage(ca,0,0);k.restore()}}}else if(T instanceof THREE.ParticleCircleMaterial){if(M){Q.r=da.r+ba.r+Z.r;Q.g=da.g+ba.g+Z.g;Q.b=da.b+ba.b+Z.b;m.r=T.color.r*Q.r;m.g=T.color.g*Q.g;m.b=T.color.b*Q.b;m.updateStyleString()}else m.__styleString=
+T.color.__styleString;T=X.scale.x*b;D=X.scale.y*i;w.set(B.x-T,B.y-D,B.x+T,B.y+D);if(V.instersects(w)){R=m.__styleString;if(J!=R)k.fillStyle=J=R;k.save();k.translate(B.x,B.y);k.rotate(-X.rotation);k.scale(T,D);k.beginPath();k.arc(0,0,1,0,ja,true);k.closePath();k.fill();k.restore()}}}}function Oa(B,X,T,D){if(D.opacity!=0){a(D.opacity);c(D.blending);k.beginPath();k.moveTo(B.positionScreen.x,B.positionScreen.y);k.lineTo(X.positionScreen.x,X.positionScreen.y);k.closePath();if(D instanceof THREE.LineBasicMaterial){m.__styleString=
+D.color.__styleString;B=D.linewidth;if(K!=B)k.lineWidth=K=B;B=m.__styleString;if(H!=B)k.strokeStyle=H=B;k.stroke();w.inflate(D.linewidth*2)}}}function Ia(B,X,T,D,R,$){if(R.opacity!=0){a(R.opacity);c(R.blending);f=B.positionScreen.x;j=B.positionScreen.y;q=X.positionScreen.x;l=X.positionScreen.y;r=T.positionScreen.x;C=T.positionScreen.y;k.beginPath();k.moveTo(f,j);k.lineTo(q,l);k.lineTo(r,C);k.lineTo(f,j);k.closePath();if(R instanceof THREE.MeshBasicMaterial)if(R.map)R.map.image.loaded&&R.map.mapping instanceof
+THREE.UVMapping&&xa(f,j,q,l,r,C,R.map.image,D.uvs[0].u,D.uvs[0].v,D.uvs[1].u,D.uvs[1].v,D.uvs[2].u,D.uvs[2].v);else if(R.env_map){if(R.env_map.image.loaded)if(R.env_map.mapping instanceof THREE.SphericalReflectionMapping){B=ra.matrix;Y.copy(D.vertexNormalsWorld[0]);N=(Y.x*B.n11+Y.y*B.n12+Y.z*B.n13)*0.5+0.5;G=-(Y.x*B.n21+Y.y*B.n22+Y.z*B.n23)*0.5+0.5;Y.copy(D.vertexNormalsWorld[1]);W=(Y.x*B.n11+Y.y*B.n12+Y.z*B.n13)*0.5+0.5;P=-(Y.x*B.n21+Y.y*B.n22+Y.z*B.n23)*0.5+0.5;Y.copy(D.vertexNormalsWorld[2]);I=
+(Y.x*B.n11+Y.y*B.n12+Y.z*B.n13)*0.5+0.5;L=-(Y.x*B.n21+Y.y*B.n22+Y.z*B.n23)*0.5+0.5;xa(f,j,q,l,r,C,R.env_map.image,N,G,W,P,I,L)}}else R.wireframe?Ba(R.color.__styleString,R.wireframe_linewidth):Ca(R.color.__styleString);else if(R instanceof THREE.MeshLambertMaterial){if(R.map&&!R.wireframe){R.map.mapping instanceof THREE.UVMapping&&xa(f,j,q,l,r,C,R.map.image,D.uvs[0].u,D.uvs[0].v,D.uvs[1].u,D.uvs[1].v,D.uvs[2].u,D.uvs[2].v);c(THREE.SubtractiveBlending)}if(M)if(!R.wireframe&&R.shading==THREE.SmoothShading&&
+D.vertexNormalsWorld.length==3){t.r=v.r=s.r=da.r;t.g=v.g=s.g=da.g;t.b=v.b=s.b=da.b;Aa($,D.v1.positionWorld,D.vertexNormalsWorld[0],t);Aa($,D.v2.positionWorld,D.vertexNormalsWorld[1],v);Aa($,D.v3.positionWorld,D.vertexNormalsWorld[2],s);n.r=(v.r+s.r)*0.5;n.g=(v.g+s.g)*0.5;n.b=(v.b+s.b)*0.5;O=Ja(t,v,s,n);xa(f,j,q,l,r,C,O,0,0,1,0,0,1)}else{Q.r=da.r;Q.g=da.g;Q.b=da.b;Aa($,D.centroidWorld,D.normalWorld,Q);m.r=R.color.r*Q.r;m.g=R.color.g*Q.g;m.b=R.color.b*Q.b;m.updateStyleString();R.wireframe?Ba(m.__styleString,
+R.wireframe_linewidth):Ca(m.__styleString)}else R.wireframe?Ba(R.color.__styleString,R.wireframe_linewidth):Ca(R.color.__styleString)}else if(R instanceof THREE.MeshDepthMaterial){E=ra.near;A=ra.far;t.r=t.g=t.b=1-Ea(B.positionScreen.z,E,A);v.r=v.g=v.b=1-Ea(X.positionScreen.z,E,A);s.r=s.g=s.b=1-Ea(T.positionScreen.z,E,A);n.r=(v.r+s.r)*0.5;n.g=(v.g+s.g)*0.5;n.b=(v.b+s.b)*0.5;O=Ja(t,v,s,n);xa(f,j,q,l,r,C,O,0,0,1,0,0,1)}else if(R instanceof THREE.MeshNormalMaterial){m.r=Fa(D.normalWorld.x);m.g=Fa(D.normalWorld.y);
+m.b=Fa(D.normalWorld.z);m.updateStyleString();R.wireframe?Ba(m.__styleString,R.wireframe_linewidth):Ca(m.__styleString)}}}function Ba(B,X){if(H!=B)k.strokeStyle=H=B;if(K!=X)k.lineWidth=K=X;k.stroke();w.inflate(X*2)}function Ca(B){if(J!=B)k.fillStyle=J=B;k.fill()}function xa(B,X,T,D,R,$,ca,ga,ia,na,la,oa,ya){var ta,pa;ta=ca.width-1;pa=ca.height-1;ga*=ta;ia*=pa;na*=ta;la*=pa;oa*=ta;ya*=pa;T-=B;D-=X;R-=B;$-=X;na-=ga;la-=ia;oa-=ga;ya-=ia;pa=1/(na*ya-oa*la);ta=(ya*T-la*R)*pa;la=(ya*D-la*$)*pa;T=(na*R-
+oa*T)*pa;D=(na*$-oa*D)*pa;B=B-ta*ga-T*ia;X=X-la*ga-D*ia;k.save();k.transform(ta,la,T,D,B,X);k.clip();k.drawImage(ca,0,0);k.restore()}function Ja(B,X,T,D){var R=~~(B.r*255),$=~~(B.g*255);B=~~(B.b*255);var ca=~~(X.r*255),ga=~~(X.g*255);X=~~(X.b*255);var ia=~~(T.r*255),na=~~(T.g*255);T=~~(T.b*255);var la=~~(D.r*255),oa=~~(D.g*255);D=~~(D.b*255);ha[0]=R<0?0:R>255?255:R;ha[1]=$<0?0:$>255?255:$;ha[2]=B<0?0:B>255?255:B;ha[4]=ca<0?0:ca>255?255:ca;ha[5]=ga<0?0:ga>255?255:ga;ha[6]=X<0?0:X>255?255:X;ha[8]=ia<
+0?0:ia>255?255:ia;ha[9]=na<0?0:na>255?255:na;ha[10]=T<0?0:T>255?255:T;ha[12]=la<0?0:la>255?255:la;ha[13]=oa<0?0:oa>255?255:oa;ha[14]=D<0?0:D>255?255:D;ka.putImageData(fa,0,0);ua.drawImage(qa,0,0);return sa}function Ea(B,X,T){B=(B-X)/(T-X);return B*B*(3-2*B)}function Fa(B){B=(B+1)*0.5;return B<0?0:B>1?1:B}function Ga(B,X){var T=X.x-B.x,D=X.y-B.y,R=1/Math.sqrt(T*T+D*D);T*=R;D*=R;X.x+=T;X.y+=D;B.x-=T;B.y-=D}var Da,Ka,aa,ma,wa,Ha,La,za;k.setTransform(1,0,0,-1,b,i);this.autoClear&&this.clear();d=e.projectScene(ea,
+ra,this.sortElements);(M=ea.lights.length>0)&&Ma(ea);Da=0;for(Ka=d.length;Da<Ka;Da++){aa=d[Da];w.empty();if(aa instanceof THREE.RenderableParticle){p=aa;p.x*=b;p.y*=i;ma=0;for(wa=aa.materials.length;ma<wa;ma++)Na(p,aa,aa.materials[ma],ea)}else if(aa instanceof THREE.RenderableLine){p=aa.v1;U=aa.v2;p.positionScreen.x*=b;p.positionScreen.y*=i;U.positionScreen.x*=b;U.positionScreen.y*=i;w.addPoint(p.positionScreen.x,p.positionScreen.y);w.addPoint(U.positionScreen.x,U.positionScreen.y);if(V.instersects(w)){ma=
+0;for(wa=aa.materials.length;ma<wa;)Oa(p,U,aa,aa.materials[ma++],ea)}}else if(aa instanceof THREE.RenderableFace3){p=aa.v1;U=aa.v2;F=aa.v3;p.positionScreen.x*=b;p.positionScreen.y*=i;U.positionScreen.x*=b;U.positionScreen.y*=i;F.positionScreen.x*=b;F.positionScreen.y*=i;if(aa.overdraw){Ga(p.positionScreen,U.positionScreen);Ga(U.positionScreen,F.positionScreen);Ga(F.positionScreen,p.positionScreen)}w.add3Points(p.positionScreen.x,p.positionScreen.y,U.positionScreen.x,U.positionScreen.y,F.positionScreen.x,
+F.positionScreen.y);if(V.instersects(w)){ma=0;for(wa=aa.meshMaterials.length;ma<wa;){za=aa.meshMaterials[ma++];if(za instanceof THREE.MeshFaceMaterial){Ha=0;for(La=aa.faceMaterials.length;Ha<La;)(za=aa.faceMaterials[Ha++])&&Ia(p,U,F,aa,za,ea)}else Ia(p,U,F,aa,za,ea)}}}S.addRectangle(w)}k.setTransform(1,0,0,1,0,0)}};
+THREE.SVGRenderer=function(){function a(N,G,W){var P,I,L,V;P=0;for(I=N.lights.length;P<I;P++){L=N.lights[P];if(L instanceof THREE.DirectionalLight){V=G.normalWorld.dot(L.position)*L.intensity;if(V>0){W.r+=L.color.r*V;W.g+=L.color.g*V;W.b+=L.color.b*V}}else if(L instanceof THREE.PointLight){C.sub(L.position,G.centroidWorld);C.normalize();V=G.normalWorld.dot(C)*L.intensity;if(V>0){W.r+=L.color.r*V;W.g+=L.color.g*V;W.b+=L.color.b*V}}}}function c(N,G,W,P,I,L){s=e(n++);s.setAttribute("d","M "+N.positionScreen.x+
+" "+N.positionScreen.y+" L "+G.positionScreen.x+" "+G.positionScreen.y+" L "+W.positionScreen.x+","+W.positionScreen.y+"z");if(I instanceof THREE.MeshBasicMaterial)F.__styleString=I.color.__styleString;else if(I instanceof THREE.MeshLambertMaterial)if(U){f.r=j.r;f.g=j.g;f.b=j.b;a(L,P,f);F.r=I.color.r*f.r;F.g=I.color.g*f.g;F.b=I.color.b*f.b;F.updateStyleString()}else F.__styleString=I.color.__styleString;else if(I instanceof THREE.MeshDepthMaterial){r=1-I.__2near/(I.__farPlusNear-P.z*I.__farMinusNear);
+F.setRGB(r,r,r)}else I instanceof THREE.MeshNormalMaterial&&F.setRGB(g(P.normalWorld.x),g(P.normalWorld.y),g(P.normalWorld.z));I.wireframe?s.setAttribute("style","fill: none; stroke: "+F.__styleString+"; stroke-width: "+I.wireframe_linewidth+"; stroke-opacity: "+I.opacity+"; stroke-linecap: "+I.wireframe_linecap+"; stroke-linejoin: "+I.wireframe_linejoin):s.setAttribute("style","fill: "+F.__styleString+"; fill-opacity: "+I.opacity);b.appendChild(s)}function d(N,G,W,P,I,L,V){s=e(n++);s.setAttribute("d",
+"M "+N.positionScreen.x+" "+N.positionScreen.y+" L "+G.positionScreen.x+" "+G.positionScreen.y+" L "+W.positionScreen.x+","+W.positionScreen.y+" L "+P.positionScreen.x+","+P.positionScreen.y+"z");if(L instanceof THREE.MeshBasicMaterial)F.__styleString=L.color.__styleString;else if(L instanceof THREE.MeshLambertMaterial)if(U){f.r=j.r;f.g=j.g;f.b=j.b;a(V,I,f);F.r=L.color.r*f.r;F.g=L.color.g*f.g;F.b=L.color.b*f.b;F.updateStyleString()}else F.__styleString=L.color.__styleString;else if(L instanceof THREE.MeshDepthMaterial){r=
+1-L.__2near/(L.__farPlusNear-I.z*L.__farMinusNear);F.setRGB(r,r,r)}else L instanceof THREE.MeshNormalMaterial&&F.setRGB(g(I.normalWorld.x),g(I.normalWorld.y),g(I.normalWorld.z));L.wireframe?s.setAttribute("style","fill: none; stroke: "+F.__styleString+"; stroke-width: "+L.wireframe_linewidth+"; stroke-opacity: "+L.opacity+"; stroke-linecap: "+L.wireframe_linecap+"; stroke-linejoin: "+L.wireframe_linejoin):s.setAttribute("style","fill: "+F.__styleString+"; fill-opacity: "+L.opacity);b.appendChild(s)}
+function e(N){if(m[N]==null){m[N]=document.createElementNS("http://www.w3.org/2000/svg","path");O==0&&m[N].setAttribute("shape-rendering","crispEdges");return m[N]}return m[N]}function g(N){return N<0?Math.min((1+N)*0.5,0.5):0.5+Math.min(N*0.5,0.5)}var h=null,o=new THREE.Projector,b=document.createElementNS("http://www.w3.org/2000/svg","svg"),i,k,y,z,u,x,H,J,K=new THREE.Rectangle,p=new THREE.Rectangle,U=false,F=new THREE.Color(16777215),f=new THREE.Color(16777215),j=new THREE.Color(0),q=new THREE.Color(0),
+l=new THREE.Color(0),r,C=new THREE.Vector3,m=[],t=[],v=[],s,n,E,A,O=1;this.domElement=b;this.sortElements=this.sortObjects=this.autoClear=true;this.setQuality=function(N){switch(N){case "high":O=1;break;case "low":O=0}};this.setSize=function(N,G){i=N;k=G;y=i/2;z=k/2;b.setAttribute("viewBox",-y+" "+-z+" "+i+" "+k);b.setAttribute("width",i);b.setAttribute("height",k);K.set(-y,-z,y,z)};this.clear=function(){for(;b.childNodes.length>0;)b.removeChild(b.childNodes[0])};this.render=function(N,G){var W,P,
+I,L,V,S,w,M;this.autoClear&&this.clear();h=o.projectScene(N,G,this.sortElements);A=E=n=0;if(U=N.lights.length>0){w=N.lights;j.setRGB(0,0,0);q.setRGB(0,0,0);l.setRGB(0,0,0);W=0;for(P=w.length;W<P;W++){I=w[W];L=I.color;if(I instanceof THREE.AmbientLight){j.r+=L.r;j.g+=L.g;j.b+=L.b}else if(I instanceof THREE.DirectionalLight){q.r+=L.r;q.g+=L.g;q.b+=L.b}else if(I instanceof THREE.PointLight){l.r+=L.r;l.g+=L.g;l.b+=L.b}}}W=0;for(P=h.length;W<P;W++){w=h[W];p.empty();if(w instanceof THREE.RenderableParticle){u=
+w;u.x*=y;u.y*=-z;I=0;for(L=w.materials.length;I<L;I++)if(M=w.materials[I]){V=u;S=w;M=M;var Q=E++;if(t[Q]==null){t[Q]=document.createElementNS("http://www.w3.org/2000/svg","circle");O==0&&t[Q].setAttribute("shape-rendering","crispEdges")}s=t[Q];s.setAttribute("cx",V.x);s.setAttribute("cy",V.y);s.setAttribute("r",S.scale.x*y);if(M instanceof THREE.ParticleCircleMaterial){if(U){f.r=j.r+q.r+l.r;f.g=j.g+q.g+l.g;f.b=j.b+q.b+l.b;F.r=M.color.r*f.r;F.g=M.color.g*f.g;F.b=M.color.b*f.b;F.updateStyleString()}else F=
+M.color;s.setAttribute("style","fill: "+F.__styleString)}b.appendChild(s)}}else if(w instanceof THREE.RenderableLine){u=w.v1;x=w.v2;u.positionScreen.x*=y;u.positionScreen.y*=-z;x.positionScreen.x*=y;x.positionScreen.y*=-z;p.addPoint(u.positionScreen.x,u.positionScreen.y);p.addPoint(x.positionScreen.x,x.positionScreen.y);if(K.instersects(p)){I=0;for(L=w.materials.length;I<L;)if(M=w.materials[I++]){V=u;S=x;M=M;Q=A++;if(v[Q]==null){v[Q]=document.createElementNS("http://www.w3.org/2000/svg","line");O==
+0&&v[Q].setAttribute("shape-rendering","crispEdges")}s=v[Q];s.setAttribute("x1",V.positionScreen.x);s.setAttribute("y1",V.positionScreen.y);s.setAttribute("x2",S.positionScreen.x);s.setAttribute("y2",S.positionScreen.y);if(M instanceof THREE.LineBasicMaterial){F.__styleString=M.color.__styleString;s.setAttribute("style","fill: none; stroke: "+F.__styleString+"; stroke-width: "+M.linewidth+"; stroke-opacity: "+M.opacity+"; stroke-linecap: "+M.linecap+"; stroke-linejoin: "+M.linejoin);b.appendChild(s)}}}}else if(w instanceof
+THREE.RenderableFace3){u=w.v1;x=w.v2;H=w.v3;u.positionScreen.x*=y;u.positionScreen.y*=-z;x.positionScreen.x*=y;x.positionScreen.y*=-z;H.positionScreen.x*=y;H.positionScreen.y*=-z;p.addPoint(u.positionScreen.x,u.positionScreen.y);p.addPoint(x.positionScreen.x,x.positionScreen.y);p.addPoint(H.positionScreen.x,H.positionScreen.y);if(K.instersects(p)){I=0;for(L=w.meshMaterials.length;I<L;){M=w.meshMaterials[I++];if(M instanceof THREE.MeshFaceMaterial){V=0;for(S=w.faceMaterials.length;V<S;)(M=w.faceMaterials[V++])&&
+c(u,x,H,w,M,N)}else M&&c(u,x,H,w,M,N)}}}else if(w instanceof THREE.RenderableFace4){u=w.v1;x=w.v2;H=w.v3;J=w.v4;u.positionScreen.x*=y;u.positionScreen.y*=-z;x.positionScreen.x*=y;x.positionScreen.y*=-z;H.positionScreen.x*=y;H.positionScreen.y*=-z;J.positionScreen.x*=y;J.positionScreen.y*=-z;p.addPoint(u.positionScreen.x,u.positionScreen.y);p.addPoint(x.positionScreen.x,x.positionScreen.y);p.addPoint(H.positionScreen.x,H.positionScreen.y);p.addPoint(J.positionScreen.x,J.positionScreen.y);if(K.instersects(p)){I=
+0;for(L=w.meshMaterials.length;I<L;){M=w.meshMaterials[I++];if(M instanceof THREE.MeshFaceMaterial){V=0;for(S=w.faceMaterials.length;V<S;)(M=w.faceMaterials[V++])&&d(u,x,H,J,w,M,N)}else M&&d(u,x,H,J,w,M,N)}}}}}};
+THREE.WebGLRenderer=function(a){function c(f,j){f.fragment_shader=j.fragment_shader;f.vertex_shader=j.vertex_shader;f.uniforms=Uniforms.clone(j.uniforms)}function d(f,j){f.uniforms.color.value.setRGB(f.color.r*f.opacity,f.color.g*f.opacity,f.color.b*f.opacity);f.uniforms.opacity.value=f.opacity;f.uniforms.map.texture=f.map;f.uniforms.env_map.texture=f.env_map;f.uniforms.reflectivity.value=f.reflectivity;f.uniforms.refraction_ratio.value=f.refraction_ratio;f.uniforms.combine.value=f.combine;f.uniforms.useRefract.value=
+f.env_map&&f.env_map.mapping instanceof THREE.CubeRefractionMapping;if(j){f.uniforms.fogColor.value.setHex(j.color.hex);if(j instanceof THREE.Fog){f.uniforms.fogNear.value=j.near;f.uniforms.fogFar.value=j.far}else if(j instanceof THREE.FogExp2)f.uniforms.fogDensity.value=j.density}}function e(f,j){f.uniforms.color.value.setRGB(f.color.r*f.opacity,f.color.g*f.opacity,f.color.b*f.opacity);f.uniforms.opacity.value=f.opacity;if(j){f.uniforms.fogColor.value.setHex(j.color.hex);if(j instanceof THREE.Fog){f.uniforms.fogNear.value=
+j.near;f.uniforms.fogFar.value=j.far}else if(j instanceof THREE.FogExp2)f.uniforms.fogDensity.value=j.density}}function g(f,j){var q;if(f=="fragment")q=b.createShader(b.FRAGMENT_SHADER);else if(f=="vertex")q=b.createShader(b.VERTEX_SHADER);b.shaderSource(q,j);b.compileShader(q);if(!b.getShaderParameter(q,b.COMPILE_STATUS)){alert(b.getShaderInfoLog(q));return null}return q}function h(f){switch(f){case THREE.RepeatWrapping:return b.REPEAT;case THREE.ClampToEdgeWrapping:return b.CLAMP_TO_EDGE;case THREE.MirroredRepeatWrapping:return b.MIRRORED_REPEAT;
+case THREE.NearestFilter:return b.NEAREST;case THREE.NearestMipMapNearestFilter:return b.NEAREST_MIPMAP_NEAREST;case THREE.NearestMipMapLinearFilter:return b.NEAREST_MIPMAP_LINEAR;case THREE.LinearFilter:return b.LINEAR;case THREE.LinearMipMapNearestFilter:return b.LINEAR_MIPMAP_NEAREST;case THREE.LinearMipMapLinearFilter:return b.LINEAR_MIPMAP_LINEAR;case THREE.ByteType:return b.BYTE;case THREE.UnsignedByteType:return b.UNSIGNED_BYTE;case THREE.ShortType:return b.SHORT;case THREE.UnsignedShortType:return b.UNSIGNED_SHORT;
+case THREE.IntType:return b.INT;case THREE.UnsignedShortType:return b.UNSIGNED_INT;case THREE.FloatType:return b.FLOAT;case THREE.AlphaFormat:return b.ALPHA;case THREE.RGBFormat:return b.RGB;case THREE.RGBAFormat:return b.RGBA;case THREE.LuminanceFormat:return b.LUMINANCE;case THREE.LuminanceAlphaFormat:return b.LUMINANCE_ALPHA}return 0}var o=document.createElement("canvas"),b,i=null,k=null,y=new THREE.Matrix4,z,u=new Float32Array(16),x=new Float32Array(16),H=new Float32Array(16),J=new Float32Array(9),
+K=new Float32Array(16),p=true,U=new THREE.Color(0),F=0;if(a){if(a.antialias!==undefined)p=a.antialias;a.clearColor!==undefined&&U.setHex(a.clearColor);if(a.clearAlpha!==undefined)F=a.clearAlpha}this.domElement=o;this.autoClear=true;(function(f,j,q){try{b=o.getContext("experimental-webgl",{antialias:f})}catch(l){}if(!b){alert("WebGL not supported");throw"cannot create webgl context";}b.clearColor(0,0,0,1);b.clearDepth(1);b.enable(b.DEPTH_TEST);b.depthFunc(b.LEQUAL);b.frontFace(b.CCW);b.cullFace(b.BACK);
+b.enable(b.CULL_FACE);b.enable(b.BLEND);b.blendFunc(b.ONE,b.ONE_MINUS_SRC_ALPHA);b.clearColor(j.r,j.g,j.b,q)})(p,U,F);this.context=b;this.lights={ambient:[0,0,0],directional:{length:0,colors:[],positions:[]},point:{length:0,colors:[],positions:[]}};this.setSize=function(f,j){o.width=f;o.height=j;b.viewport(0,0,o.width,o.height)};this.setClearColor=function(f,j){var q=new THREE.Color(f);b.clearColor(q.r,q.g,q.b,j)};this.clear=function(){b.clear(b.COLOR_BUFFER_BIT|b.DEPTH_BUFFER_BIT)};this.setupLights=
+function(f,j){var q,l,r,C=0,m=0,t=0,v,s,n,E=this.lights,A=E.directional.colors,O=E.directional.positions,N=E.point.colors,G=E.point.positions,W=0,P=0;q=0;for(l=j.length;q<l;q++){r=j[q];v=r.color;s=r.position;n=r.intensity;if(r instanceof THREE.AmbientLight){C+=v.r;m+=v.g;t+=v.b}else if(r instanceof THREE.DirectionalLight){A[W*3]=v.r*n;A[W*3+1]=v.g*n;A[W*3+2]=v.b*n;O[W*3]=s.x;O[W*3+1]=s.y;O[W*3+2]=s.z;W+=1}else if(r instanceof THREE.PointLight){N[P*3]=v.r*n;N[P*3+1]=v.g*n;N[P*3+2]=v.b*n;G[P*3]=s.x;
+G[P*3+1]=s.y;G[P*3+2]=s.z;P+=1}}E.point.length=P;E.directional.length=W;E.ambient[0]=C;E.ambient[1]=m;E.ambient[2]=t};this.createParticleBuffers=function(f){f.__webGLVertexBuffer=b.createBuffer();f.__webGLFaceBuffer=b.createBuffer()};this.createLineBuffers=function(f){f.__webGLVertexBuffer=b.createBuffer();f.__webGLLineBuffer=b.createBuffer()};this.createMeshBuffers=function(f){f.__webGLVertexBuffer=b.createBuffer();f.__webGLNormalBuffer=b.createBuffer();f.__webGLTangentBuffer=b.createBuffer();f.__webGLUVBuffer=
+b.createBuffer();f.__webGLFaceBuffer=b.createBuffer();f.__webGLLineBuffer=b.createBuffer()};this.initLineBuffers=function(f){var j=f.vertices.length;f.__vertexArray=new Float32Array(j*3);f.__lineArray=new Uint16Array(j);f.__webGLLineCount=j};this.initMeshBuffers=function(f,j){var q,l,r=0,C=0,m=0,t=j.geometry.faces,v=f.faces;q=0;for(l=v.length;q<l;q++){fi=v[q];face=t[fi];if(face instanceof THREE.Face3){r+=3;C+=1;m+=3}else if(face instanceof THREE.Face4){r+=4;C+=2;m+=4}}f.__vertexArray=new Float32Array(r*
+3);f.__normalArray=new Float32Array(r*3);f.__tangentArray=new Float32Array(r*4);f.__uvArray=new Float32Array(r*2);f.__faceArray=new Uint16Array(C*3);f.__lineArray=new Uint16Array(m*2);r=false;q=0;for(l=j.materials.length;q<l;q++){t=j.materials[q];if(t instanceof THREE.MeshFaceMaterial){t=0;for(v=f.materials.length;t<v;t++)if(f.materials[t]&&f.materials[t].shading!=undefined&&f.materials[t].shading==THREE.SmoothShading){r=true;break}}else if(t&&t.shading!=undefined&&t.shading==THREE.SmoothShading){r=
+true;break}if(r)break}f.__needsSmoothNormals=r;f.__webGLFaceCount=C*3;f.__webGLLineCount=m*2};this.setMeshBuffers=function(f,j,q,l,r,C,m,t){var v,s,n,E,A,O,N,G,W,P=0,I=0,L=0,V=0,S=0,w=0,M=0,Q=f.__vertexArray,da=f.__uvArray,ba=f.__normalArray,Z=f.__tangentArray,ja=f.__faceArray,Y=f.__lineArray,qa=f.__needsSmoothNormals,ka=j.geometry,fa=ka.vertices,ha=f.faces,sa=ka.faces,ua=ka.uvs;j=0;for(v=ha.length;j<v;j++){s=ha[j];n=sa[s];s=ua[s];E=n.vertexNormals;A=n.normal;if(n instanceof THREE.Face3){if(l){O=
+fa[n.a].position;N=fa[n.b].position;G=fa[n.c].position;Q[I]=O.x;Q[I+1]=O.y;Q[I+2]=O.z;Q[I+3]=N.x;Q[I+4]=N.y;Q[I+5]=N.z;Q[I+6]=G.x;Q[I+7]=G.y;Q[I+8]=G.z;I+=9}if(t&&ka.hasTangents){O=fa[n.a].tangent;N=fa[n.b].tangent;G=fa[n.c].tangent;Z[w]=O.x;Z[w+1]=O.y;Z[w+2]=O.z;Z[w+3]=O.w;Z[w+4]=N.x;Z[w+5]=N.y;Z[w+6]=N.z;Z[w+7]=N.w;Z[w+8]=G.x;Z[w+9]=G.y;Z[w+10]=G.z;Z[w+11]=G.w;w+=12}if(m)if(E.length==3&&qa)for(n=0;n<3;n++){A=E[n];ba[S]=A.x;ba[S+1]=A.y;ba[S+2]=A.z;S+=3}else for(n=0;n<3;n++){ba[S]=A.x;ba[S+1]=A.y;
+ba[S+2]=A.z;S+=3}if(C&&s)for(n=0;n<3;n++){E=s[n];da[L]=E.u;da[L+1]=E.v;L+=2}if(r){ja[V]=P;ja[V+1]=P+1;ja[V+2]=P+2;V+=3;Y[M]=P;Y[M+1]=P+1;Y[M+2]=P;Y[M+3]=P+2;Y[M+4]=P+1;Y[M+5]=P+2;M+=6;P+=3}}else if(n instanceof THREE.Face4){if(l){O=fa[n.a].position;N=fa[n.b].position;G=fa[n.c].position;W=fa[n.d].position;Q[I]=O.x;Q[I+1]=O.y;Q[I+2]=O.z;Q[I+3]=N.x;Q[I+4]=N.y;Q[I+5]=N.z;Q[I+6]=G.x;Q[I+7]=G.y;Q[I+8]=G.z;Q[I+9]=W.x;Q[I+10]=W.y;Q[I+11]=W.z;I+=12}if(t&&ka.hasTangents){O=fa[n.a].tangent;N=fa[n.b].tangent;
+G=fa[n.c].tangent;n=fa[n.d].tangent;Z[w]=O.x;Z[w+1]=O.y;Z[w+2]=O.z;Z[w+3]=O.w;Z[w+4]=N.x;Z[w+5]=N.y;Z[w+6]=N.z;Z[w+7]=N.w;Z[w+8]=G.x;Z[w+9]=G.y;Z[w+10]=G.z;Z[w+11]=G.w;Z[w+12]=n.x;Z[w+13]=n.y;Z[w+14]=n.z;Z[w+15]=n.w;w+=16}if(m)if(E.length==4&&qa)for(n=0;n<4;n++){A=E[n];ba[S]=A.x;ba[S+1]=A.y;ba[S+2]=A.z;S+=3}else for(n=0;n<4;n++){ba[S]=A.x;ba[S+1]=A.y;ba[S+2]=A.z;S+=3}if(C&&s)for(n=0;n<4;n++){E=s[n];da[L]=E.u;da[L+1]=E.v;L+=2}if(r){ja[V]=P;ja[V+1]=P+1;ja[V+2]=P+2;ja[V+3]=P;ja[V+4]=P+2;ja[V+5]=P+3;
+V+=6;Y[M]=P;Y[M+1]=P+1;Y[M+2]=P;Y[M+3]=P+3;Y[M+4]=P+1;Y[M+5]=P+2;Y[M+6]=P+2;Y[M+7]=P+3;M+=8;P+=4}}}if(l){b.bindBuffer(b.ARRAY_BUFFER,f.__webGLVertexBuffer);b.bufferData(b.ARRAY_BUFFER,Q,q)}if(m){b.bindBuffer(b.ARRAY_BUFFER,f.__webGLNormalBuffer);b.bufferData(b.ARRAY_BUFFER,ba,q)}if(t&&ka.hasTangents){b.bindBuffer(b.ARRAY_BUFFER,f.__webGLTangentBuffer);b.bufferData(b.ARRAY_BUFFER,Z,q)}if(C&&L>0){b.bindBuffer(b.ARRAY_BUFFER,f.__webGLUVBuffer);b.bufferData(b.ARRAY_BUFFER,da,q)}if(r){b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,
+f.__webGLFaceBuffer);b.bufferData(b.ELEMENT_ARRAY_BUFFER,ja,q);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,f.__webGLLineBuffer);b.bufferData(b.ELEMENT_ARRAY_BUFFER,Y,q)}};this.setLineBuffers=function(f,j,q,l){var r,C,m=f.vertices,t=m.length,v=f.__vertexArray,s=f.__lineArray;if(q)for(q=0;q<t;q++){r=m[q].position;C=q*3;v[C]=r.x;v[C+1]=r.y;v[C+2]=r.z}if(l)for(q=0;q<t;q++)s[q]=q;b.bindBuffer(b.ARRAY_BUFFER,f.__webGLVertexBuffer);b.bufferData(b.ARRAY_BUFFER,v,j);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,f.__webGLLineBuffer);
+b.bufferData(b.ELEMENT_ARRAY_BUFFER,s,j)};this.setParticleBuffers=function(){};this.renderBuffer=function(f,j,q,l,r,C){var m,t,v,s;if(!l.program){if(l instanceof THREE.MeshDepthMaterial){c(l,THREE.ShaderLib.depth);l.uniforms.mNear.value=f.near;l.uniforms.mFar.value=f.far}else if(l instanceof THREE.MeshNormalMaterial)c(l,THREE.ShaderLib.normal);else if(l instanceof THREE.MeshBasicMaterial){c(l,THREE.ShaderLib.basic);d(l,q)}else if(l instanceof THREE.MeshLambertMaterial){c(l,THREE.ShaderLib.lambert);
+d(l,q)}else if(l instanceof THREE.MeshPhongMaterial){c(l,THREE.ShaderLib.phong);d(l,q)}else if(l instanceof THREE.LineBasicMaterial){c(l,THREE.ShaderLib.basic);e(l,q)}var n,E,A;n=s=t=0;for(E=j.length;n<E;n++){A=j[n];A instanceof THREE.DirectionalLight&&s++;A instanceof THREE.PointLight&&t++}if(t+s<=4){n=s;t=t}else{n=Math.ceil(4*s/(t+s));t=4-n}t={directional:n,point:t};s={fog:q,map:l.map,env_map:l.env_map,maxDirLights:t.directional,maxPointLights:t.point};t=l.fragment_shader;n=l.vertex_shader;E=b.createProgram();
+A=["#ifdef GL_ES\nprecision highp float;\n#endif","#define MAX_DIR_LIGHTS "+s.maxDirLights,"#define MAX_POINT_LIGHTS "+s.maxPointLights,s.fog?"#define USE_FOG":"",s.fog instanceof THREE.FogExp2?"#define FOG_EXP2":"",s.map?"#define USE_MAP":"",s.env_map?"#define USE_ENVMAP":"","uniform mat4 viewMatrix;\nuniform vec3 cameraPosition;\n"].join("\n");s=[b.getParameter(b.MAX_VERTEX_TEXTURE_IMAGE_UNITS)>0?"#define VERTEX_TEXTURES":"","#define MAX_DIR_LIGHTS "+s.maxDirLights,"#define MAX_POINT_LIGHTS "+s.maxPointLights,
+s.map?"#define USE_MAP":"",s.env_map?"#define USE_ENVMAP":"","uniform mat4 objectMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\nuniform mat3 normalMatrix;\nuniform vec3 cameraPosition;\nattribute vec3 position;\nattribute vec3 normal;\nattribute vec2 uv;\n"].join("\n");b.attachShader(E,g("fragment",A+t));b.attachShader(E,g("vertex",s+n));b.linkProgram(E);b.getProgramParameter(E,b.LINK_STATUS)||alert("Could not initialise shaders\nVALIDATE_STATUS: "+
+b.getProgramParameter(E,b.VALIDATE_STATUS)+", gl error ["+b.getError()+"]");E.uniforms={};E.attributes={};l.program=E;t=["viewMatrix","modelViewMatrix","projectionMatrix","normalMatrix","objectMatrix","cameraPosition"];for(m in l.uniforms)t.push(m);m=l.program;n=0;for(E=t.length;n<E;n++){A=t[n];m.uniforms[A]=b.getUniformLocation(m,A)}m=l.program;t=["position","normal","uv","tangent"];n=0;for(E=t.length;n<E;n++){A=t[n];m.attributes[A]=b.getAttribLocation(m,A)}}m=l.program;if(m!=i){b.useProgram(m);
+i=m}this.loadCamera(m,f);this.loadMatrices(m);if(l instanceof THREE.MeshPhongMaterial||l instanceof THREE.MeshLambertMaterial){this.setupLights(m,j);f=this.lights;l.uniforms.enableLighting.value=f.directional.length+f.point.length;l.uniforms.ambientLightColor.value=f.ambient;l.uniforms.directionalLightColor.value=f.directional.colors;l.uniforms.directionalLightDirection.value=f.directional.positions;l.uniforms.pointLightColor.value=f.point.colors;l.uniforms.pointLightPosition.value=f.point.positions}if(l instanceof
+THREE.MeshBasicMaterial||l instanceof THREE.MeshLambertMaterial||l instanceof THREE.MeshPhongMaterial)d(l,q);l instanceof THREE.LineBasicMaterial&&e(l,q);if(l instanceof THREE.MeshPhongMaterial){l.uniforms.ambient.value.setRGB(l.ambient.r,l.ambient.g,l.ambient.b);l.uniforms.specular.value.setRGB(l.specular.r,l.specular.g,l.specular.b);l.uniforms.shininess.value=l.shininess}q=l.uniforms;for(v in q)if(n=m.uniforms[v]){j=q[v];t=j.type;f=j.value;if(t=="i")b.uniform1i(n,f);else if(t=="f")b.uniform1f(n,
+f);else if(t=="fv1")b.uniform1fv(n,f);else if(t=="fv")b.uniform3fv(n,f);else if(t=="v2")b.uniform2f(n,f.x,f.y);else if(t=="v3")b.uniform3f(n,f.x,f.y,f.z);else if(t=="c")b.uniform3f(n,f.r,f.g,f.b);else if(t=="t"){b.uniform1i(n,f);if(j=j.texture)if(j.image instanceof Array&&j.image.length==6){j=j;f=f;if(j.image.length==6){if(!j.image.__webGLTextureCube&&!j.image.__cubeMapInitialized&&j.image.loadCount==6){j.image.__webGLTextureCube=b.createTexture();b.bindTexture(b.TEXTURE_CUBE_MAP,j.image.__webGLTextureCube);
+b.texParameteri(b.TEXTURE_CUBE_MAP,b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_CUBE_MAP,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_CUBE_MAP,b.TEXTURE_MAG_FILTER,b.LINEAR);b.texParameteri(b.TEXTURE_CUBE_MAP,b.TEXTURE_MIN_FILTER,b.LINEAR_MIPMAP_LINEAR);for(t=0;t<6;++t)b.texImage2D(b.TEXTURE_CUBE_MAP_POSITIVE_X+t,0,b.RGBA,b.RGBA,b.UNSIGNED_BYTE,j.image[t]);b.generateMipmap(b.TEXTURE_CUBE_MAP);b.bindTexture(b.TEXTURE_CUBE_MAP,null);j.image.__cubeMapInitialized=true}b.activeTexture(b.TEXTURE0+
+f);b.bindTexture(b.TEXTURE_CUBE_MAP,j.image.__webGLTextureCube)}}else{j=j;f=f;if(!j.__webGLTexture&&j.image.loaded){j.__webGLTexture=b.createTexture();b.bindTexture(b.TEXTURE_2D,j.__webGLTexture);b.texImage2D(b.TEXTURE_2D,0,b.RGBA,b.RGBA,b.UNSIGNED_BYTE,j.image);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,h(j.wrap_s));b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,h(j.wrap_t));b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,h(j.mag_filter));b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,h(j.min_filter));
+b.generateMipmap(b.TEXTURE_2D);b.bindTexture(b.TEXTURE_2D,null)}b.activeTexture(b.TEXTURE0+f);b.bindTexture(b.TEXTURE_2D,j.__webGLTexture)}}}v=m.attributes;b.bindBuffer(b.ARRAY_BUFFER,r.__webGLVertexBuffer);b.vertexAttribPointer(v.position,3,b.FLOAT,false,0,0);b.enableVertexAttribArray(v.position);if(v.normal>=0){b.bindBuffer(b.ARRAY_BUFFER,r.__webGLNormalBuffer);b.vertexAttribPointer(v.normal,3,b.FLOAT,false,0,0);b.enableVertexAttribArray(v.normal)}if(v.tangent>=0){b.bindBuffer(b.ARRAY_BUFFER,r.__webGLTangentBuffer);
+b.vertexAttribPointer(v.tangent,4,b.FLOAT,false,0,0);b.enableVertexAttribArray(v.tangent)}if(v.uv>=0)if(r.__webGLUVBuffer){b.bindBuffer(b.ARRAY_BUFFER,r.__webGLUVBuffer);b.vertexAttribPointer(v.uv,2,b.FLOAT,false,0,0);b.enableVertexAttribArray(v.uv)}else b.disableVertexAttribArray(v.uv);if(l.wireframe||l instanceof THREE.LineBasicMaterial){v=l.wireframe_linewidth!==undefined?l.wireframe_linewidth:l.linewidth!==undefined?l.linewidth:1;l=l instanceof THREE.LineBasicMaterial&&C.type==THREE.LineStrip?
+b.LINE_STRIP:b.LINES;b.lineWidth(v);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,r.__webGLLineBuffer);b.drawElements(l,r.__webGLLineCount,b.UNSIGNED_SHORT,0)}else{b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,r.__webGLFaceBuffer);b.drawElements(b.TRIANGLES,r.__webGLFaceCount,b.UNSIGNED_SHORT,0)}};this.renderPass=function(f,j,q,l,r,C,m){var t,v,s,n,E;s=0;for(n=l.materials.length;s<n;s++){t=l.materials[s];if(t instanceof THREE.MeshFaceMaterial){t=0;for(v=r.materials.length;t<v;t++)if((E=r.materials[t])&&E.blending==C&&
+E.opacity<1==m){this.setBlending(E.blending);this.renderBuffer(f,j,q,E,r,l)}}else if((E=t)&&E.blending==C&&E.opacity<1==m){this.setBlending(E.blending);this.renderBuffer(f,j,q,E,r,l)}}};this.render=function(f,j,q,l){var r,C,m,t=f.lights,v=f.fog;this.initWebGLObjects(f);l=l!==undefined?l:true;if(q&&!q.__webGLFramebuffer){q.__webGLFramebuffer=b.createFramebuffer();q.__webGLRenderbuffer=b.createRenderbuffer();q.__webGLTexture=b.createTexture();b.bindRenderbuffer(b.RENDERBUFFER,q.__webGLRenderbuffer);
+b.renderbufferStorage(b.RENDERBUFFER,b.DEPTH_COMPONENT16,q.width,q.height);b.bindTexture(b.TEXTURE_2D,q.__webGLTexture);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,h(q.wrap_s));b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,h(q.wrap_t));b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,h(q.mag_filter));b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,h(q.min_filter));b.texImage2D(b.TEXTURE_2D,0,h(q.format),q.width,q.height,0,h(q.format),h(q.type),null);b.bindFramebuffer(b.FRAMEBUFFER,q.__webGLFramebuffer);
+b.framebufferTexture2D(b.FRAMEBUFFER,b.COLOR_ATTACHMENT0,b.TEXTURE_2D,q.__webGLTexture,0);b.framebufferRenderbuffer(b.FRAMEBUFFER,b.DEPTH_ATTACHMENT,b.RENDERBUFFER,q.__webGLRenderbuffer);b.bindTexture(b.TEXTURE_2D,null);b.bindRenderbuffer(b.RENDERBUFFER,null);b.bindFramebuffer(b.FRAMEBUFFER,null)}if(q){r=q.__webGLFramebuffer;m=q.width;C=q.height}else{r=null;m=o.width;C=o.height}if(r!=k){b.bindFramebuffer(b.FRAMEBUFFER,r);b.viewport(0,0,m,C);l&&b.clear(b.COLOR_BUFFER_BIT|b.DEPTH_BUFFER_BIT);k=r}this.autoClear&&
+this.clear();j.autoUpdateMatrix&&j.updateMatrix();u.set(j.matrix.flatten());H.set(j.projectionMatrix.flatten());l=0;for(r=f.__webGLObjects.length;l<r;l++){C=f.__webGLObjects[l];m=C.object;C=C.buffer;if(m.visible){this.setupMatrices(m,j);this.renderPass(j,t,v,m,C,THREE.NormalBlending,false)}}l=0;for(r=f.__webGLObjects.length;l<r;l++){C=f.__webGLObjects[l];m=C.object;C=C.buffer;if(m.visible){this.setupMatrices(m,j);if(m.doubleSided)b.disable(b.CULL_FACE);else{b.enable(b.CULL_FACE);m.flipSided?b.frontFace(b.CW):
+b.frontFace(b.CCW)}this.renderPass(j,t,v,m,C,THREE.AdditiveBlending,false);this.renderPass(j,t,v,m,C,THREE.SubtractiveBlending,false);this.renderPass(j,t,v,m,C,THREE.AdditiveBlending,true);this.renderPass(j,t,v,m,C,THREE.SubtractiveBlending,true);this.renderPass(j,t,v,m,C,THREE.NormalBlending,true)}}if(q&&q.min_filter!==THREE.NearestFilter&&q.min_filter!==THREE.LinearFilter){b.bindTexture(b.TEXTURE_2D,q.__webGLTexture);b.generateMipmap(b.TEXTURE_2D);b.bindTexture(b.TEXTURE_2D,null)}};this.initWebGLObjects=
+function(f){function j(s,n,E,A){if(s[n]==undefined){f.__webGLObjects.push({buffer:E,object:A});s[n]=1}}var q,l,r,C,m,t,v;if(!f.__webGLObjects){f.__webGLObjects=[];f.__webGLObjectsMap={}}q=0;for(l=f.objects.length;q<l;q++){r=f.objects[q];m=r.geometry;if(f.__webGLObjectsMap[r.id]==undefined)f.__webGLObjectsMap[r.id]={};v=f.__webGLObjectsMap[r.id];if(r instanceof THREE.Mesh){for(C in m.geometryChunks){t=m.geometryChunks[C];if(!t.__webGLVertexBuffer){this.createMeshBuffers(t);this.initMeshBuffers(t,r);
+m.__dirtyVertices=true;m.__dirtyElements=true;m.__dirtyUvs=true;m.__dirtyNormals=true;m.__dirtyTangents=true}if(m.__dirtyVertices||m.__dirtyElements||m.__dirtyUvs)this.setMeshBuffers(t,r,b.DYNAMIC_DRAW,m.__dirtyVertices,m.__dirtyElements,m.__dirtyUvs,m.__dirtyNormals,m.__dirtyTangents);j(v,C,t,r)}m.__dirtyVertices=false;m.__dirtyElements=false;m.__dirtyUvs=false;m.__dirtyNormals=false;m.__dirtyTangents=false}else if(r instanceof THREE.Line){if(!m.__webGLVertexBuffer){this.createLineBuffers(m);this.initLineBuffers(m);
+m.__dirtyVertices=true;m.__dirtyElements=true}m.__dirtyVertices&&this.setLineBuffers(m,b.DYNAMIC_DRAW,m.__dirtyVertices,m.__dirtyElements);j(v,0,m,r);m.__dirtyVertices=false;m.__dirtyElements=false}else if(r instanceof THREE.ParticleSystem){m.__webGLVertexBuffer||this.createParticleBuffers(m);j(v,0,m,r)}}};this.removeObject=function(f,j){var q,l;for(q=f.__webGLObjects.length-1;q>=0;q--){l=f.__webGLObjects[q].object;j==l&&f.__webGLObjects.splice(q,1)}};this.setupMatrices=function(f,j){f.autoUpdateMatrix&&
+f.updateMatrix();y.multiply(j.matrix,f.matrix);x.set(y.flatten());z=THREE.Matrix4.makeInvert3x3(y).transpose();J.set(z.m);K.set(f.matrix.flatten())};this.loadMatrices=function(f){b.uniformMatrix4fv(f.uniforms.viewMatrix,false,u);b.uniformMatrix4fv(f.uniforms.modelViewMatrix,false,x);b.uniformMatrix4fv(f.uniforms.projectionMatrix,false,H);b.uniformMatrix3fv(f.uniforms.normalMatrix,false,J);b.uniformMatrix4fv(f.uniforms.objectMatrix,false,K)};this.loadCamera=function(f,j){b.uniform3f(f.uniforms.cameraPosition,
+j.position.x,j.position.y,j.position.z)};this.setBlending=function(f){switch(f){case THREE.AdditiveBlending:b.blendEquation(b.FUNC_ADD);b.blendFunc(b.ONE,b.ONE);break;case THREE.SubtractiveBlending:b.blendFunc(b.DST_COLOR,b.ZERO);break;default:b.blendEquation(b.FUNC_ADD);b.blendFunc(b.ONE,b.ONE_MINUS_SRC_ALPHA)}};this.setFaceCulling=function(f,j){if(f){!j||j=="ccw"?b.frontFace(b.CCW):b.frontFace(b.CW);if(f=="back")b.cullFace(b.BACK);else f=="front"?b.cullFace(b.FRONT):b.cullFace(b.FRONT_AND_BACK);
+b.enable(b.CULL_FACE)}else b.disable(b.CULL_FACE)};this.supportsVertexTextures=function(){return b.getParameter(b.MAX_VERTEX_TEXTURE_IMAGE_UNITS)>0}};
+THREE.Snippets={fog_pars_fragment:"#ifdef USE_FOG\nuniform vec3 fogColor;\n#ifdef FOG_EXP2\nuniform float fogDensity;\n#else\nuniform float fogNear;\nuniform float fogFar;\n#endif\n#endif",fog_fragment:"#ifdef USE_FOG\nfloat depth = gl_FragCoord.z / gl_FragCoord.w;\n#ifdef FOG_EXP2\nconst float LOG2 = 1.442695;\nfloat fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );\nfogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );\n#else\nfloat fogFactor = smoothstep( fogNear, fogFar, depth );\n#endif\ngl_FragColor = mix( gl_FragColor, vec4( fogColor, 1.0 ), fogFactor );\n#endif",envmap_pars_fragment:"#ifdef USE_ENVMAP\nvarying vec3 vReflect;\nuniform float reflectivity;\nuniform samplerCube env_map;\nuniform int combine;\n#endif",
+envmap_fragment:"#ifdef USE_ENVMAP\ncubeColor = textureCube( env_map, vec3( -vReflect.x, vReflect.yz ) );\nif ( combine == 1 ) {\ngl_FragColor = mix( gl_FragColor, cubeColor, reflectivity );\n} else {\ngl_FragColor = gl_FragColor * cubeColor;\n}\n#endif",envmap_pars_vertex:"#ifdef USE_ENVMAP\nvarying vec3 vReflect;\nuniform float refraction_ratio;\nuniform bool useRefract;\n#endif",envmap_vertex:"#ifdef USE_ENVMAP\nvec4 mPosition = objectMatrix * vec4( position, 1.0 );\nvec3 nWorld = mat3( objectMatrix[0].xyz, objectMatrix[1].xyz, objectMatrix[2].xyz ) * normal;\nif ( useRefract ) {\nvReflect = refract( normalize( mPosition.xyz - cameraPosition ), normalize( nWorld.xyz ), refraction_ratio );\n} else {\nvReflect = reflect( normalize( mPosition.xyz - cameraPosition ), normalize( nWorld.xyz ) );\n}\n#endif",
+map_pars_fragment:"#ifdef USE_MAP\nvarying vec2 vUv;\nuniform sampler2D map;\n#endif",map_pars_vertex:"#ifdef USE_MAP\nvarying vec2 vUv;\n#endif",map_fragment:"#ifdef USE_MAP\nmapColor = texture2D( map, vUv );\n#endif",map_vertex:"#ifdef USE_MAP\nvUv = uv;\n#endif",lights_pars_vertex:"uniform bool enableLighting;\nuniform vec3 ambientLightColor;\n#if MAX_DIR_LIGHTS > 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\n#ifdef PHONG\nvarying vec3 vPointLightVector[ MAX_POINT_LIGHTS ];\n#endif\n#endif",
+lights_vertex:"if ( !enableLighting ) {\nvLightWeighting = vec3( 1.0 );\n} else {\nvLightWeighting = ambientLightColor;\n#if MAX_DIR_LIGHTS > 0\nfor( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nfloat directionalLightWeighting = max( dot( transformedNormal, normalize( lDirection.xyz ) ), 0.0 );\nvLightWeighting += directionalLightColor[ i ] * directionalLightWeighting;\n}\n#endif\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 pointLightVector = normalize( lPosition.xyz - mvPosition.xyz );\nfloat pointLightWeighting = max( dot( transformedNormal, pointLightVector ), 0.0 );\nvLightWeighting += pointLightColor[ i ] * pointLightWeighting;\n#ifdef PHONG\nvPointLightVector[ i ] = pointLightVector;\n#endif\n}\n#endif\n}",
+lights_pars_fragment:"#if MAX_DIR_LIGHTS > 0\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nvarying vec3 vPointLightVector[ MAX_POINT_LIGHTS ];\n#endif\nvarying vec3 vViewPosition;\nvarying vec3 vNormal;",lights_fragment:"vec3 normal = normalize( vNormal );\nvec3 viewPosition = normalize( vViewPosition );\nvec4 mSpecular = vec4( specular, opacity );\n#if MAX_POINT_LIGHTS > 0\nvec4 pointDiffuse = vec4( 0.0 );\nvec4 pointSpecular = vec4( 0.0 );\nfor( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {\nvec3 pointVector = normalize( vPointLightVector[ i ] );\nvec3 pointHalfVector = normalize( vPointLightVector[ i ] + vViewPosition );\nfloat pointDotNormalHalf = dot( normal, pointHalfVector );\nfloat pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );\nfloat pointSpecularWeight = 0.0;\nif ( pointDotNormalHalf >= 0.0 )\npointSpecularWeight = pow( pointDotNormalHalf, shininess );\npointDiffuse += mColor * pointDiffuseWeight;\npointSpecular += mSpecular * pointSpecularWeight;\n}\n#endif\n#if MAX_DIR_LIGHTS > 0\nvec4 dirDiffuse = vec4( 0.0 );\nvec4 dirSpecular = vec4( 0.0 );\nfor( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nvec3 dirHalfVector = normalize( lDirection.xyz + vViewPosition );\nfloat dirDotNormalHalf = dot( normal, dirHalfVector );\nfloat dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );\nfloat dirSpecularWeight = 0.0;\nif ( dirDotNormalHalf >= 0.0 )\ndirSpecularWeight = pow( dirDotNormalHalf, shininess );\ndirDiffuse += mColor * dirDiffuseWeight;\ndirSpecular += mSpecular * dirSpecularWeight;\n}\n#endif\nvec4 totalLight = vec4( ambient, opacity );\n#if MAX_DIR_LIGHTS > 0\ntotalLight += dirDiffuse + dirSpecular;\n#endif\n#if MAX_POINT_LIGHTS > 0\ntotalLight += pointDiffuse + pointSpecular;\n#endif"};
+THREE.UniformsLib={common:{color:{type:"c",value:new THREE.Color(15658734)},opacity:{type:"f",value:1},map:{type:"t",value:0,texture:null},env_map:{type:"t",value:1,texture:null},useRefract:{type:"i",value:0},reflectivity:{type:"f",value:1},refraction_ratio:{type:"f",value:0.98},combine:{type:"i",value:0},fogDensity:{type:"f",value:2.5E-4},fogNear:{type:"f",value:1},fogFar:{type:"f",value:2E3},fogColor:{type:"c",value:new THREE.Color(16777215)}},lights:{enableLighting:{type:"i",value:1},ambientLightColor:{type:"fv",
+value:[]},directionalLightDirection:{type:"fv",value:[]},directionalLightColor:{type:"fv",value:[]},pointLightPosition:{type:"fv",value:[]},pointLightColor:{type:"fv",value:[]}}};
+THREE.ShaderLib={depth:{uniforms:{mNear:{type:"f",value:1},mFar:{type:"f",value:2E3}},fragment_shader:"uniform float mNear;\nuniform float mFar;\nvoid main() {\nfloat depth = gl_FragCoord.z / gl_FragCoord.w;\nfloat color = 1.0 - smoothstep( mNear, mFar, depth );\ngl_FragColor = vec4( vec3( color ), 1.0 );\n}",vertex_shader:"void main() {\ngl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}"},normal:{uniforms:{},fragment_shader:"varying vec3 vNormal;\nvoid main() {\ngl_FragColor = vec4( 0.5 * normalize( vNormal ) + 0.5, 1.0 );\n}",
+vertex_shader:"varying vec3 vNormal;\nvoid main() {\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\nvNormal = normalize( normalMatrix * normal );\ngl_Position = projectionMatrix * mvPosition;\n}"},basic:{uniforms:THREE.UniformsLib.common,fragment_shader:["uniform vec3 color;\nuniform float opacity;",THREE.Snippets.map_pars_fragment,THREE.Snippets.envmap_pars_fragment,THREE.Snippets.fog_pars_fragment,"void main() {\nvec4 mColor = vec4( color, opacity );\nvec4 mapColor = vec4( 1.0 );\nvec4 cubeColor = vec4( 1.0 );",
+THREE.Snippets.map_fragment,"gl_FragColor = mColor * mapColor;",THREE.Snippets.envmap_fragment,THREE.Snippets.fog_fragment,"}"].join("\n"),vertex_shader:[THREE.Snippets.map_pars_vertex,THREE.Snippets.envmap_pars_vertex,"void main() {\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",THREE.Snippets.map_vertex,THREE.Snippets.envmap_vertex,"gl_Position = projectionMatrix * mvPosition;\n}"].join("\n")},lambert:{uniforms:Uniforms.merge([THREE.UniformsLib.common,THREE.UniformsLib.lights]),fragment_shader:["uniform vec3 color;\nuniform float opacity;\nvarying vec3 vLightWeighting;",
+THREE.Snippets.map_pars_fragment,THREE.Snippets.envmap_pars_fragment,THREE.Snippets.fog_pars_fragment,"void main() {\nvec4 mColor = vec4( color, opacity );\nvec4 mapColor = vec4( 1.0 );\nvec4 cubeColor = vec4( 1.0 );",THREE.Snippets.map_fragment,"gl_FragColor = mColor * mapColor * vec4( vLightWeighting, 1.0 );",THREE.Snippets.envmap_fragment,THREE.Snippets.fog_fragment,"}"].join("\n"),vertex_shader:["varying vec3 vLightWeighting;",THREE.Snippets.map_pars_vertex,THREE.Snippets.envmap_pars_vertex,
+THREE.Snippets.lights_pars_vertex,"void main() {\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",THREE.Snippets.map_vertex,THREE.Snippets.envmap_vertex,"vec3 transformedNormal = normalize( normalMatrix * normal );",THREE.Snippets.lights_vertex,"gl_Position = projectionMatrix * mvPosition;\n}"].join("\n")},phong:{uniforms:Uniforms.merge([THREE.UniformsLib.common,THREE.UniformsLib.lights,{ambient:{type:"c",value:new THREE.Color(328965)},specular:{type:"c",value:new THREE.Color(1118481)},
+shininess:{type:"f",value:30}}]),fragment_shader:["uniform vec3 color;\nuniform float opacity;\nuniform vec3 ambient;\nuniform vec3 specular;\nuniform float shininess;\nvarying vec3 vLightWeighting;",THREE.Snippets.map_pars_fragment,THREE.Snippets.envmap_pars_fragment,THREE.Snippets.fog_pars_fragment,THREE.Snippets.lights_pars_fragment,"void main() {\nvec4 mColor = vec4( color, opacity );\nvec4 mapColor = vec4( 1.0 );\nvec4 cubeColor = vec4( 1.0 );",THREE.Snippets.map_fragment,THREE.Snippets.lights_fragment,
+"gl_FragColor = mapColor * totalLight * vec4( vLightWeighting, 1.0 );",THREE.Snippets.envmap_fragment,THREE.Snippets.fog_fragment,"}"].join("\n"),vertex_shader:["#define PHONG\nvarying vec3 vLightWeighting;\nvarying vec3 vViewPosition;\nvarying vec3 vNormal;",THREE.Snippets.map_pars_vertex,THREE.Snippets.envmap_pars_vertex,THREE.Snippets.lights_pars_vertex,"void main() {\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",THREE.Snippets.map_vertex,THREE.Snippets.envmap_vertex,"#ifndef USE_ENVMAP\nvec4 mPosition = objectMatrix * vec4( position, 1.0 );\n#endif\nvViewPosition = cameraPosition - mPosition.xyz;\nvec3 transformedNormal = normalize( normalMatrix * normal );\nvNormal = transformedNormal;",
+THREE.Snippets.lights_vertex,"gl_Position = projectionMatrix * mvPosition;\n}"].join("\n")}};THREE.RenderableObject=function(){this.z=this.object=null};THREE.RenderableFace3=function(){this.z=null;this.v1=new THREE.Vertex;this.v2=new THREE.Vertex;this.v3=new THREE.Vertex;this.centroidWorld=new THREE.Vector3;this.centroidScreen=new THREE.Vector3;this.normalWorld=new THREE.Vector3;this.vertexNormalsWorld=[];this.faceMaterials=this.meshMaterials=null;this.overdraw=false;this.uvs=[null,null,null]};
+THREE.RenderableParticle=function(){this.rotation=this.z=this.y=this.x=null;this.scale=new THREE.Vector2;this.materials=null};THREE.RenderableLine=function(){this.z=null;this.v1=new THREE.Vertex;this.v2=new THREE.Vertex;this.materials=null};
diff --git a/extlib/thingiview.js/binaryReader.js b/extlib/thingiview.js/binaryReader.js
new file mode 100644
index 00000000..f99a2379
--- /dev/null
+++ b/extlib/thingiview.js/binaryReader.js
@@ -0,0 +1,126 @@
+// BinaryReader
+// Refactored by Vjeux <vjeuxx@gmail.com>
+// http://blog.vjeux.com/2010/javascript/javascript-binary-reader.html
+
+// Original
+//+ Jonas Raoni Soares Silva
+//@ http://jsfromhell.com/classes/binary-parser [rev. #1]
+
+BinaryReader = function (data) {
+ this._buffer = data;
+ this._pos = 0;
+};
+
+BinaryReader.prototype = {
+
+ /* Public */
+
+ readInt8: function (){ return this._decodeInt(8, true); },
+ readUInt8: function (){ return this._decodeInt(8, false); },
+ readInt16: function (){ return this._decodeInt(16, true); },
+ readUInt16: function (){ return this._decodeInt(16, false); },
+ readInt32: function (){ return this._decodeInt(32, true); },
+ readUInt32: function (){ return this._decodeInt(32, false); },
+
+ readFloat: function (){ return this._decodeFloat(23, 8); },
+ readDouble: function (){ return this._decodeFloat(52, 11); },
+
+ readChar: function () { return this.readString(1); },
+ readString: function (length) {
+ this._checkSize(length * 8);
+ var result = this._buffer.substr(this._pos, length);
+ this._pos += length;
+ return result;
+ },
+
+ seek: function (pos) {
+ this._pos = pos;
+ this._checkSize(0);
+ },
+
+ getPosition: function () {
+ return this._pos;
+ },
+
+ getSize: function () {
+ return this._buffer.length;
+ },
+
+
+ /* Private */
+
+ _decodeFloat: function(precisionBits, exponentBits){
+ var length = precisionBits + exponentBits + 1;
+ var size = length >> 3;
+ this._checkSize(length);
+
+ var bias = Math.pow(2, exponentBits - 1) - 1;
+ var signal = this._readBits(precisionBits + exponentBits, 1, size);
+ var exponent = this._readBits(precisionBits, exponentBits, size);
+ var significand = 0;
+ var divisor = 2;
+ // var curByte = length + (-precisionBits >> 3) - 1;
+ var curByte = 0;
+ do {
+ var byteValue = this._readByte(++curByte, size);
+ var startBit = precisionBits % 8 || 8;
+ var mask = 1 << startBit;
+ while (mask >>= 1) {
+ if (byteValue & mask) {
+ significand += 1 / divisor;
+ }
+ divisor *= 2;
+ }
+ } while (precisionBits -= startBit);
+
+ this._pos += size;
+
+ return exponent == (bias << 1) + 1 ? significand ? NaN : signal ? -Infinity : +Infinity
+ : (1 + signal * -2) * (exponent || significand ? !exponent ? Math.pow(2, -bias + 1) * significand
+ : Math.pow(2, exponent - bias) * (1 + significand) : 0);
+ },
+
+ _decodeInt: function(bits, signed){
+ var x = this._readBits(0, bits, bits / 8), max = Math.pow(2, bits);
+ var result = signed && x >= max / 2 ? x - max : x;
+
+ this._pos += bits / 8;
+ return result;
+ },
+
+ //shl fix: Henri Torgemane ~1996 (compressed by Jonas Raoni)
+ _shl: function (a, b){
+ for (++b; --b; a = ((a %= 0x7fffffff + 1) & 0x40000000) == 0x40000000 ? a * 2 : (a - 0x40000000) * 2 + 0x7fffffff + 1);
+ return a;
+ },
+
+ _readByte: function (i, size) {
+ return this._buffer.charCodeAt(this._pos + size - i - 1) & 0xff;
+ },
+
+ _readBits: function (start, length, size) {
+ var offsetLeft = (start + length) % 8;
+ var offsetRight = start % 8;
+ var curByte = size - (start >> 3) - 1;
+ var lastByte = size + (-(start + length) >> 3);
+ var diff = curByte - lastByte;
+
+ var sum = (this._readByte(curByte, size) >> offsetRight) & ((1 << (diff ? 8 - offsetRight : length)) - 1);
+
+ if (diff && offsetLeft) {
+ sum += (this._readByte(lastByte++, size) & ((1 << offsetLeft) - 1)) << (diff-- << 3) - offsetRight;
+ }
+
+ while (diff) {
+ sum += this._shl(this._readByte(lastByte++, size), (diff-- << 3) - offsetRight);
+ }
+
+ return sum;
+ },
+
+ _checkSize: function (neededBits) {
+ if (!(this._pos + Math.ceil(neededBits / 8) < this._buffer.length)) {
+ throw new Error("Index out of bound");
+ }
+ }
+}; \ No newline at end of file
diff --git a/extlib/thingiview.js/plane.js b/extlib/thingiview.js/plane.js
new file mode 100644
index 00000000..9f970be0
--- /dev/null
+++ b/extlib/thingiview.js/plane.js
@@ -0,0 +1,62 @@
+/**
+ * @author mr.doob / http://mrdoob.com/
+ * based on http://papervision3d.googlecode.com/svn/trunk/as3/trunk/src/org/papervision3d/objects/primitives/Plane.as
+ */
+
+var Plane = function ( width, height, segments_width, segments_height ) {
+
+ THREE.Geometry.call( this );
+
+ var ix, iy,
+ width_half = width / 2,
+ height_half = height / 2,
+ gridX = segments_width || 1,
+ gridY = segments_height || 1,
+ gridX1 = gridX + 1,
+ gridY1 = gridY + 1,
+ segment_width = width / gridX,
+ segment_height = height / gridY;
+
+
+ for( iy = 0; iy < gridY1; iy++ ) {
+
+ for( ix = 0; ix < gridX1; ix++ ) {
+
+ var x = ix * segment_width - width_half;
+ var y = iy * segment_height - height_half;
+
+ this.vertices.push( new THREE.Vertex( new THREE.Vector3( x, - y, 0 ) ) );
+
+ }
+
+ }
+
+ for( iy = 0; iy < gridY; iy++ ) {
+
+ for( ix = 0; ix < gridX; ix++ ) {
+
+ var a = ix + gridX1 * iy;
+ var b = ix + gridX1 * ( iy + 1 );
+ var c = ( ix + 1 ) + gridX1 * ( iy + 1 );
+ var d = ( ix + 1 ) + gridX1 * iy;
+
+ this.faces.push( new THREE.Face4( a, b, c, d ) );
+ this.uvs.push( [
+ new THREE.UV( ix / gridX, iy / gridY ),
+ new THREE.UV( ix / gridX, ( iy + 1 ) / gridY ),
+ new THREE.UV( ( ix + 1 ) / gridX, ( iy + 1 ) / gridY ),
+ new THREE.UV( ( ix + 1 ) / gridX, iy / gridY )
+ ] );
+
+ }
+
+ }
+
+ this.computeCentroids();
+ this.computeFaceNormals();
+ this.sortFacesByMaterial();
+
+};
+
+Plane.prototype = new THREE.Geometry();
+Plane.prototype.constructor = Plane;
diff --git a/extlib/thingiview.js/stats.js b/extlib/thingiview.js/stats.js
new file mode 100644
index 00000000..270d1ce3
--- /dev/null
+++ b/extlib/thingiview.js/stats.js
@@ -0,0 +1,2 @@
+// stats.js r5 - http://github.com/mrdoob/stats.js
+var Stats=function(){var j=0,u=2,r,C=0,E=new Date().getTime(),w=E,f=E,m=0,e=1000,i=0,F,q,c,d,B,k=0,G=1000,a=0,A,t,p,D,l,v=0,o=1000,s=0,h,n,z,g,b,y={fps:{bg:{r:16,g:16,b:48},fg:{r:0,g:255,b:255}},ms:{bg:{r:16,g:48,b:16},fg:{r:0,g:255,b:0}},mem:{bg:{r:48,g:16,b:26},fg:{r:255,g:0,b:128}}};r=document.createElement("div");r.style.fontFamily="Helvetica, Arial, sans-serif";r.style.textAlign="left";r.style.fontSize="9px";r.style.opacity="0.9";r.style.width="80px";r.style.cursor="pointer";r.addEventListener("click",H,false);F=document.createElement("div");F.style.backgroundColor="rgb("+Math.floor(y.fps.bg.r/2)+","+Math.floor(y.fps.bg.g/2)+","+Math.floor(y.fps.bg.b/2)+")";F.style.padding="2px 0px 3px 0px";r.appendChild(F);q=document.createElement("div");q.innerHTML="<strong>FPS</strong>";q.style.color="rgb("+y.fps.fg.r+","+y.fps.fg.g+","+y.fps.fg.b+")";q.style.margin="0px 0px 1px 3px";F.appendChild(q);c=document.createElement("canvas");c.width=74;c.height=30;c.style.display="block";c.style.marginLeft="3px";F.appendChild(c);d=c.getContext("2d");d.fillStyle="rgb("+y.fps.bg.r+","+y.fps.bg.g+","+y.fps.bg.b+")";d.fillRect(0,0,c.width,c.height);B=d.getImageData(0,0,c.width,c.height);A=document.createElement("div");A.style.backgroundColor="rgb("+Math.floor(y.ms.bg.r/2)+","+Math.floor(y.ms.bg.g/2)+","+Math.floor(y.ms.bg.b/2)+")";A.style.padding="2px 0px 3px 0px";A.style.display="none";r.appendChild(A);t=document.createElement("div");t.innerHTML="<strong>MS</strong>";t.style.color="rgb("+y.ms.fg.r+","+y.ms.fg.g+","+y.ms.fg.b+")";t.style.margin="0px 0px 1px 3px";A.appendChild(t);p=document.createElement("canvas");p.width=74;p.height=30;p.style.display="block";p.style.marginLeft="3px";A.appendChild(p);D=p.getContext("2d");D.fillStyle="rgb("+y.ms.bg.r+","+y.ms.bg.g+","+y.ms.bg.b+")";D.fillRect(0,0,p.width,p.height);l=D.getImageData(0,0,p.width,p.height);try{if(webkitPerformance&&webkitPerformance.memory.totalJSHeapSize){u=3}}catch(x){}h=document.createElement("div");h.style.backgroundColor="rgb("+Math.floor(y.mem.bg.r/2)+","+Math.floor(y.mem.bg.g/2)+","+Math.floor(y.mem.bg.b/2)+")";h.style.padding="2px 0px 3px 0px";h.style.display="none";r.appendChild(h);n=document.createElement("div");n.innerHTML="<strong>MEM</strong>";n.style.color="rgb("+y.mem.fg.r+","+y.mem.fg.g+","+y.mem.fg.b+")";n.style.margin="0px 0px 1px 3px";h.appendChild(n);z=document.createElement("canvas");z.width=74;z.height=30;z.style.display="block";z.style.marginLeft="3px";h.appendChild(z);g=z.getContext("2d");g.fillStyle="#301010";g.fillRect(0,0,z.width,z.height);b=g.getImageData(0,0,z.width,z.height);function I(N,M,K){var J,O,L;for(O=0;O<30;O++){for(J=0;J<73;J++){L=(J+O*74)*4;N[L]=N[L+4];N[L+1]=N[L+5];N[L+2]=N[L+6]}}for(O=0;O<30;O++){L=(73+O*74)*4;if(O<M){N[L]=y[K].bg.r;N[L+1]=y[K].bg.g;N[L+2]=y[K].bg.b}else{N[L]=y[K].fg.r;N[L+1]=y[K].fg.g;N[L+2]=y[K].fg.b}}}function H(){j++;j==u?j=0:j;F.style.display="none";A.style.display="none";h.style.display="none";switch(j){case 0:F.style.display="block";break;case 1:A.style.display="block";break;case 2:h.style.display="block";break}}return{domElement:r,update:function(){C++;E=new Date().getTime();k=E-w;G=Math.min(G,k);a=Math.max(a,k);I(l.data,Math.min(30,30-(k/200)*30),"ms");t.innerHTML="<strong>"+k+" MS</strong> ("+G+"-"+a+")";D.putImageData(l,0,0);w=E;if(E>f+1000){m=Math.round((C*1000)/(E-f));e=Math.min(e,m);i=Math.max(i,m);I(B.data,Math.min(30,30-(m/100)*30),"fps");q.innerHTML="<strong>"+m+" FPS</strong> ("+e+"-"+i+")";d.putImageData(B,0,0);if(u==3){v=webkitPerformance.memory.usedJSHeapSize*9.54e-7;o=Math.min(o,v);s=Math.max(s,v);I(b.data,Math.min(30,30-(v/2)),"mem");n.innerHTML="<strong>"+Math.round(v)+" MEM</strong> ("+Math.round(o)+"-"+Math.round(s)+")";g.putImageData(b,0,0)}f=E;C=0}}}}; \ No newline at end of file
diff --git a/extlib/thingiview.js/thingiloader.js b/extlib/thingiview.js/thingiloader.js
new file mode 100644
index 00000000..3791a49c
--- /dev/null
+++ b/extlib/thingiview.js/thingiloader.js
@@ -0,0 +1,318 @@
+Thingiloader = function(event) {
+ // Code from https://developer.mozilla.org/En/Using_XMLHttpRequest#Receiving_binary_data
+ this.load_binary_resource = function(url) {
+ var req = new XMLHttpRequest();
+ req.open('GET', url, false);
+ // The following line says we want to receive data as Binary and not as Unicode
+ req.overrideMimeType('text/plain; charset=x-user-defined');
+ req.send(null);
+ if (req.status != 200) return '';
+
+ return req.responseText;
+ };
+
+ this.loadSTL = function(url) {
+ var looksLikeBinary = function(reader) {
+ // STL files don't specify a way to distinguish ASCII from binary.
+ // The usual way is checking for "solid" at the start of the file --
+ // but Thingiverse has seen at least one binary STL file in the wild
+ // that breaks this.
+
+ // The approach here is different: binary STL files contain a triangle
+ // count early in the file. If this correctly predicts the file's length,
+ // it is most probably a binary STL file.
+
+ reader.seek(80); // skip the header
+ var count = reader.readUInt32();
+
+ var predictedSize = 80 /* header */ + 4 /* count */ + 50 * count;
+ return reader.getSize() == predictedSize;
+ };
+
+ workerFacadeMessage({'status':'message', 'content':'Downloading ' + url});
+ var file = this.load_binary_resource(url);
+ var reader = new BinaryReader(file);
+
+ if (looksLikeBinary(reader)) {
+ this.loadSTLBinary(reader);
+ } else {
+ this.loadSTLString(file);
+ }
+ };
+
+ this.loadOBJ = function(url) {
+ workerFacadeMessage({'status':'message', 'content':'Downloading ' + url});
+ var file = this.load_binary_resource(url);
+ this.loadOBJString(file);
+ };
+
+ this.loadJSON = function(url) {
+ workerFacadeMessage({'status':'message', 'content':'Downloading ' + url});
+ var file = this.load_binary_resource(url);
+ this.loadJSONString(file);
+ };
+
+ this.loadPLY = function(url) {
+ workerFacadeMessage({'status':'message', 'content':'Downloading ' + url});
+
+ var file = this.load_binary_resource(url);
+
+ if (file.match(/format ascii/i)) {
+ this.loadPLYString(file);
+ } else {
+ this.loadPLYBinary(file);
+ }
+ };
+
+ this.loadSTLString = function(STLString) {
+ workerFacadeMessage({'status':'message', 'content':'Parsing STL String...'});
+ workerFacadeMessage({'status':'complete', 'content':this.ParseSTLString(STLString)});
+ };
+
+ this.loadSTLBinary = function(STLBinary) {
+ workerFacadeMessage({'status':'message', 'content':'Parsing STL Binary...'});
+ workerFacadeMessage({'status':'complete', 'content':this.ParseSTLBinary(STLBinary)});
+ };
+
+ this.loadOBJString = function(OBJString) {
+ workerFacadeMessage({'status':'message', 'content':'Parsing OBJ String...'});
+ workerFacadeMessage({'status':'complete', 'content':this.ParseOBJString(OBJString)});
+ };
+
+ this.loadJSONString = function(JSONString) {
+ workerFacadeMessage({'status':'message', 'content':'Parsing JSON String...'});
+ workerFacadeMessage({'status':'complete', 'content':eval(JSONString)});
+ };
+
+ this.loadPLYString = function(PLYString) {
+ workerFacadeMessage({'status':'message', 'content':'Parsing PLY String...'});
+ workerFacadeMessage({'status':'complete_points', 'content':this.ParsePLYString(PLYString)});
+ };
+
+ this.loadPLYBinary = function(PLYBinary) {
+ workerFacadeMessage({'status':'message', 'content':'Parsing PLY Binary...'});
+ workerFacadeMessage({'status':'complete_points', 'content':this.ParsePLYBinary(PLYBinary)});
+ };
+
+ this.ParsePLYString = function(input) {
+ var properties = [];
+ var vertices = [];
+ var colors = [];
+
+ var vertex_count = 0;
+
+ var header = /ply\n([\s\S]+)\nend_header/ig.exec(input)[1];
+ var data = /end_header\n([\s\S]+)$/ig.exec(input)[1];
+
+ // workerFacadeMessage({'status':'message', 'content':'header:\n' + header});
+ // workerFacadeMessage({'status':'message', 'content':'data:\n' + data});
+
+ header_parts = header.split("\n");
+
+ for (i in header_parts) {
+ if (/element vertex/i.test(header_parts[i])) {
+ vertex_count = /element vertex (\d+)/i.exec(header_parts[i])[1];
+ } else if (/property/i.test(header_parts[i])) {
+ properties.push(/property (.*) (.*)/i.exec(header_parts[i])[2]);
+ }
+ }
+
+ // workerFacadeMessage({'status':'message', 'content':'properties: ' + properties});
+
+ data_parts = data.split("\n");
+
+ for (i in data_parts) {
+ data_line = data_parts[i];
+ data_line_parts = data_line.split(" ");
+
+ vertices.push([
+ parseFloat(data_line_parts[properties.indexOf("x")]),
+ parseFloat(data_line_parts[properties.indexOf("y")]),
+ parseFloat(data_line_parts[properties.indexOf("z")])
+ ]);
+
+ colors.push([
+ parseInt(data_line_parts[properties.indexOf("red")]),
+ parseInt(data_line_parts[properties.indexOf("green")]),
+ parseInt(data_line_parts[properties.indexOf("blue")])
+ ]);
+ }
+
+ // workerFacadeMessage({'status':'message', 'content':'vertices: ' + vertices});
+
+ return [vertices, colors];
+ };
+
+ this.ParsePLYBinary = function(input) {
+ return false;
+ };
+
+ this.ParseSTLBinary = function(input) {
+ // Skip the header.
+ input.seek(80);
+
+ // Load the number of vertices.
+ var count = input.readUInt32();
+
+ // During the parse loop we maintain the following data structures:
+ var vertices = []; // Append-only list of all unique vertices.
+ var vert_hash = {}; // Mapping from vertex to index in 'vertices', above.
+ var faces = []; // List of triangle descriptions, each a three-element
+ // list of indices in 'vertices', above.
+
+ for (var i = 0; i < count; i++) {
+ if (i % 100 == 0) {
+ workerFacadeMessage({
+ 'status':'message',
+ 'content':'Parsing ' + (i+1) + ' of ' + count + ' polygons...'
+ });
+ workerFacadeMessage({
+ 'status':'progress',
+ 'content':parseInt(i / count * 100) + '%'
+ });
+ }
+
+ // Skip the normal (3 single-precision floats)
+ input.seek(input.getPosition() + 12);
+
+ var face_indices = [];
+ for (var x = 0; x < 3; x++) {
+ var vertex = [input.readFloat(), input.readFloat(), input.readFloat()];
+
+ var vertexIndex = vert_hash[vertex];
+ if (vertexIndex == null) {
+ vertexIndex = vertices.length;
+ vertices.push(vertex);
+ vert_hash[vertex] = vertexIndex;
+ }
+
+ face_indices.push(vertexIndex);
+ }
+ faces.push(face_indices);
+
+ // Skip the "attribute" field (unused in common models)
+ input.readUInt16();
+ }
+
+ return [vertices, faces];
+ };
+
+ // build stl's vertex and face arrays
+ this.ParseSTLString = function(STLString) {
+ var vertexes = [];
+ var faces = [];
+
+ var face_vertexes = [];
+ var vert_hash = {}
+
+ // console.log(STLString);
+
+ // strip out extraneous stuff
+ STLString = STLString.replace(/\r/, "\n");
+ STLString = STLString.replace(/^solid[^\n]*/, "");
+ STLString = STLString.replace(/\n/g, " ");
+ STLString = STLString.replace(/facet normal /g,"");
+ STLString = STLString.replace(/outer loop/g,"");
+ STLString = STLString.replace(/vertex /g,"");
+ STLString = STLString.replace(/endloop/g,"");
+ STLString = STLString.replace(/endfacet/g,"");
+ STLString = STLString.replace(/endsolid[^\n]*/, "");
+ STLString = STLString.replace(/\s+/g, " ");
+ STLString = STLString.replace(/^\s+/, "");
+
+ // console.log(STLString);
+
+ var facet_count = 0;
+ var block_start = 0;
+
+ var points = STLString.split(" ");
+
+ workerFacadeMessage({'status':'message', 'content':'Parsing vertices...'});
+ for (var i=0; i<points.length/12-1; i++) {
+ if ((i % 100) == 0) {
+ workerFacadeMessage({'status':'progress', 'content':parseInt(i / (points.length/12-1) * 100) + '%'});
+ }
+
+ var face_indices = [];
+ for (var x=0; x<3; x++) {
+ var vertex = [parseFloat(points[block_start+x*3+3]), parseFloat(points[block_start+x*3+4]), parseFloat(points[block_start+x*3+5])];
+
+ var vertexIndex = vert_hash[vertex];
+ if (vertexIndex == null) {
+ vertexIndex = vertexes.length;
+ vertexes.push(vertex);
+ vert_hash[vertex] = vertexIndex;
+ }
+
+ face_indices.push(vertexIndex);
+ }
+ faces.push(face_indices);
+
+ block_start = block_start + 12;
+ }
+
+ return [vertexes, faces];
+ };
+
+ this.ParseOBJString = function(OBJString) {
+ var vertexes = [];
+ var faces = [];
+
+ var lines = OBJString.split("\n");
+
+ // var normal_position = 0;
+
+ for (var i=0; i<lines.length; i++) {
+ workerFacadeMessage({'status':'progress', 'content':parseInt(i / lines.length * 100) + '%'});
+
+ line_parts = lines[i].replace(/\s+/g, " ").split(" ");
+
+ if (line_parts[0] == "v") {
+ vertexes.push([parseFloat(line_parts[1]), parseFloat(line_parts[2]), parseFloat(line_parts[3])]);
+ } else if (line_parts[0] == "f") {
+ faces.push([parseFloat(line_parts[1].split("/")[0])-1, parseFloat(line_parts[2].split("/")[0])-1, parseFloat(line_parts[3].split("/")[0]-1), 0])
+ }
+ }
+
+ return [vertexes, faces];
+ };
+
+ switch(event.data.cmd) {
+ case "loadSTL":
+ this.loadSTL(event.data.param);
+ break;
+ case "loadSTLString":
+ this.loadSTLString(event.data.param);
+ break;
+ case "loadSTLBinary":
+ this.loadSTLBinary(event.data.param);
+ break;
+ case "loadOBJ":
+ this.loadOBJ(event.data.param);
+ break;
+ case "loadOBJString":
+ this.loadOBJString(event.data.param);
+ break;
+ case "loadJSON":
+ this.loadJSON(event.data.param);
+ break;
+ case "loadPLY":
+ this.loadPLY(event.data.param);
+ break;
+ case "loadPLYString":
+ this.loadPLYString(event.data.param);
+ break;
+ case "loadPLYBinary":
+ this.loadPLYBinary(event.data.param);
+ break;
+ }
+
+};
+
+if (typeof(window) === "undefined") {
+ onmessage = Thingiloader;
+ workerFacadeMessage = postMessage;
+ importScripts('binaryReader.js');
+} else {
+ workerFacadeMessage = WorkerFacade.add(thingiurlbase + "/thingiloader.js", Thingiloader);
+}
diff --git a/extlib/thingiview.js/thingiview.js b/extlib/thingiview.js/thingiview.js
new file mode 100644
index 00000000..5eb30335
--- /dev/null
+++ b/extlib/thingiview.js/thingiview.js
@@ -0,0 +1,898 @@
+Thingiview = function(containerId) {
+ scope = this;
+
+ this.containerId = containerId;
+ var container = document.getElementById(containerId);
+
+ // var stats = null;
+ var camera = null;
+ var scene = null;
+ var renderer = null;
+ var object = null;
+ var plane = null;
+
+ var ambientLight = null;
+ var directionalLight = null;
+ var pointLight = null;
+
+ var targetXRotation = 0;
+ var targetXRotationOnMouseDown = 0;
+ var mouseX = 0;
+ var mouseXOnMouseDown = 0;
+
+ var targetYRotation = 0;
+ var targetYRotationOnMouseDown = 0;
+ var mouseY = 0;
+ var mouseYOnMouseDown = 0;
+
+ var mouseDown = false;
+ var mouseOver = false;
+
+ var windowHalfX = window.innerWidth / 2;
+ var windowHalfY = window.innerHeight / 2
+
+ var view = null;
+ var infoMessage = null;
+ var progressBar = null;
+ var alertBox = null;
+
+ var timer = null;
+
+ var rotateTimer = null;
+ var rotateListener = null;
+ var wasRotating = null;
+
+ var cameraView = 'diagonal';
+ var cameraZoom = 0;
+ var rotate = false;
+ var backgroundColor = '#606060';
+ var objectMaterial = 'solid';
+ var objectColor = 0xffffff;
+ var showPlane = true;
+ var isWebGl = false;
+
+ if (document.defaultView && document.defaultView.getComputedStyle) {
+ var width = parseFloat(document.defaultView.getComputedStyle(container,null).getPropertyValue('width'));
+ var height = parseFloat(document.defaultView.getComputedStyle(container,null).getPropertyValue('height'));
+ } else {
+ var width = parseFloat(container.currentStyle.width);
+ var height = parseFloat(container.currentStyle.height);
+ }
+
+ var geometry;
+
+ this.initScene = function() {
+ container.style.position = 'relative';
+ container.innerHTML = '';
+
+ camera = new THREE.Camera(45, width/ height, 1, 100000);
+ camera.updateMatrix();
+
+ scene = new THREE.Scene();
+
+ ambientLight = new THREE.AmbientLight(0x202020);
+ scene.addLight(ambientLight);
+
+ directionalLight = new THREE.DirectionalLight(0xffffff, 0.75);
+ directionalLight.position.x = 1;
+ directionalLight.position.y = 1;
+ directionalLight.position.z = 2;
+ directionalLight.position.normalize();
+ scene.addLight(directionalLight);
+
+ pointLight = new THREE.PointLight(0xffffff, 0.3);
+ pointLight.position.x = 0;
+ pointLight.position.y = -25;
+ pointLight.position.z = 10;
+ scene.addLight(pointLight);
+
+ progressBar = document.createElement('div');
+ progressBar.style.position = 'absolute';
+ progressBar.style.top = '0px';
+ progressBar.style.left = '0px';
+ progressBar.style.backgroundColor = 'red';
+ progressBar.style.padding = '5px';
+ progressBar.style.display = 'none';
+ progressBar.style.overflow = 'visible';
+ progressBar.style.whiteSpace = 'nowrap';
+ progressBar.style.zIndex = 100;
+ container.appendChild(progressBar);
+
+ alertBox = document.createElement('div');
+ alertBox.id = 'alertBox';
+ alertBox.style.position = 'absolute';
+ alertBox.style.top = '25%';
+ alertBox.style.left = '25%';
+ alertBox.style.width = '50%';
+ alertBox.style.height = '50%';
+ alertBox.style.backgroundColor = '#dddddd';
+ alertBox.style.padding = '10px';
+ // alertBox.style.overflowY = 'scroll';
+ alertBox.style.display = 'none';
+ alertBox.style.zIndex = 100;
+ container.appendChild(alertBox);
+
+ // load a blank object
+ // this.loadSTLString('');
+
+ if (showPlane) {
+ loadPlaneGeometry();
+ }
+
+ this.setCameraView(cameraView);
+ this.setObjectMaterial(objectMaterial);
+
+ testCanvas = document.createElement('canvas');
+ try {
+ if (testCanvas.getContext('experimental-webgl')) {
+ // showPlane = false;
+ isWebGl = true;
+ renderer = new THREE.WebGLRenderer();
+ // renderer = new THREE.CanvasRenderer();
+ } else {
+ renderer = new THREE.CanvasRenderer();
+ }
+ } catch(e) {
+ renderer = new THREE.CanvasRenderer();
+ // log("failed webgl detection");
+ }
+
+ // renderer.setSize(container.innerWidth, container.innerHeight);
+
+ renderer.setSize(width, height);
+ renderer.domElement.style.backgroundColor = backgroundColor;
+ container.appendChild(renderer.domElement);
+
+ // stats = new Stats();
+ // stats.domElement.style.position = 'absolute';
+ // stats.domElement.style.top = '0px';
+ // container.appendChild(stats.domElement);
+
+ // TODO: figure out how to get the render window to resize when window resizes
+ // window.addEventListener('resize', onContainerResize(), false);
+ // container.addEventListener('resize', onContainerResize(), false);
+
+ // renderer.domElement.addEventListener('mousemove', onRendererMouseMove, false);
+ window.addEventListener('mousemove', onRendererMouseMove, false);
+ renderer.domElement.addEventListener('mouseover', onRendererMouseOver, false);
+ renderer.domElement.addEventListener('mouseout', onRendererMouseOut, false);
+ renderer.domElement.addEventListener('mousedown', onRendererMouseDown, false);
+ // renderer.domElement.addEventListener('mouseup', onRendererMouseUp, false);
+ window.addEventListener('mouseup', onRendererMouseUp, false);
+
+ renderer.domElement.addEventListener('touchstart', onRendererTouchStart, false);
+ renderer.domElement.addEventListener('touchend', onRendererTouchEnd, false);
+ renderer.domElement.addEventListener('touchmove', onRendererTouchMove, false);
+
+ renderer.domElement.addEventListener('DOMMouseScroll', onRendererScroll, false);
+ renderer.domElement.addEventListener('mousewheel', onRendererScroll, false);
+ renderer.domElement.addEventListener('gesturechange', onRendererGestureChange, false);
+ }
+
+ // FIXME
+ // onContainerResize = function(event) {
+ // width = parseFloat(document.defaultView.getComputedStyle(container,null).getPropertyValue('width'));
+ // height = parseFloat(document.defaultView.getComputedStyle(container,null).getPropertyValue('height'));
+ //
+ // // log("resized width: " + width + ", height: " + height);
+ //
+ // if (renderer) {
+ // renderer.setSize(width, height);
+ // camera.projectionMatrix = THREE.Matrix4.makePerspective(70, width / height, 1, 10000);
+ // sceneLoop();
+ // }
+ // };
+
+ onRendererScroll = function(event) {
+ event.preventDefault();
+
+ var rolled = 0;
+
+ if (event.wheelDelta === undefined) {
+ // Firefox
+ // The measurement units of the detail and wheelDelta properties are different.
+ rolled = -40 * event.detail;
+ } else {
+ rolled = event.wheelDelta;
+ }
+
+ if (rolled > 0) {
+ // up
+ scope.setCameraZoom(+10);
+ } else {
+ // down
+ scope.setCameraZoom(-10);
+ }
+ }
+
+ onRendererGestureChange = function(event) {
+ event.preventDefault();
+
+ if (event.scale > 1) {
+ scope.setCameraZoom(+5);
+ } else {
+ scope.setCameraZoom(-5);
+ }
+ }
+
+ onRendererMouseOver = function(event) {
+ mouseOver = true;
+ // targetRotation = object.rotation.z;
+ if (timer == null) {
+ // log('starting loop');
+ timer = setInterval(sceneLoop, 1000/60);
+ }
+ }
+
+ onRendererMouseDown = function(event) {
+ // log("down");
+
+ event.preventDefault();
+ mouseDown = true;
+
+ if(scope.getRotation()){
+ wasRotating = true;
+ scope.setRotation(false);
+ } else {
+ wasRotating = false;
+ }
+
+ mouseXOnMouseDown = event.clientX - windowHalfX;
+ mouseYOnMouseDown = event.clientY - windowHalfY;
+
+ targetXRotationOnMouseDown = targetXRotation;
+ targetYRotationOnMouseDown = targetYRotation;
+ }
+
+ onRendererMouseMove = function(event) {
+ // log("move");
+
+ if (mouseDown) {
+ mouseX = event.clientX - windowHalfX;
+ // targetXRotation = targetXRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.02;
+ xrot = targetXRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.02;
+
+ mouseY = event.clientY - windowHalfY;
+ // targetYRotation = targetYRotationOnMouseDown + (mouseY - mouseYOnMouseDown) * 0.02;
+ yrot = targetYRotationOnMouseDown + (mouseY - mouseYOnMouseDown) * 0.02;
+
+ targetXRotation = xrot;
+ targetYRotation = yrot;
+ }
+ }
+
+ onRendererMouseUp = function(event) {
+ // log("up");
+ if (mouseDown) {
+ mouseDown = false;
+ if (!mouseOver) {
+ clearInterval(timer);
+ timer = null;
+ }
+ if (wasRotating) {
+ scope.setRotation(true);
+ }
+ }
+ }
+
+ onRendererMouseOut = function(event) {
+ if (!mouseDown) {
+ clearInterval(timer);
+ timer = null;
+ }
+ mouseOver = false;
+ }
+
+ onRendererTouchStart = function(event) {
+ targetXRotation = object.rotation.z;
+ targetYRotation = object.rotation.x;
+
+ timer = setInterval(sceneLoop, 1000/60);
+
+ if (event.touches.length == 1) {
+ event.preventDefault();
+
+ mouseXOnMouseDown = event.touches[0].pageX - windowHalfX;
+ targetXRotationOnMouseDown = targetXRotation;
+
+ mouseYOnMouseDown = event.touches[0].pageY - windowHalfY;
+ targetYRotationOnMouseDown = targetYRotation;
+ }
+ }
+
+ onRendererTouchEnd = function(event) {
+ clearInterval(timer);
+ timer = null;
+ // targetXRotation = object.rotation.z;
+ // targetYRotation = object.rotation.x;
+ }
+
+ onRendererTouchMove = function(event) {
+ if (event.touches.length == 1) {
+ event.preventDefault();
+
+ mouseX = event.touches[0].pageX - windowHalfX;
+ targetXRotation = targetXRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.05;
+
+ mouseY = event.touches[0].pageY - windowHalfY;
+ targetYRotation = targetYRotationOnMouseDown + (mouseY - mouseYOnMouseDown) * 0.05;
+ }
+ }
+
+ sceneLoop = function() {
+ if (object) {
+ // if (view == 'bottom') {
+ // if (showPlane) {
+ // plane.rotation.z = object.rotation.z -= (targetRotation + object.rotation.z) * 0.05;
+ // } else {
+ // object.rotation.z -= (targetRotation + object.rotation.z) * 0.05;
+ // }
+ // } else {
+ // if (showPlane) {
+ // plane.rotation.z = object.rotation.z += (targetRotation - object.rotation.z) * 0.05;
+ // } else {
+ // object.rotation.z += (targetRotation - object.rotation.z) * 0.05;
+ // }
+ // }
+
+ if (showPlane) {
+ plane.rotation.z = object.rotation.z = (targetXRotation - object.rotation.z) * 0.2;
+ plane.rotation.x = object.rotation.x = (targetYRotation - object.rotation.x) * 0.2;
+ } else {
+ object.rotation.z = (targetXRotation - object.rotation.z) * 0.2;
+ object.rotation.x = (targetYRotation - object.rotation.x) * 0.2;
+ }
+
+ // log(object.rotation.x);
+
+ camera.updateMatrix();
+ object.updateMatrix();
+
+ if (showPlane) {
+ plane.updateMatrix();
+ }
+
+ renderer.render(scene, camera);
+ // stats.update();
+ }
+ }
+
+ rotateLoop = function() {
+ // targetRotation += 0.01;
+ targetXRotation += 0.05;
+ sceneLoop();
+ }
+
+ this.getShowPlane = function(){
+ return showPlane;
+ }
+
+ this.setShowPlane = function(show) {
+ showPlane = show;
+
+ if (show) {
+ if (scene && !plane) {
+ loadPlaneGeometry();
+ }
+ plane.material[0].opacity = 1;
+ // plane.updateMatrix();
+ } else {
+ if (scene && plane) {
+ // alert(plane.material[0].opacity);
+ plane.material[0].opacity = 0;
+ // plane.updateMatrix();
+ }
+ }
+
+ sceneLoop();
+ }
+
+ this.getRotation = function() {
+ return rotateTimer !== null;
+ }
+
+ this.resetRotation = function () {
+ if (rotate) {
+ this.setRotation(false);
+ this.setRotation(true);
+ }
+ }
+
+ this.setRotation = function(rotate) {
+ rotation = rotate;
+
+ if (rotate) {
+ rotateTimer = setInterval(rotateLoop, 1000/60);
+ } else {
+ clearInterval(rotateTimer);
+ rotateTimer = null;
+ }
+
+ scope.onSetRotation();
+ }
+
+ this.onSetRotation = function(callback) {
+ if(callback === undefined){
+ if(rotateListener !== null){
+ try{
+ rotateListener(scope.getRotation());
+ } catch(ignored) {}
+ }
+ } else {
+ rotateListener = callback;
+ }
+ }
+
+ this.setCameraView = function(dir) {
+ cameraView = dir;
+
+ targetXRotation = 0;
+ targetYRotation = 0;
+
+ if (object) {
+ object.rotation.x = 0;
+ object.rotation.y = 0;
+ object.rotation.z = 0;
+ }
+
+ if (showPlane && object) {
+ plane.rotation.x = object.rotation.x;
+ plane.rotation.y = object.rotation.y;
+ plane.rotation.z = object.rotation.z;
+ }
+
+ if (dir == 'top') {
+ // camera.position.y = 0;
+ // camera.position.z = 100;
+ // camera.target.position.z = 0;
+ if (showPlane) {
+ plane.flipSided = false;
+ }
+ } else if (dir == 'side') {
+ // camera.position.y = -70;
+ // camera.position.z = 70;
+ // camera.target.position.z = 0;
+ targetYRotation = -4.5;
+ if (showPlane) {
+ plane.flipSided = false;
+ }
+ } else if (dir == 'bottom') {
+ // camera.position.y = 0;
+ // camera.position.z = -100;
+ // camera.target.position.z = 0;
+ if (showPlane) {
+ plane.flipSided = true;
+ }
+ } else {
+ // camera.position.y = -70;
+ // camera.position.z = 70;
+ // camera.target.position.z = 0;
+ if (showPlane) {
+ plane.flipSided = false;
+ }
+ }
+
+ mouseX = targetXRotation;
+ mouseXOnMouseDown = targetXRotation;
+
+ mouseY = targetYRotation;
+ mouseYOnMouseDown = targetYRotation;
+
+ scope.centerCamera();
+
+ sceneLoop();
+ }
+
+ this.setCameraZoom = function(factor) {
+ cameraZoom = factor;
+
+ if (cameraView == 'bottom') {
+ if (camera.position.z + factor > 0) {
+ factor = 0;
+ }
+ } else {
+ if (camera.position.z - factor < 0) {
+ factor = 0;
+ }
+ }
+
+ if (cameraView == 'top') {
+ camera.position.z -= factor;
+ } else if (cameraView == 'bottom') {
+ camera.position.z += factor;
+ } else if (cameraView == 'side') {
+ camera.position.y += factor;
+ camera.position.z -= factor;
+ } else {
+ camera.position.y += factor;
+ camera.position.z -= factor;
+ }
+
+ sceneLoop();
+ }
+
+ this.getObjectMaterial = function() {
+ return objectMaterial;
+ }
+
+ this.setObjectMaterial = function(type) {
+ objectMaterial = type;
+
+ loadObjectGeometry();
+ }
+
+ this.setBackgroundColor = function(color) {
+ backgroundColor = color
+
+ if (renderer) {
+ renderer.domElement.style.backgroundColor = color;
+ }
+ }
+
+ this.setObjectColor = function(color) {
+ objectColor = parseInt(color.replace(/\#/g, ''), 16);
+
+ loadObjectGeometry();
+ }
+
+ this.loadSTL = function(url) {
+ scope.newWorker('loadSTL', url);
+ }
+
+ this.loadOBJ = function(url) {
+ scope.newWorker('loadOBJ', url);
+ }
+
+ this.loadSTLString = function(STLString) {
+ scope.newWorker('loadSTLString', STLString);
+ }
+
+ this.loadSTLBinary = function(STLBinary) {
+ scope.newWorker('loadSTLBinary', STLBinary);
+ }
+
+ this.loadOBJString = function(OBJString) {
+ scope.newWorker('loadOBJString', OBJString);
+ }
+
+ this.loadJSON = function(url) {
+ scope.newWorker('loadJSON', url);
+ }
+
+ this.loadPLY = function(url) {
+ scope.newWorker('loadPLY', url);
+ }
+
+ this.loadPLYString = function(PLYString) {
+ scope.newWorker('loadPLYString', PLYString);
+ }
+
+ this.loadPLYBinary = function(PLYBinary) {
+ scope.newWorker('loadPLYBinary', PLYBinary);
+ }
+
+ this.centerCamera = function() {
+ if (geometry) {
+ // Using method from http://msdn.microsoft.com/en-us/library/bb197900(v=xnagamestudio.10).aspx
+ // log("bounding sphere radius = " + geometry.boundingSphere.radius);
+
+ // look at the center of the object
+ camera.target.position.x = geometry.center_x;
+ camera.target.position.y = geometry.center_y;
+ camera.target.position.z = geometry.center_z;
+
+ // set camera position to center of sphere
+ camera.position.x = geometry.center_x;
+ camera.position.y = geometry.center_y;
+ camera.position.z = geometry.center_z;
+
+ // find distance to center
+ distance = geometry.boundingSphere.radius / Math.sin((camera.fov/2) * (Math.PI / 180));
+
+ // zoom backwards about half that distance, I don't think I'm doing the math or backwards vector calculation correctly?
+ // scope.setCameraZoom(-distance/1.8);
+ // scope.setCameraZoom(-distance/1.5);
+ scope.setCameraZoom(-distance/1.9);
+
+ directionalLight.position.x = geometry.min_y * 2;
+ directionalLight.position.y = geometry.min_y * 2;
+ directionalLight.position.z = geometry.max_z * 2;
+
+ pointLight.position.x = geometry.center_y;
+ pointLight.position.y = geometry.center_y;
+ pointLight.position.z = geometry.max_z * 2;
+ } else {
+ // set to any valid position so it doesn't fail before geometry is available
+ camera.position.y = -70;
+ camera.position.z = 70;
+ camera.target.position.z = 0;
+ }
+ }
+
+ this.loadArray = function(array) {
+ log("loading array...");
+ geometry = new STLGeometry(array);
+ loadObjectGeometry();
+ scope.resetRotation();
+ scope.centerCamera();
+ log("finished loading " + geometry.faces.length + " faces.");
+ }
+
+ this.newWorker = function(cmd, param) {
+ scope.setRotation(false);
+
+ var worker = new WorkerFacade(thingiurlbase + '/thingiloader.js');
+
+ worker.onmessage = function(event) {
+ if (event.data.status == "complete") {
+ progressBar.innerHTML = 'Initializing geometry...';
+ // scene.removeObject(object);
+ geometry = new STLGeometry(event.data.content);
+ loadObjectGeometry();
+ progressBar.innerHTML = '';
+ progressBar.style.display = 'none';
+
+ scope.resetRotation();
+ log("finished loading " + geometry.faces.length + " faces.");
+ scope.centerCamera();
+ } else if (event.data.status == "complete_points") {
+ progressBar.innerHTML = 'Initializing points...';
+
+ geometry = new THREE.Geometry();
+
+ var material = new THREE.ParticleBasicMaterial( { color: 0xff0000, opacity: 1 } );
+
+ // material = new THREE.ParticleBasicMaterial( { size: 35, sizeAttenuation: false} );
+ // material.color.setHSV( 1.0, 0.2, 0.8 );
+
+ for (i in event.data.content[0]) {
+ // for (var i=0; i<10; i++) {
+ vector = new THREE.Vector3( event.data.content[0][i][0], event.data.content[0][i][1], event.data.content[0][i][2] );
+ geometry.vertices.push( new THREE.Vertex( vector ) );
+ }
+
+ particles = new THREE.ParticleSystem( geometry, material );
+ particles.sortParticles = true;
+ particles.updateMatrix();
+ scene.addObject( particles );
+
+ camera.updateMatrix();
+ renderer.render(scene, camera);
+
+ progressBar.innerHTML = '';
+ progressBar.style.display = 'none';
+
+ scope.resetRotation();
+ log("finished loading " + event.data.content[0].length + " points.");
+ // scope.centerCamera();
+ } else if (event.data.status == "progress") {
+ progressBar.style.display = 'block';
+ progressBar.style.width = event.data.content;
+ // log(event.data.content);
+ } else if (event.data.status == "message") {
+ progressBar.style.display = 'block';
+ progressBar.innerHTML = event.data.content;
+ log(event.data.content);
+ } else if (event.data.status == "alert") {
+ scope.displayAlert(event.data.content);
+ } else {
+ alert('Error: ' + event.data);
+ log('Unknown Worker Message: ' + event.data);
+ }
+ }
+
+ worker.onerror = function(error) {
+ log(error);
+ error.preventDefault();
+ }
+
+ worker.postMessage({'cmd':cmd, 'param':param});
+ }
+
+ this.displayAlert = function(msg) {
+ msg = msg + "<br/><br/><center><input type=\"button\" value=\"Ok\" onclick=\"document.getElementById('alertBox').style.display='none'\"></center>"
+
+ alertBox.innerHTML = msg;
+ alertBox.style.display = 'block';
+
+ // log(msg);
+ }
+
+ function loadPlaneGeometry() {
+ // TODO: switch to lines instead of the Plane object so we can get rid of the horizontal lines in canvas renderer...
+ plane = new THREE.Mesh(new Plane(100, 100, 10, 10), new THREE.MeshBasicMaterial({color:0xafafaf,wireframe:true}));
+ scene.addObject(plane);
+ }
+
+ function loadObjectGeometry() {
+ if (scene && geometry) {
+ if (objectMaterial == 'wireframe') {
+ // material = new THREE.MeshColorStrokeMaterial(objectColor, 1, 1);
+ material = new THREE.MeshBasicMaterial({color:objectColor,wireframe:true});
+ } else {
+ if (isWebGl) {
+ // material = new THREE.MeshPhongMaterial(objectColor, objectColor, 0xffffff, 50, 1.0);
+ // material = new THREE.MeshColorFillMaterial(objectColor);
+ // material = new THREE.MeshLambertMaterial({color:objectColor});
+ material = new THREE.MeshLambertMaterial({color:objectColor, shading: THREE.FlatShading});
+ } else {
+ // material = new THREE.MeshColorFillMaterial(objectColor);
+ material = new THREE.MeshLambertMaterial({color:objectColor, shading: THREE.FlatShading});
+ }
+ }
+
+ // scene.removeObject(object);
+
+ if (object) {
+ // shouldn't be needed, but this fixes a bug with webgl not removing previous object when loading a new one dynamically
+ object.materials = [new THREE.MeshBasicMaterial({color:0xffffff, opacity:0})];
+ scene.removeObject(object);
+ // object.geometry = geometry;
+ // object.materials = [material];
+ }
+
+ object = new THREE.Mesh(geometry, material);
+ scene.addObject(object);
+
+ if (objectMaterial != 'wireframe') {
+ object.overdraw = true;
+ object.doubleSided = true;
+ }
+
+ object.updateMatrix();
+
+ targetXRotation = 0;
+ targetYRotation = 0;
+
+ sceneLoop();
+ }
+ }
+
+};
+
+var STLGeometry = function(stlArray) {
+ // log("building geometry...");
+ THREE.Geometry.call(this);
+
+ var scope = this;
+
+ // var vertexes = stlArray[0];
+ // var normals = stlArray[1];
+ // var faces = stlArray[2];
+
+ for (var i=0; i<stlArray[0].length; i++) {
+ v(stlArray[0][i][0], stlArray[0][i][1], stlArray[0][i][2]);
+ }
+
+ for (var i=0; i<stlArray[1].length; i++) {
+ f3(stlArray[1][i][0], stlArray[1][i][1], stlArray[1][i][2]);
+ }
+
+ function v(x, y, z) {
+ // log("adding vertex: " + x + "," + y + "," + z);
+ scope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) );
+ }
+
+ function f3(a, b, c) {
+ // log("adding face: " + a + "," + b + "," + c)
+ scope.faces.push( new THREE.Face3( a, b, c ) );
+ }
+
+ // log("computing centroids...");
+ this.computeCentroids();
+ // log("computing normals...");
+ // this.computeNormals();
+ this.computeFaceNormals();
+ this.sortFacesByMaterial();
+ // log("finished building geometry");
+
+ scope.min_x = 0;
+ scope.min_y = 0;
+ scope.min_z = 0;
+
+ scope.max_x = 0;
+ scope.max_y = 0;
+ scope.max_z = 0;
+
+ for (var v = 0, vl = scope.vertices.length; v < vl; v ++) {
+ scope.max_x = Math.max(scope.max_x, scope.vertices[v].position.x);
+ scope.max_y = Math.max(scope.max_y, scope.vertices[v].position.y);
+ scope.max_z = Math.max(scope.max_z, scope.vertices[v].position.z);
+
+ scope.min_x = Math.min(scope.min_x, scope.vertices[v].position.x);
+ scope.min_y = Math.min(scope.min_y, scope.vertices[v].position.y);
+ scope.min_z = Math.min(scope.min_z, scope.vertices[v].position.z);
+}
+
+ scope.center_x = (scope.max_x + scope.min_x)/2;
+ scope.center_y = (scope.max_y + scope.min_y)/2;
+ scope.center_z = (scope.max_z + scope.min_z)/2;
+}
+
+STLGeometry.prototype = new THREE.Geometry();
+STLGeometry.prototype.constructor = STLGeometry;
+
+function log(msg) {
+ if (this.console) {
+ console.log(msg);
+ }
+}
+
+/* A facade for the Web Worker API that fakes it in case it's missing.
+Good when web workers aren't supported in the browser, but it's still fast enough, so execution doesn't hang too badly (e.g. Opera 10.5).
+By Stefan Wehrmeyer, licensed under MIT
+*/
+
+var WorkerFacade;
+if(!!window.Worker){
+ WorkerFacade = (function(){
+ return function(path){
+ return new window.Worker(path);
+ };
+ }());
+} else {
+ WorkerFacade = (function(){
+ var workers = {}, masters = {}, loaded = false;
+ var that = function(path){
+ var theworker = {}, loaded = false, callings = [];
+ theworker.postToWorkerFunction = function(args){
+ try{
+ workers[path]({"data":args});
+ }catch(err){
+ theworker.onerror(err);
+ }
+ };
+ theworker.postMessage = function(params){
+ if(!loaded){
+ callings.push(params);
+ return;
+ }
+ theworker.postToWorkerFunction(params);
+ };
+ masters[path] = theworker;
+ var scr = document.createElement("SCRIPT");
+ scr.src = path;
+ scr.type = "text/javascript";
+ scr.onload = function(){
+ loaded = true;
+ while(callings.length > 0){
+ theworker.postToWorkerFunction(callings[0]);
+ callings.shift();
+ }
+ };
+ document.body.appendChild(scr);
+
+ var binaryscr = document.createElement("SCRIPT");
+ binaryscr.src = thingiurlbase + '/binaryReader.js';
+ binaryscr.type = "text/javascript";
+ document.body.appendChild(binaryscr);
+
+ return theworker;
+ };
+ that.fake = true;
+ that.add = function(pth, worker){
+ workers[pth] = worker;
+ return function(param){
+ masters[pth].onmessage({"data": param});
+ };
+ };
+ that.toString = function(){
+ return "FakeWorker('"+path+"')";
+ };
+ return that;
+ }());
+}
+
+/* Then just use WorkerFacade instead of Worker (or alias it)
+
+The Worker code must should use a custom function (name it how you want) instead of postMessage.
+Put this at the end of the Worker:
+
+if(typeof(window) === "undefined"){
+ onmessage = nameOfWorkerFunction;
+ customPostMessage = postMessage;
+} else {
+ customPostMessage = WorkerFacade.add("path/to/thisworker.js", nameOfWorkerFunction);
+}
+
+*/
diff --git a/extlib/video-js/LGPLv3-LICENSE.txt b/extlib/video-js/LGPLv3-LICENSE.txt
new file mode 100644
index 00000000..65c5ca88
--- /dev/null
+++ b/extlib/video-js/LGPLv3-LICENSE.txt
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/extlib/video-js/demo.html b/extlib/video-js/demo.html
deleted file mode 100644
index a8393af0..00000000
--- a/extlib/video-js/demo.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <title>Video.js | HTML5 Video Player</title>
-
- <link href="http://vjs.zencdn.net/c/video-js.css" rel="stylesheet" type="text/css">
-
- <!-- video.js must be in the <head> for older IEs to work. -->
- <script src="http://vjs.zencdn.net/c/video.js"></script>
-
-</head>
-<body>
-
- <video id="example_video_1" class="video-js vjs-default-skin" controls preload="none" width="640" height="264"
- poster="http://video-js.zencoder.com/oceans-clip.png"
- data-setup="{}">
- <source src="http://video-js.zencoder.com/oceans-clip.mp4" type='video/mp4' />
- <source src="http://video-js.zencoder.com/oceans-clip.webm" type='video/webm' />
- <source src="http://video-js.zencoder.com/oceans-clip.ogv" type='video/ogg' />
- </video>
-
-</body>
-</html>
diff --git a/extlib/video-js/video-js.css b/extlib/video-js/video-js.css
deleted file mode 100644
index a1a18a00..00000000
--- a/extlib/video-js/video-js.css
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
-VideoJS Default Styles (http://videojs.com)
-Version 3.1.0
-*/
-
-/*
-REQUIRED STYLES (be careful overriding)
-================================================================================ */
-/* When loading the player, the video tag is replaced with a DIV,
- that will hold the video tag or object tag for other playback methods.
- The div contains the video playback element (Flash or HTML5) and controls, and sets the width and height of the video.
-
- ** If you want to add some kind of border/padding (e.g. a frame), or special positioning, use another containing element.
- Otherwise you risk messing up control positioning and full window mode. **
-*/
-.video-js {
- background-color: #000; position: relative; padding: 0;
-
- /* Start with 10px for base font size so other dimensions can be em based and easily calculable. */
- font-size: 10px;
-
- /* Allow poster to be vertially aligned. */
- vertical-align: middle;
- /* display: table-cell; */ /*This works in Safari but not Firefox.*/
-}
-
-/* Playback technology elements expand to the width/height of the containing div. <video> or <object> */
-.video-js .vjs-tech { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
-
-/* Fix for Firefox 9 fullscreen (only if it is enabled). Not needed when checking fullScreenEnabled. */
-.video-js:-moz-full-screen { position: absolute; }
-
-/* Fullscreen Styles */
-body.vjs-full-window {
- padding: 0; margin: 0;
- height: 100%; overflow-y: auto; /* Fix for IE6 full-window. http://www.cssplay.co.uk/layouts/fixed.html */
-}
-.video-js.vjs-fullscreen {
- position: fixed; overflow: hidden; z-index: 1000; left: 0; top: 0; bottom: 0; right: 0; width: 100% !important; height: 100% !important;
- _position: absolute; /* IE6 Full-window (underscore hack) */
-}
-.video-js:-webkit-full-screen {
- width: 100% !important; height: 100% !important;
-}
-
-/* Poster Styles */
-.vjs-poster {
- margin: 0 auto; padding: 0; cursor: pointer;
-
- /* Scale with the size of the player div. Works when poster is vertically shorter, but stretches when it's less wide. */
- position: relative; width: 100%; max-height: 100%;
-}
-
-/* Subtiles Styles */
-.video-js .vjs-subtitles { color: #fff; font-size: 20px; text-align: center; position: absolute; bottom: 40px; left: 0; right: 0; }
-
-/* Fading sytles, used to fade control bar. */
-.vjs-fade-in {
- visibility: visible !important; /* Needed to make sure things hide in older browsers too. */
- opacity: 1 !important;
-
- -webkit-transition: visibility 0s linear 0s, opacity 0.3s linear;
- -moz-transition: visibility 0s linear 0s, opacity 0.3s linear;
- -ms-transition: visibility 0s linear 0s, opacity 0.3s linear;
- -o-transition: visibility 0s linear 0s, opacity 0.3s linear;
- transition: visibility 0s linear 0s, opacity 0.3s linear;
-}
-.vjs-fade-out {
- visibility: hidden !important;
- opacity: 0 !important;
-
- -webkit-transition: visibility 0s linear 1.5s,opacity 1.5s linear;
- -moz-transition: visibility 0s linear 1.5s,opacity 1.5s linear;
- -ms-transition: visibility 0s linear 1.5s,opacity 1.5s linear;
- -o-transition: visibility 0s linear 1.5s,opacity 1.5s linear;
- transition: visibility 0s linear 1.5s,opacity 1.5s linear;
-}
-
-/* DEFAULT SKIN (override in another file to create new skins)
-================================================================================
-Instead of editing this file, I recommend creating your own skin CSS file to be included after this file,
-so you can upgrade to newer versions easier. You can remove all these styles by removing the 'vjs-default-skin' class from the tag. */
-
-/* The default control bar. Created by bar.js */
-.vjs-default-skin .vjs-controls {
- position: absolute;
- bottom: 0; /* Distance from the bottom of the box/video. Keep 0. Use height to add more bottom margin. */
- left: 0; right: 0; /* 100% width of div */
- margin: 0; padding: 0; /* Controls are absolutely position, so no padding necessary */
- height: 2.6em; /* Including any margin you want above or below control items */
- color: #fff; border-top: 1px solid #404040;
-
- /* CSS Gradient */
- /* Can use the Ultimate CSS Gradient Generator: http://www.colorzilla.com/gradient-editor/ */
- background: #242424; /* Old browsers */
- background: -moz-linear-gradient(top, #242424 50%, #1f1f1f 50%, #171717 100%); /* FF3.6+ */
- background: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(50%,#242424), color-stop(50%,#1f1f1f), color-stop(100%,#171717)); /* Chrome,Safari4+ */
- background: -webkit-linear-gradient(top, #242424 50%,#1f1f1f 50%,#171717 100%); /* Chrome10+,Safari5.1+ */
- background: -o-linear-gradient(top, #242424 50%,#1f1f1f 50%,#171717 100%); /* Opera11.10+ */
- background: -ms-linear-gradient(top, #242424 50%,#1f1f1f 50%,#171717 100%); /* IE10+ */
- /* Filter was causing a lot of weird issues in IE. Elements would stop showing up, or other styles would break. */
- /*filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#242424', endColorstr='#171717',GradientType=0 );*/ /* IE6-9 */
- background: linear-gradient(top, #242424 50%,#1f1f1f 50%,#171717 100%); /* W3C */
-
- /* Start hidden and with 0 opacity. Opacity is used to fade in modern browsers. */
- /* Can't use display block to hide initially because widths of slider handles aren't calculated and avaialbe for positioning correctly. */
- visibility: hidden;
- opacity: 0;
-}
-
-/* General styles for individual controls. */
-.vjs-default-skin .vjs-control {
- position: relative; float: left;
- text-align: center; margin: 0; padding: 0;
- height: 2.6em; width: 2.6em;
-}
-
-.vjs-default-skin .vjs-control:focus {
- outline: 0;
-}
-
-/* Hide control text visually, but have it available for screenreaders: h5bp.com/v */
-.vjs-default-skin .vjs-control-text { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }
-
-
-/* Play/Pause
--------------------------------------------------------------------------------- */
-.vjs-default-skin .vjs-play-control { width: 5em; cursor: pointer !important; }
-/* Play Icon */
-.vjs-default-skin.vjs-paused .vjs-play-control div { width: 15px; height: 17px; background: url('video-js.png'); margin: 0.5em auto 0; }
-.vjs-default-skin.vjs-playing .vjs-play-control div { width: 15px; height: 17px; background: url('video-js.png') -25px 0; margin: 0.5em auto 0; }
-
-/* Rewind
--------------------------------------------------------------------------------- */
-.vjs-default-skin .vjs-rewind-control { width: 5em; cursor: pointer !important; }
-.vjs-default-skin .vjs-rewind-control div { width: 19px; height: 16px; background: url('video-js.png'); margin: 0.5em auto 0; }
-
-/* Volume/Mute
--------------------------------------------------------------------------------- */
-.vjs-default-skin .vjs-mute-control { width: 3.8em; cursor: pointer !important; float: right; }
-.vjs-default-skin .vjs-mute-control div { width: 22px; height: 16px; background: url('video-js.png') -75px -25px; margin: 0.5em auto 0; }
-.vjs-default-skin .vjs-mute-control.vjs-vol-0 div { background: url('video-js.png') 0 -25px; }
-.vjs-default-skin .vjs-mute-control.vjs-vol-1 div { background: url('video-js.png') -25px -25px; }
-.vjs-default-skin .vjs-mute-control.vjs-vol-2 div { background: url('video-js.png') -50px -25px; }
-
-
-.vjs-default-skin .vjs-volume-control { width: 5em; float: right; }
-.vjs-default-skin .vjs-volume-bar {
- position: relative; width: 5em; height: 0.6em; margin: 1em auto 0; cursor: pointer !important;
-
- -moz-border-radius: 0.3em; -webkit-border-radius: 0.3em; border-radius: 0.3em;
-
- background: #666;
- background: -moz-linear-gradient(top, #333, #666);
- background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#333), to(#666));
- background: -webkit-linear-gradient(top, #333, #666);
- background: -o-linear-gradient(top, #333, #666);
- background: -ms-linear-gradient(top, #333, #666);
- background: linear-gradient(top, #333, #666);
-}
-.vjs-default-skin .vjs-volume-level {
- position: absolute; top: 0; left: 0; height: 0.6em;
-
- -moz-border-radius: 0.3em; -webkit-border-radius: 0.3em; border-radius: 0.3em;
-
- background: #fff;
- background: -moz-linear-gradient(top, #fff, #ccc);
- background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#ccc));
- background: -webkit-linear-gradient(top, #fff, #ccc);
- background: -o-linear-gradient(top, #fff, #ccc);
- background: -ms-linear-gradient(top, #fff, #ccc);
- background: linear-gradient(top, #fff, #ccc);
-}
-.vjs-default-skin .vjs-volume-handle {
- position: absolute; top: -0.2em; width: 0.8em; height: 0.8em; background: #ccc; left: 0;
- border: 1px solid #fff;
- -moz-border-radius: 0.6em; -webkit-border-radius: 0.6em; border-radius: 0.6em;
-}
-
-/* Progress
--------------------------------------------------------------------------------- */
-.vjs-default-skin div.vjs-progress-control {
- position: absolute;
- left: 4.8em; right: 4.8em; /* Leave room for time displays. */
- height: 1.0em; width: auto;
- top: -1.3em; /* Set above the rest of the controls. And leave room for 2px of borders (progress bottom and controls top). */
- border-bottom: 1px solid #1F1F1F;
- border-top: 1px solid #222;
-
- /* CSS Gradient */
- background: #333;
- background: -moz-linear-gradient(top, #222, #333);
- background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#222), to(#333));
- background: -webkit-linear-gradient(top, #222, #333);
- background: -o-linear-gradient(top, #333, #222);
- background: -ms-linear-gradient(top, #333, #222);
- background: linear-gradient(top, #333, #222);
-
-
- /* 1px top shadow */
-/* -webkit-box-shadow: 0px -1px 0px 0px rgba(0, 0, 0, 0.15); -moz-box-shadow: 0px -1px 0px 0px rgba(0, 0, 0, 0.15); box-shadow: 0px -1px 0px 0px rgba(0, 0, 0, 0.15);*/
-}
-
-/* Box containing play and load progresses. Also acts as seek scrubber. */
-.vjs-default-skin .vjs-progress-holder {
- position: relative; cursor: pointer !important; /*overflow: hidden;*/
- padding: 0; margin: 0; /* Placement within the progress control item */
- height: 1.0em;
- -moz-border-radius: 0.6em; -webkit-border-radius: 0.6em; border-radius: 0.6em;
-
- /* CSS Gradient */
- background: #111;
- background: -moz-linear-gradient(top, #111, #262626);
- background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#111), to(#262626));
- background: -webkit-linear-gradient(top, #111, #262626);
- background: -o-linear-gradient(top, #111, #262626);
- background: -ms-linear-gradient(top, #111, #262626);
- background: linear-gradient(top, #111, #262626);
-}
-.vjs-default-skin .vjs-progress-holder .vjs-play-progress,
-.vjs-default-skin .vjs-progress-holder .vjs-load-progress { /* Progress Bars */
- position: absolute; display: block; height: 1.0em; margin: 0; padding: 0;
- left: 0; top: 0; /*Needed for IE6*/
- -moz-border-radius: 0.6em; -webkit-border-radius: 0.6em; border-radius: 0.6em;
-
- /*width: 0;*/
-}
-
-.vjs-default-skin .vjs-play-progress {
- /* CSS Gradient. */
- background: #fff; /* Old browsers */
- background: -moz-linear-gradient(top, #fff 0%, #d6d6d6 50%, #fff 100%);
- background: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%,#fff), color-stop(50%,#d6d6d6), color-stop(100%,#fff));
- background: -webkit-linear-gradient(top, #fff 0%,#d6d6d6 50%,#fff 100%);
- background: -o-linear-gradient(top, #fff 0%,#d6d6d6 50%,#fff 100%);
- background: -ms-linear-gradient(top, #fff 0%,#d6d6d6 50%,#fff 100%);
- background: linear-gradient(top, #fff 0%,#d6d6d6 50%,#fff 100%);
-
- background: #efefef;
- background: -moz-linear-gradient(top, #efefef 0%, #f5f5f5 50%, #dbdbdb 50%, #f1f1f1 100%);
- background: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%,#efefef), color-stop(50%,#f5f5f5), color-stop(50%,#dbdbdb), color-stop(100%,#f1f1f1));
- background: -webkit-linear-gradient(top, #efefef 0%,#f5f5f5 50%,#dbdbdb 50%,#f1f1f1 100%);
- background: -o-linear-gradient(top, #efefef 0%,#f5f5f5 50%,#dbdbdb 50%,#f1f1f1 100%);
- background: -ms-linear-gradient(top, #efefef 0%,#f5f5f5 50%,#dbdbdb 50%,#f1f1f1 100%);
- filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#efefef', endColorstr='#f1f1f1',GradientType=0 );
- background: linear-gradient(top, #efefef 0%,#f5f5f5 50%,#dbdbdb 50%,#f1f1f1 100%);
-}
-.vjs-default-skin .vjs-load-progress {
- opacity: 0.8;
-
- /* CSS Gradient */
- background: #666;
- background: -moz-linear-gradient(top, #666, #333);
- background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#666), to(#333));
- background: -webkit-linear-gradient(top, #666, #333);
- background: -o-linear-gradient(top, #666, #333);
- background: -ms-linear-gradient(top, #666, #333);
- background: linear-gradient(top, #666, #333);
-}
-
-.vjs-default-skin div.vjs-seek-handle {
- position: absolute;
- width: 16px; height: 16px; /* Match img pixles */
- margin-top: -0.3em;
- left: 0; top: 0; /*Needed for IE6*/
-
- background: url('video-js.png') 0 -50px;
- /* CSS Curved Corners. Needed to make shadows curved. */
- -moz-border-radius: 0.8em; -webkit-border-radius: 0.8em; border-radius: 0.8em;
- /* CSS Shadows */
- -webkit-box-shadow: 0 2px 4px 0 #000; -moz-box-shadow: 0 2px 4px 0 #000; box-shadow: 0 2px 4px 0 #000;
-}
-/* Time Display
--------------------------------------------------------------------------------- */
-.vjs-default-skin .vjs-time-controls {
- position: absolute;
- right: 0;
- height: 1.0em; width: 4.8em;
- top: -1.3em;
- border-bottom: 1px solid #1F1F1F;
- border-top: 1px solid #222;
- background-color: #333;
-
- font-size: 1em; line-height: 1.0em; font-weight: normal; font-family: Helvetica, Arial, sans-serif;
-
- background: #333;
- background: -moz-linear-gradient(top, #222, #333);
- background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#222), to(#333));
- background: -webkit-linear-gradient(top, #222, #333);
- background: -o-linear-gradient(top, #333, #222);
- background: -ms-linear-gradient(top, #333, #222);
- background: linear-gradient(top, #333, #222);
-
- /* 1px top shadow */
-/* -webkit-box-shadow: 0px -1px 0px 0px rgba(0, 0, 0, 0.15); -moz-box-shadow: 0px -1px 0px 0px rgba(0, 0, 0, 0.15); box-shadow: 0px -1px 0px 0px rgba(0, 0, 0, 0.15);*/
-}
-
-.vjs-default-skin .vjs-current-time { left: 0; }
-
-.vjs-default-skin .vjs-duration { right: 0; display: none; }
-.vjs-default-skin .vjs-remaining-time { right: 0; }
-
-.vjs-time-divider { display:none; }
-
-.vjs-default-skin .vjs-time-control { font-size: 1em; line-height: 1; font-weight: normal; font-family: Helvetica, Arial, sans-serif; }
-.vjs-default-skin .vjs-time-control span { line-height: 25px; /* Centering vertically */ }
-
-/* Fullscreen
--------------------------------------------------------------------------------- */
-.vjs-secondary-controls { float: right; }
-
-.vjs-default-skin .vjs-fullscreen-control { width: 3.8em; cursor: pointer !important; float: right; }
-.vjs-default-skin .vjs-fullscreen-control div { width: 16px; height: 16px; background: url('video-js.png') -50px 0; margin: 0.5em auto 0; }
-
-.vjs-default-skin.vjs-fullscreen .vjs-fullscreen-control div { background: url('video-js.png') -75px 0; }
-
-
-/* Big Play Button (at start)
----------------------------------------------------------*/
-.vjs-default-skin .vjs-big-play-button {
- display: block; /* Start hidden */ z-index: 2;
- position: absolute; top: 50%; left: 50%; width: 8.0em; height: 8.0em; margin: -43px 0 0 -43px; text-align: center; vertical-align: center; cursor: pointer !important;
- border: 0.3em solid #fff; opacity: 0.95;
- -webkit-border-radius: 25px; -moz-border-radius: 25px; border-radius: 25px;
-
- background: #454545;
- background: -moz-linear-gradient(top, #454545 0%, #232323 50%, #161616 50%, #3f3f3f 100%);
- background: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%,#454545), color-stop(50%,#232323), color-stop(50%,#161616), color-stop(100%,#3f3f3f));
- background: -webkit-linear-gradient(top, #454545 0%,#232323 50%,#161616 50%,#3f3f3f 100%);
- background: -o-linear-gradient(top, #454545 0%,#232323 50%,#161616 50%,#3f3f3f 100%);
- background: -ms-linear-gradient(top, #454545 0%,#232323 50%,#161616 50%,#3f3f3f 100%);
- filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#454545', endColorstr='#3f3f3f',GradientType=0 );
- background: linear-gradient(top, #454545 0%,#232323 50%,#161616 50%,#3f3f3f 100%);
-
- /* CSS Shadows */
- -webkit-box-shadow: 4px 4px 8px #000; -moz-box-shadow: 4px 4px 8px #000; box-shadow: 4px 4px 8px #000;
-}
-
-.vjs-default-skin div.vjs-big-play-button:hover {
- -webkit-box-shadow: 0 0 80px #fff; -moz-box-shadow: 0 0 80px #fff; box-shadow: 0 0 80px #fff;
-}
-
-.vjs-default-skin div.vjs-big-play-button span {
- position: absolute; top: 50%; left: 50%;
- display: block; width: 35px; height: 42px;
- margin: -20px 0 0 -15px; /* Using negative margin to center image. */
- background: url('video-js.png') -100px 0;
-}
-
-/* Loading Spinner
----------------------------------------------------------*/
-/* CSS Spinners by Kilian Valkhof - http://kilianvalkhof.com/2010/css-xhtml/css3-loading-spinners-without-images/ */
-.vjs-loading-spinner {
- display: none;
- position: absolute; top: 50%; left: 50%; width: 55px; height: 55px;
- margin: -28px 0 0 -28px;
- -webkit-animation-name: rotatethis;
- -webkit-animation-duration:1s;
- -webkit-animation-iteration-count:infinite;
- -webkit-animation-timing-function:linear;
- -moz-animation-name: rotatethis;
- -moz-animation-duration:1s;
- -moz-animation-iteration-count:infinite;
- -moz-animation-timing-function:linear;
-}
-
-@-webkit-keyframes rotatethis {
- 0% {-webkit-transform:scale(0.6) rotate(0deg); }
- 12.5% {-webkit-transform:scale(0.6) rotate(0deg); }
- 12.51% {-webkit-transform:scale(0.6) rotate(45deg); }
- 25% {-webkit-transform:scale(0.6) rotate(45deg); }
- 25.01% {-webkit-transform:scale(0.6) rotate(90deg);}
- 37.5% {-webkit-transform:scale(0.6) rotate(90deg);}
- 37.51% {-webkit-transform:scale(0.6) rotate(135deg);}
- 50% {-webkit-transform:scale(0.6) rotate(135deg);}
- 50.01% {-webkit-transform:scale(0.6) rotate(180deg);}
- 62.5% {-webkit-transform:scale(0.6) rotate(180deg);}
- 62.51% {-webkit-transform:scale(0.6) rotate(225deg);}
- 75% {-webkit-transform:scale(0.6) rotate(225deg);}
- 75.01% {-webkit-transform:scale(0.6) rotate(270deg);}
- 87.5% {-webkit-transform:scale(0.6) rotate(270deg);}
- 87.51% {-webkit-transform:scale(0.6) rotate(315deg);}
- 100% {-webkit-transform:scale(0.6) rotate(315deg);}
-}
-
-@-moz-keyframes rotatethis {
- 0% {-moz-transform:scale(0.6) rotate(0deg);}
- 12.5% {-moz-transform:scale(0.6) rotate(0deg);}
- 12.51% {-moz-transform:scale(0.6) rotate(45deg);}
- 25% {-moz-transform:scale(0.6) rotate(45deg);}
- 25.01% {-moz-transform:scale(0.6) rotate(90deg);}
- 37.5% {-moz-transform:scale(0.6) rotate(90deg);}
- 37.51% {-moz-transform:scale(0.6) rotate(135deg);}
- 50% {-moz-transform:scale(0.6) rotate(135deg);}
- 50.01% {-moz-transform:scale(0.6) rotate(180deg);}
- 62.5% {-moz-transform:scale(0.6) rotate(180deg);}
- 62.51% {-moz-transform:scale(0.6) rotate(225deg);}
- 75% {-moz-transform:scale(0.6) rotate(225deg);}
- 75.01% {-moz-transform:scale(0.6) rotate(270deg);}
- 87.5% {-moz-transform:scale(0.6) rotate(270deg);}
- 87.51% {-moz-transform:scale(0.6) rotate(315deg);}
- 100% {-moz-transform:scale(0.6) rotate(315deg);}
-}
-/* Each circle */
-div.vjs-loading-spinner .ball1 { opacity: 0.12; position:absolute; left: 20px; top: 0px; width: 13px; height: 13px; background: #fff;
- border-radius: 13px; -webkit-border-radius: 13px; -moz-border-radius: 13px; border: 1px solid #ccc; }
-
-div.vjs-loading-spinner .ball2 { opacity: 0.25; position:absolute; left: 34px; top: 6px; width: 13px; height: 13px; background: #fff;
- border-radius: 13px; -webkit-border-radius: 13px; -moz-border-radius: 13px; border: 1px solid #ccc; }
-
-div.vjs-loading-spinner .ball3 { opacity: 0.37; position:absolute; left: 40px; top: 20px; width: 13px; height: 13px; background: #fff;
- border-radius: 13px; -webkit-border-radius: 13px; -moz-border-radius: 13px; border: 1px solid #ccc; }
-
-div.vjs-loading-spinner .ball4 { opacity: 0.50; position:absolute; left: 34px; top: 34px; width: 13px; height: 13px; background: #fff;
- border-radius: 10px; -webkit-border-radius: 10px; -moz-border-radius: 15px; border: 1px solid #ccc; }
-
-div.vjs-loading-spinner .ball5 { opacity: 0.62; position:absolute; left: 20px; top: 40px; width: 13px; height: 13px; background: #fff;
- border-radius: 13px; -webkit-border-radius: 13px; -moz-border-radius: 13px; border: 1px solid #ccc; }
-
-div.vjs-loading-spinner .ball6 { opacity: 0.75; position:absolute; left: 6px; top: 34px; width: 13px; height: 13px; background: #fff;
- border-radius: 13px; -webkit-border-radius: 13px; -moz-border-radius: 13px; border: 1px solid #ccc; }
-
-div.vjs-loading-spinner .ball7 { opacity: 0.87; position:absolute; left: 0px; top: 20px; width: 13px; height: 13px; background: #fff;
- border-radius: 13px; -webkit-border-radius: 13px; -moz-border-radius: 13px; border: 1px solid #ccc; }
-
-div.vjs-loading-spinner .ball8 { opacity: 1.00; position:absolute; left: 6px; top: 6px; width: 13px; height: 13px; background: #fff;
- border-radius: 13px; -webkit-border-radius: 13px; -moz-border-radius: 13px; border: 1px solid #ccc; }
diff --git a/extlib/video-js/video-js.min.css b/extlib/video-js/video-js.min.css
index 4394cdd7..06c0e6b4 100644
--- a/extlib/video-js/video-js.min.css
+++ b/extlib/video-js/video-js.min.css
@@ -1 +1 @@
-.video-js{background-color:#000;position:relative;padding:0;font-size:10px;vertical-align:middle}.video-js .vjs-tech{position:absolute;top:0;left:0;width:100%;height:100%}.video-js:-moz-full-screen{position:absolute}body.vjs-full-window{padding:0;margin:0;height:100%;overflow-y:auto}.video-js.vjs-fullscreen{position:fixed;overflow:hidden;z-index:1000;left:0;top:0;bottom:0;right:0;width:100%!important;height:100%!important;_position:absolute}.video-js:-webkit-full-screen{width:100%!important;height:100%!important}.vjs-poster{margin:0 auto;padding:0;cursor:pointer;position:relative;width:100%;max-height:100%}.video-js .vjs-subtitles{color:#fff;font-size:20px;text-align:center;position:absolute;bottom:40px;left:0;right:0}.vjs-fade-in{visibility:visible!important;opacity:1!important;-webkit-transition:visibility 0s linear 0s,opacity .3s linear;-moz-transition:visibility 0s linear 0s,opacity .3s linear;-ms-transition:visibility 0s linear 0s,opacity .3s linear;-o-transition:visibility 0s linear 0s,opacity .3s linear;transition:visibility 0s linear 0s,opacity .3s linear}.vjs-fade-out{visibility:hidden!important;opacity:0!important;-webkit-transition:visibility 0s linear 1.5s,opacity 1.5s linear;-moz-transition:visibility 0s linear 1.5s,opacity 1.5s linear;-ms-transition:visibility 0s linear 1.5s,opacity 1.5s linear;-o-transition:visibility 0s linear 1.5s,opacity 1.5s linear;transition:visibility 0s linear 1.5s,opacity 1.5s linear}.vjs-default-skin .vjs-controls{position:absolute;bottom:0;left:0;right:0;margin:0;padding:0;height:2.6em;color:#fff;border-top:1px solid #404040;background:#242424;background:-moz-linear-gradient(top,#242424 50%,#1f1f1f 50%,#171717 100%);background:-webkit-gradient(linear,0% 0,0% 100%,color-stop(50%,#242424),color-stop(50%,#1f1f1f),color-stop(100%,#171717));background:-webkit-linear-gradient(top,#242424 50%,#1f1f1f 50%,#171717 100%);background:-o-linear-gradient(top,#242424 50%,#1f1f1f 50%,#171717 100%);background:-ms-linear-gradient(top,#242424 50%,#1f1f1f 50%,#171717 100%);background:linear-gradient(top,#242424 50%,#1f1f1f 50%,#171717 100%);visibility:hidden;opacity:0}.vjs-default-skin .vjs-control{position:relative;float:left;text-align:center;margin:0;padding:0;height:2.6em;width:2.6em}.vjs-default-skin .vjs-control:focus{outline:0}.vjs-default-skin .vjs-control-text{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.vjs-default-skin .vjs-play-control{width:5em;cursor:pointer!important}.vjs-default-skin.vjs-paused .vjs-play-control div{width:15px;height:17px;background:url('video-js.png');margin:.5em auto 0}.vjs-default-skin.vjs-playing .vjs-play-control div{width:15px;height:17px;background:url('video-js.png') -25px 0;margin:.5em auto 0}.vjs-default-skin .vjs-rewind-control{width:5em;cursor:pointer!important}.vjs-default-skin .vjs-rewind-control div{width:19px;height:16px;background:url('video-js.png');margin:.5em auto 0}.vjs-default-skin .vjs-mute-control{width:3.8em;cursor:pointer!important;float:right}.vjs-default-skin .vjs-mute-control div{width:22px;height:16px;background:url('video-js.png') -75px -25px;margin:.5em auto 0}.vjs-default-skin .vjs-mute-control.vjs-vol-0 div{background:url('video-js.png') 0 -25px}.vjs-default-skin .vjs-mute-control.vjs-vol-1 div{background:url('video-js.png') -25px -25px}.vjs-default-skin .vjs-mute-control.vjs-vol-2 div{background:url('video-js.png') -50px -25px}.vjs-default-skin .vjs-volume-control{width:5em;float:right}.vjs-default-skin .vjs-volume-bar{position:relative;width:5em;height:.6em;margin:1em auto 0;cursor:pointer!important;-moz-border-radius:.3em;-webkit-border-radius:.3em;border-radius:.3em;background:#666;background:-moz-linear-gradient(top,#333,#666);background:-webkit-gradient(linear,0% 0,0% 100%,from(#333),to(#666));background:-webkit-linear-gradient(top,#333,#666);background:-o-linear-gradient(top,#333,#666);background:-ms-linear-gradient(top,#333,#666);background:linear-gradient(top,#333,#666)}.vjs-default-skin .vjs-volume-level{position:absolute;top:0;left:0;height:.6em;-moz-border-radius:.3em;-webkit-border-radius:.3em;border-radius:.3em;background:#fff;background:-moz-linear-gradient(top,#fff,#ccc);background:-webkit-gradient(linear,0% 0,0% 100%,from(#fff),to(#ccc));background:-webkit-linear-gradient(top,#fff,#ccc);background:-o-linear-gradient(top,#fff,#ccc);background:-ms-linear-gradient(top,#fff,#ccc);background:linear-gradient(top,#fff,#ccc)}.vjs-default-skin .vjs-volume-handle{position:absolute;top:-0.2em;width:.8em;height:.8em;background:#ccc;left:0;border:1px solid #fff;-moz-border-radius:.6em;-webkit-border-radius:.6em;border-radius:.6em}.vjs-default-skin div.vjs-progress-control{position:absolute;left:4.8em;right:4.8em;height:1.0em;width:auto;top:-1.3em;border-bottom:1px solid #1f1f1f;border-top:1px solid #222;background:#333;background:-moz-linear-gradient(top,#222,#333);background:-webkit-gradient(linear,0% 0,0% 100%,from(#222),to(#333));background:-webkit-linear-gradient(top,#222,#333);background:-o-linear-gradient(top,#333,#222);background:-ms-linear-gradient(top,#333,#222);background:linear-gradient(top,#333,#222)}.vjs-default-skin .vjs-progress-holder{position:relative;cursor:pointer!important;padding:0;margin:0;height:1.0em;-moz-border-radius:.6em;-webkit-border-radius:.6em;border-radius:.6em;background:#111;background:-moz-linear-gradient(top,#111,#262626);background:-webkit-gradient(linear,0% 0,0% 100%,from(#111),to(#262626));background:-webkit-linear-gradient(top,#111,#262626);background:-o-linear-gradient(top,#111,#262626);background:-ms-linear-gradient(top,#111,#262626);background:linear-gradient(top,#111,#262626)}.vjs-default-skin .vjs-progress-holder .vjs-play-progress,.vjs-default-skin .vjs-progress-holder .vjs-load-progress{position:absolute;display:block;height:1.0em;margin:0;padding:0;left:0;top:0;-moz-border-radius:.6em;-webkit-border-radius:.6em;border-radius:.6em}.vjs-default-skin .vjs-play-progress{background:#fff;background:-moz-linear-gradient(top,#fff 0,#d6d6d6 50%,#fff 100%);background:-webkit-gradient(linear,0% 0,0% 100%,color-stop(0%,#fff),color-stop(50%,#d6d6d6),color-stop(100%,#fff));background:-webkit-linear-gradient(top,#fff 0,#d6d6d6 50%,#fff 100%);background:-o-linear-gradient(top,#fff 0,#d6d6d6 50%,#fff 100%);background:-ms-linear-gradient(top,#fff 0,#d6d6d6 50%,#fff 100%);background:linear-gradient(top,#fff 0,#d6d6d6 50%,#fff 100%);background:#efefef;background:-moz-linear-gradient(top,#efefef 0,#f5f5f5 50%,#dbdbdb 50%,#f1f1f1 100%);background:-webkit-gradient(linear,0% 0,0% 100%,color-stop(0%,#efefef),color-stop(50%,#f5f5f5),color-stop(50%,#dbdbdb),color-stop(100%,#f1f1f1));background:-webkit-linear-gradient(top,#efefef 0,#f5f5f5 50%,#dbdbdb 50%,#f1f1f1 100%);background:-o-linear-gradient(top,#efefef 0,#f5f5f5 50%,#dbdbdb 50%,#f1f1f1 100%);background:-ms-linear-gradient(top,#efefef 0,#f5f5f5 50%,#dbdbdb 50%,#f1f1f1 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#efefef',endColorstr='#f1f1f1',GradientType=0);background:linear-gradient(top,#efefef 0,#f5f5f5 50%,#dbdbdb 50%,#f1f1f1 100%)}.vjs-default-skin .vjs-load-progress{opacity:.8;background:#666;background:-moz-linear-gradient(top,#666,#333);background:-webkit-gradient(linear,0% 0,0% 100%,from(#666),to(#333));background:-webkit-linear-gradient(top,#666,#333);background:-o-linear-gradient(top,#666,#333);background:-ms-linear-gradient(top,#666,#333);background:linear-gradient(top,#666,#333)}.vjs-default-skin div.vjs-seek-handle{position:absolute;width:16px;height:16px;margin-top:-0.3em;left:0;top:0;background:url('video-js.png') 0 -50px;-moz-border-radius:.8em;-webkit-border-radius:.8em;border-radius:.8em;-webkit-box-shadow:0 2px 4px 0 #000;-moz-box-shadow:0 2px 4px 0 #000;box-shadow:0 2px 4px 0 #000}.vjs-default-skin .vjs-time-controls{position:absolute;right:0;height:1.0em;width:4.8em;top:-1.3em;border-bottom:1px solid #1f1f1f;border-top:1px solid #222;background-color:#333;font-size:1em;line-height:1.0em;font-weight:normal;font-family:Helvetica,Arial,sans-serif;background:#333;background:-moz-linear-gradient(top,#222,#333);background:-webkit-gradient(linear,0% 0,0% 100%,from(#222),to(#333));background:-webkit-linear-gradient(top,#222,#333);background:-o-linear-gradient(top,#333,#222);background:-ms-linear-gradient(top,#333,#222);background:linear-gradient(top,#333,#222)}.vjs-default-skin .vjs-current-time{left:0}.vjs-default-skin .vjs-duration{right:0;display:none}.vjs-default-skin .vjs-remaining-time{right:0}.vjs-time-divider{display:none}.vjs-default-skin .vjs-time-control{font-size:1em;line-height:1;font-weight:normal;font-family:Helvetica,Arial,sans-serif}.vjs-default-skin .vjs-time-control span{line-height:25px}.vjs-secondary-controls{float:right}.vjs-default-skin .vjs-fullscreen-control{width:3.8em;cursor:pointer!important;float:right}.vjs-default-skin .vjs-fullscreen-control div{width:16px;height:16px;background:url('video-js.png') -50px 0;margin:.5em auto 0}.vjs-default-skin.vjs-fullscreen .vjs-fullscreen-control div{background:url('video-js.png') -75px 0}.vjs-default-skin .vjs-big-play-button{display:block;z-index:2;position:absolute;top:50%;left:50%;width:8.0em;height:8.0em;margin:-43px 0 0 -43px;text-align:center;vertical-align:center;cursor:pointer!important;border:.3em solid #fff;opacity:.95;-webkit-border-radius:25px;-moz-border-radius:25px;border-radius:25px;background:#454545;background:-moz-linear-gradient(top,#454545 0,#232323 50%,#161616 50%,#3f3f3f 100%);background:-webkit-gradient(linear,0% 0,0% 100%,color-stop(0%,#454545),color-stop(50%,#232323),color-stop(50%,#161616),color-stop(100%,#3f3f3f));background:-webkit-linear-gradient(top,#454545 0,#232323 50%,#161616 50%,#3f3f3f 100%);background:-o-linear-gradient(top,#454545 0,#232323 50%,#161616 50%,#3f3f3f 100%);background:-ms-linear-gradient(top,#454545 0,#232323 50%,#161616 50%,#3f3f3f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#454545',endColorstr='#3f3f3f',GradientType=0);background:linear-gradient(top,#454545 0,#232323 50%,#161616 50%,#3f3f3f 100%);-webkit-box-shadow:4px 4px 8px #000;-moz-box-shadow:4px 4px 8px #000;box-shadow:4px 4px 8px #000}.vjs-default-skin div.vjs-big-play-button:hover{-webkit-box-shadow:0 0 80px #fff;-moz-box-shadow:0 0 80px #fff;box-shadow:0 0 80px #fff}.vjs-default-skin div.vjs-big-play-button span{position:absolute;top:50%;left:50%;display:block;width:35px;height:42px;margin:-20px 0 0 -15px;background:url('video-js.png') -100px 0}.vjs-loading-spinner{display:none;position:absolute;top:50%;left:50%;width:55px;height:55px;margin:-28px 0 0 -28px;-webkit-animation-name:rotatethis;-webkit-animation-duration:1s;-webkit-animation-iteration-count:infinite;-webkit-animation-timing-function:linear;-moz-animation-name:rotatethis;-moz-animation-duration:1s;-moz-animation-iteration-count:infinite;-moz-animation-timing-function:linear}@-webkit-keyframes rotatethis{0%{-webkit-transform:scale(0.6) rotate(0deg)}12.5%{-webkit-transform:scale(0.6) rotate(0deg)}12.51%{-webkit-transform:scale(0.6) rotate(45deg)}25%{-webkit-transform:scale(0.6) rotate(45deg)}25.01%{-webkit-transform:scale(0.6) rotate(90deg)}37.5%{-webkit-transform:scale(0.6) rotate(90deg)}37.51%{-webkit-transform:scale(0.6) rotate(135deg)}50%{-webkit-transform:scale(0.6) rotate(135deg)}50.01%{-webkit-transform:scale(0.6) rotate(180deg)}62.5%{-webkit-transform:scale(0.6) rotate(180deg)}62.51%{-webkit-transform:scale(0.6) rotate(225deg)}75%{-webkit-transform:scale(0.6) rotate(225deg)}75.01%{-webkit-transform:scale(0.6) rotate(270deg)}87.5%{-webkit-transform:scale(0.6) rotate(270deg)}87.51%{-webkit-transform:scale(0.6) rotate(315deg)}100%{-webkit-transform:scale(0.6) rotate(315deg)}}@-moz-keyframes rotatethis{0%{-moz-transform:scale(0.6) rotate(0deg)}12.5%{-moz-transform:scale(0.6) rotate(0deg)}12.51%{-moz-transform:scale(0.6) rotate(45deg)}25%{-moz-transform:scale(0.6) rotate(45deg)}25.01%{-moz-transform:scale(0.6) rotate(90deg)}37.5%{-moz-transform:scale(0.6) rotate(90deg)}37.51%{-moz-transform:scale(0.6) rotate(135deg)}50%{-moz-transform:scale(0.6) rotate(135deg)}50.01%{-moz-transform:scale(0.6) rotate(180deg)}62.5%{-moz-transform:scale(0.6) rotate(180deg)}62.51%{-moz-transform:scale(0.6) rotate(225deg)}75%{-moz-transform:scale(0.6) rotate(225deg)}75.01%{-moz-transform:scale(0.6) rotate(270deg)}87.5%{-moz-transform:scale(0.6) rotate(270deg)}87.51%{-moz-transform:scale(0.6) rotate(315deg)}100%{-moz-transform:scale(0.6) rotate(315deg)}}div.vjs-loading-spinner .ball1{opacity:.12;position:absolute;left:20px;top:0;width:13px;height:13px;background:#fff;border-radius:13px;-webkit-border-radius:13px;-moz-border-radius:13px;border:1px solid #ccc}div.vjs-loading-spinner .ball2{opacity:.25;position:absolute;left:34px;top:6px;width:13px;height:13px;background:#fff;border-radius:13px;-webkit-border-radius:13px;-moz-border-radius:13px;border:1px solid #ccc}div.vjs-loading-spinner .ball3{opacity:.37;position:absolute;left:40px;top:20px;width:13px;height:13px;background:#fff;border-radius:13px;-webkit-border-radius:13px;-moz-border-radius:13px;border:1px solid #ccc}div.vjs-loading-spinner .ball4{opacity:.50;position:absolute;left:34px;top:34px;width:13px;height:13px;background:#fff;border-radius:10px;-webkit-border-radius:10px;-moz-border-radius:15px;border:1px solid #ccc}div.vjs-loading-spinner .ball5{opacity:.62;position:absolute;left:20px;top:40px;width:13px;height:13px;background:#fff;border-radius:13px;-webkit-border-radius:13px;-moz-border-radius:13px;border:1px solid #ccc}div.vjs-loading-spinner .ball6{opacity:.75;position:absolute;left:6px;top:34px;width:13px;height:13px;background:#fff;border-radius:13px;-webkit-border-radius:13px;-moz-border-radius:13px;border:1px solid #ccc}div.vjs-loading-spinner .ball7{opacity:.87;position:absolute;left:0;top:20px;width:13px;height:13px;background:#fff;border-radius:13px;-webkit-border-radius:13px;-moz-border-radius:13px;border:1px solid #ccc}div.vjs-loading-spinner .ball8{opacity:1.00;position:absolute;left:6px;top:6px;width:13px;height:13px;background:#fff;border-radius:13px;-webkit-border-radius:13px;-moz-border-radius:13px;border:1px solid #ccc} \ No newline at end of file
+.video-js{background-color:#000;position:relative;padding:0;font-size:10px;vertical-align:middle}.video-js .vjs-tech{position:absolute;top:0;left:0;width:100%;height:100%}.video-js:-moz-full-screen{position:absolute}body.vjs-full-window{padding:0;margin:0;height:100%;overflow-y:auto}.video-js.vjs-fullscreen{position:fixed;overflow:hidden;z-index:1000;left:0;top:0;bottom:0;right:0;width:100%!important;height:100%!important;_position:absolute}.video-js:-webkit-full-screen{width:100%!important;height:100%!important}.vjs-poster{margin:0 auto;padding:0;cursor:pointer;position:relative;width:100%;max-height:100%}.video-js .vjs-text-track-display{text-align:center;position:absolute;bottom:4em;left:1em;right:1em;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}.video-js .vjs-text-track{display:none;color:#fff;font-size:1.4em;text-align:center;margin-bottom:.1em;background:#000;background:rgba(0,0,0,0.50)}.video-js .vjs-subtitles{color:#fff}.video-js .vjs-captions{color:#fc6}.vjs-tt-cue{display:block}.vjs-fade-in{visibility:visible!important;opacity:1!important;-webkit-transition:visibility 0s linear 0s,opacity .3s linear;-moz-transition:visibility 0s linear 0s,opacity .3s linear;-ms-transition:visibility 0s linear 0s,opacity .3s linear;-o-transition:visibility 0s linear 0s,opacity .3s linear;transition:visibility 0s linear 0s,opacity .3s linear}.vjs-fade-out{visibility:hidden!important;opacity:0!important;-webkit-transition:visibility 0s linear 1.5s,opacity 1.5s linear;-moz-transition:visibility 0s linear 1.5s,opacity 1.5s linear;-ms-transition:visibility 0s linear 1.5s,opacity 1.5s linear;-o-transition:visibility 0s linear 1.5s,opacity 1.5s linear;transition:visibility 0s linear 1.5s,opacity 1.5s linear}.vjs-default-skin .vjs-controls{position:absolute;bottom:0;left:0;right:0;margin:0;padding:0;height:2.6em;color:#fff;border-top:1px solid #404040;background:#242424;background:-moz-linear-gradient(top,#242424 50%,#1f1f1f 50%,#171717 100%);background:-webkit-gradient(linear,0% 0,0% 100%,color-stop(50%,#242424),color-stop(50%,#1f1f1f),color-stop(100%,#171717));background:-webkit-linear-gradient(top,#242424 50%,#1f1f1f 50%,#171717 100%);background:-o-linear-gradient(top,#242424 50%,#1f1f1f 50%,#171717 100%);background:-ms-linear-gradient(top,#242424 50%,#1f1f1f 50%,#171717 100%);background:linear-gradient(top,#242424 50%,#1f1f1f 50%,#171717 100%);visibility:hidden;opacity:0}.vjs-default-skin .vjs-control{position:relative;float:left;text-align:center;margin:0;padding:0;height:2.6em;width:2.6em}.vjs-default-skin .vjs-control:focus{outline:0}.vjs-default-skin .vjs-control-text{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.vjs-default-skin .vjs-play-control{width:5em;cursor:pointer!important}.vjs-default-skin.vjs-paused .vjs-play-control div{width:15px;height:17px;background:url('video-js.png');margin:.5em auto 0}.vjs-default-skin.vjs-playing .vjs-play-control div{width:15px;height:17px;background:url('video-js.png') -25px 0;margin:.5em auto 0}.vjs-default-skin .vjs-rewind-control{width:5em;cursor:pointer!important}.vjs-default-skin .vjs-rewind-control div{width:19px;height:16px;background:url('video-js.png');margin:.5em auto 0}.vjs-default-skin .vjs-mute-control{width:3.8em;cursor:pointer!important;float:right}.vjs-default-skin .vjs-mute-control div{width:22px;height:16px;background:url('video-js.png') -75px -25px;margin:.5em auto 0}.vjs-default-skin .vjs-mute-control.vjs-vol-0 div{background:url('video-js.png') 0 -25px}.vjs-default-skin .vjs-mute-control.vjs-vol-1 div{background:url('video-js.png') -25px -25px}.vjs-default-skin .vjs-mute-control.vjs-vol-2 div{background:url('video-js.png') -50px -25px}.vjs-default-skin .vjs-volume-control{width:5em;float:right}.vjs-default-skin .vjs-volume-bar{position:relative;width:5em;height:.6em;margin:1em auto 0;cursor:pointer!important;-moz-border-radius:.3em;-webkit-border-radius:.3em;border-radius:.3em;background:#666;background:-moz-linear-gradient(top,#333,#666);background:-webkit-gradient(linear,0% 0,0% 100%,from(#333),to(#666));background:-webkit-linear-gradient(top,#333,#666);background:-o-linear-gradient(top,#333,#666);background:-ms-linear-gradient(top,#333,#666);background:linear-gradient(top,#333,#666)}.vjs-default-skin .vjs-volume-level{position:absolute;top:0;left:0;height:.6em;-moz-border-radius:.3em;-webkit-border-radius:.3em;border-radius:.3em;background:#fff;background:-moz-linear-gradient(top,#fff,#ccc);background:-webkit-gradient(linear,0% 0,0% 100%,from(#fff),to(#ccc));background:-webkit-linear-gradient(top,#fff,#ccc);background:-o-linear-gradient(top,#fff,#ccc);background:-ms-linear-gradient(top,#fff,#ccc);background:linear-gradient(top,#fff,#ccc)}.vjs-default-skin .vjs-volume-handle{position:absolute;top:-0.2em;width:.8em;height:.8em;background:#ccc;left:0;border:1px solid #fff;-moz-border-radius:.6em;-webkit-border-radius:.6em;border-radius:.6em}.vjs-default-skin div.vjs-progress-control{position:absolute;left:4.8em;right:4.8em;height:1.0em;width:auto;top:-1.3em;border-bottom:1px solid #1f1f1f;border-top:1px solid #222;background:#333;background:-moz-linear-gradient(top,#222,#333);background:-webkit-gradient(linear,0% 0,0% 100%,from(#222),to(#333));background:-webkit-linear-gradient(top,#222,#333);background:-o-linear-gradient(top,#333,#222);background:-ms-linear-gradient(top,#333,#222);background:linear-gradient(top,#333,#222)}.vjs-default-skin .vjs-progress-holder{position:relative;cursor:pointer!important;padding:0;margin:0;height:1.0em;-moz-border-radius:.6em;-webkit-border-radius:.6em;border-radius:.6em;background:#111;background:-moz-linear-gradient(top,#111,#262626);background:-webkit-gradient(linear,0% 0,0% 100%,from(#111),to(#262626));background:-webkit-linear-gradient(top,#111,#262626);background:-o-linear-gradient(top,#111,#262626);background:-ms-linear-gradient(top,#111,#262626);background:linear-gradient(top,#111,#262626)}.vjs-default-skin .vjs-progress-holder .vjs-play-progress,.vjs-default-skin .vjs-progress-holder .vjs-load-progress{position:absolute;display:block;height:1.0em;margin:0;padding:0;left:0;top:0;-moz-border-radius:.6em;-webkit-border-radius:.6em;border-radius:.6em}.vjs-default-skin .vjs-play-progress{background:#fff;background:-moz-linear-gradient(top,#fff 0,#d6d6d6 50%,#fff 100%);background:-webkit-gradient(linear,0% 0,0% 100%,color-stop(0%,#fff),color-stop(50%,#d6d6d6),color-stop(100%,#fff));background:-webkit-linear-gradient(top,#fff 0,#d6d6d6 50%,#fff 100%);background:-o-linear-gradient(top,#fff 0,#d6d6d6 50%,#fff 100%);background:-ms-linear-gradient(top,#fff 0,#d6d6d6 50%,#fff 100%);background:linear-gradient(top,#fff 0,#d6d6d6 50%,#fff 100%);background:#efefef;background:-moz-linear-gradient(top,#efefef 0,#f5f5f5 50%,#dbdbdb 50%,#f1f1f1 100%);background:-webkit-gradient(linear,0% 0,0% 100%,color-stop(0%,#efefef),color-stop(50%,#f5f5f5),color-stop(50%,#dbdbdb),color-stop(100%,#f1f1f1));background:-webkit-linear-gradient(top,#efefef 0,#f5f5f5 50%,#dbdbdb 50%,#f1f1f1 100%);background:-o-linear-gradient(top,#efefef 0,#f5f5f5 50%,#dbdbdb 50%,#f1f1f1 100%);background:-ms-linear-gradient(top,#efefef 0,#f5f5f5 50%,#dbdbdb 50%,#f1f1f1 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#efefef',endColorstr='#f1f1f1',GradientType=0);background:linear-gradient(top,#efefef 0,#f5f5f5 50%,#dbdbdb 50%,#f1f1f1 100%)}.vjs-default-skin .vjs-load-progress{opacity:.8;background:#666;background:-moz-linear-gradient(top,#666,#333);background:-webkit-gradient(linear,0% 0,0% 100%,from(#666),to(#333));background:-webkit-linear-gradient(top,#666,#333);background:-o-linear-gradient(top,#666,#333);background:-ms-linear-gradient(top,#666,#333);background:linear-gradient(top,#666,#333)}.vjs-default-skin div.vjs-seek-handle{position:absolute;width:16px;height:16px;margin-top:-0.3em;left:0;top:0;background:url('video-js.png') 0 -50px;-moz-border-radius:.8em;-webkit-border-radius:.8em;border-radius:.8em;-webkit-box-shadow:0 2px 4px 0 #000;-moz-box-shadow:0 2px 4px 0 #000;box-shadow:0 2px 4px 0 #000}.vjs-default-skin .vjs-time-controls{position:absolute;right:0;height:1.0em;width:4.8em;top:-1.3em;border-bottom:1px solid #1f1f1f;border-top:1px solid #222;background-color:#333;font-size:1em;line-height:1.0em;font-weight:normal;font-family:Helvetica,Arial,sans-serif;background:#333;background:-moz-linear-gradient(top,#222,#333);background:-webkit-gradient(linear,0% 0,0% 100%,from(#222),to(#333));background:-webkit-linear-gradient(top,#222,#333);background:-o-linear-gradient(top,#333,#222);background:-ms-linear-gradient(top,#333,#222);background:linear-gradient(top,#333,#222)}.vjs-default-skin .vjs-current-time{left:0}.vjs-default-skin .vjs-duration{right:0;display:none}.vjs-default-skin .vjs-remaining-time{right:0}.vjs-time-divider{display:none}.vjs-default-skin .vjs-time-control{font-size:1em;line-height:1;font-weight:normal;font-family:Helvetica,Arial,sans-serif}.vjs-default-skin .vjs-time-control span{line-height:25px}.vjs-secondary-controls{float:right}.vjs-default-skin .vjs-fullscreen-control{width:3.8em;cursor:pointer!important;float:right}.vjs-default-skin .vjs-fullscreen-control div{width:16px;height:16px;background:url('video-js.png') -50px 0;margin:.5em auto 0}.vjs-default-skin.vjs-fullscreen .vjs-fullscreen-control div{background:url('video-js.png') -75px 0}.vjs-default-skin .vjs-big-play-button{display:block;z-index:2;position:absolute;top:50%;left:50%;width:8.0em;height:8.0em;margin:-42px 0 0 -42px;text-align:center;vertical-align:center;cursor:pointer!important;border:.2em solid #fff;opacity:.95;-webkit-border-radius:25px;-moz-border-radius:25px;border-radius:25px;background:#454545;background:-moz-linear-gradient(top,#454545 0,#232323 50%,#161616 50%,#3f3f3f 100%);background:-webkit-gradient(linear,0% 0,0% 100%,color-stop(0%,#454545),color-stop(50%,#232323),color-stop(50%,#161616),color-stop(100%,#3f3f3f));background:-webkit-linear-gradient(top,#454545 0,#232323 50%,#161616 50%,#3f3f3f 100%);background:-o-linear-gradient(top,#454545 0,#232323 50%,#161616 50%,#3f3f3f 100%);background:-ms-linear-gradient(top,#454545 0,#232323 50%,#161616 50%,#3f3f3f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#454545',endColorstr='#3f3f3f',GradientType=0);background:linear-gradient(top,#454545 0,#232323 50%,#161616 50%,#3f3f3f 100%);-webkit-box-shadow:4px 4px 8px #000;-moz-box-shadow:4px 4px 8px #000;box-shadow:4px 4px 8px #000}.vjs-default-skin div.vjs-big-play-button:hover{-webkit-box-shadow:0 0 80px #fff;-moz-box-shadow:0 0 80px #fff;box-shadow:0 0 80px #fff}.vjs-default-skin div.vjs-big-play-button span{position:absolute;top:50%;left:50%;display:block;width:35px;height:42px;margin:-20px 0 0 -15px;background:url('video-js.png') -100px 0}.vjs-loading-spinner{display:none;position:absolute;top:50%;left:50%;width:55px;height:55px;margin:-28px 0 0 -28px;-webkit-animation-name:rotatethis;-webkit-animation-duration:1s;-webkit-animation-iteration-count:infinite;-webkit-animation-timing-function:linear;-moz-animation-name:rotatethis;-moz-animation-duration:1s;-moz-animation-iteration-count:infinite;-moz-animation-timing-function:linear}@-webkit-keyframes rotatethis{0%{-webkit-transform:scale(0.6) rotate(0deg)}12.5%{-webkit-transform:scale(0.6) rotate(0deg)}12.51%{-webkit-transform:scale(0.6) rotate(45deg)}25%{-webkit-transform:scale(0.6) rotate(45deg)}25.01%{-webkit-transform:scale(0.6) rotate(90deg)}37.5%{-webkit-transform:scale(0.6) rotate(90deg)}37.51%{-webkit-transform:scale(0.6) rotate(135deg)}50%{-webkit-transform:scale(0.6) rotate(135deg)}50.01%{-webkit-transform:scale(0.6) rotate(180deg)}62.5%{-webkit-transform:scale(0.6) rotate(180deg)}62.51%{-webkit-transform:scale(0.6) rotate(225deg)}75%{-webkit-transform:scale(0.6) rotate(225deg)}75.01%{-webkit-transform:scale(0.6) rotate(270deg)}87.5%{-webkit-transform:scale(0.6) rotate(270deg)}87.51%{-webkit-transform:scale(0.6) rotate(315deg)}100%{-webkit-transform:scale(0.6) rotate(315deg)}}@-moz-keyframes rotatethis{0%{-moz-transform:scale(0.6) rotate(0deg)}12.5%{-moz-transform:scale(0.6) rotate(0deg)}12.51%{-moz-transform:scale(0.6) rotate(45deg)}25%{-moz-transform:scale(0.6) rotate(45deg)}25.01%{-moz-transform:scale(0.6) rotate(90deg)}37.5%{-moz-transform:scale(0.6) rotate(90deg)}37.51%{-moz-transform:scale(0.6) rotate(135deg)}50%{-moz-transform:scale(0.6) rotate(135deg)}50.01%{-moz-transform:scale(0.6) rotate(180deg)}62.5%{-moz-transform:scale(0.6) rotate(180deg)}62.51%{-moz-transform:scale(0.6) rotate(225deg)}75%{-moz-transform:scale(0.6) rotate(225deg)}75.01%{-moz-transform:scale(0.6) rotate(270deg)}87.5%{-moz-transform:scale(0.6) rotate(270deg)}87.51%{-moz-transform:scale(0.6) rotate(315deg)}100%{-moz-transform:scale(0.6) rotate(315deg)}}div.vjs-loading-spinner .ball1{opacity:.12;position:absolute;left:20px;top:0;width:13px;height:13px;background:#fff;border-radius:13px;-webkit-border-radius:13px;-moz-border-radius:13px;border:1px solid #ccc}div.vjs-loading-spinner .ball2{opacity:.25;position:absolute;left:34px;top:6px;width:13px;height:13px;background:#fff;border-radius:13px;-webkit-border-radius:13px;-moz-border-radius:13px;border:1px solid #ccc}div.vjs-loading-spinner .ball3{opacity:.37;position:absolute;left:40px;top:20px;width:13px;height:13px;background:#fff;border-radius:13px;-webkit-border-radius:13px;-moz-border-radius:13px;border:1px solid #ccc}div.vjs-loading-spinner .ball4{opacity:.50;position:absolute;left:34px;top:34px;width:13px;height:13px;background:#fff;border-radius:10px;-webkit-border-radius:10px;-moz-border-radius:15px;border:1px solid #ccc}div.vjs-loading-spinner .ball5{opacity:.62;position:absolute;left:20px;top:40px;width:13px;height:13px;background:#fff;border-radius:13px;-webkit-border-radius:13px;-moz-border-radius:13px;border:1px solid #ccc}div.vjs-loading-spinner .ball6{opacity:.75;position:absolute;left:6px;top:34px;width:13px;height:13px;background:#fff;border-radius:13px;-webkit-border-radius:13px;-moz-border-radius:13px;border:1px solid #ccc}div.vjs-loading-spinner .ball7{opacity:.87;position:absolute;left:0;top:20px;width:13px;height:13px;background:#fff;border-radius:13px;-webkit-border-radius:13px;-moz-border-radius:13px;border:1px solid #ccc}div.vjs-loading-spinner .ball8{opacity:1.00;position:absolute;left:6px;top:6px;width:13px;height:13px;background:#fff;border-radius:13px;-webkit-border-radius:13px;-moz-border-radius:13px;border:1px solid #ccc}.vjs-default-skin .vjs-menu-button{float:right;margin:.2em .5em 0 0;padding:0;width:3em;height:2em;cursor:pointer!important;border:1px solid #111;-moz-border-radius:.3em;-webkit-border-radius:.3em;border-radius:.3em;background:#4d4d4d;background:-moz-linear-gradient(top,#4d4d4d 0,#3f3f3f 50%,#333 50%,#252525 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#4d4d4d),color-stop(50%,#3f3f3f),color-stop(50%,#333),color-stop(100%,#252525));background:-webkit-linear-gradient(top,#4d4d4d 0,#3f3f3f 50%,#333 50%,#252525 100%);background:-o-linear-gradient(top,#4d4d4d 0,#3f3f3f 50%,#333 50%,#252525 100%);background:-ms-linear-gradient(top,#4d4d4d 0,#3f3f3f 50%,#333 50%,#252525 100%);background:linear-gradient(top,#4d4d4d 0,#3f3f3f 50%,#333 50%,#252525 100%)}.vjs-default-skin .vjs-menu-button div{background:url('video-js.png') 0 -75px no-repeat;width:16px;height:16px;margin:.2em auto 0;padding:0}.vjs-default-skin .vjs-menu-button ul{display:none;opacity:.8;padding:0;margin:0;position:absolute;width:10em;bottom:2em;max-height:15em;left:-3.5em;background-color:#111;border:2px solid #333;-moz-border-radius:.7em;-webkit-border-radius:1em;border-radius:.5em;-webkit-box-shadow:0 2px 4px 0 #000;-moz-box-shadow:0 2px 4px 0 #000;box-shadow:0 2px 4px 0 #000;overflow:auto}.vjs-default-skin .vjs-menu-button:focus ul,.vjs-default-skin .vjs-menu-button:hover ul{display:block;list-style:none}.vjs-default-skin .vjs-menu-button ul li{list-style:none;margin:0;padding:.3em 0 .3em 20px;line-height:1.4em;font-size:1.2em;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;text-align:left}.vjs-default-skin .vjs-menu-button ul li.vjs-selected{text-decoration:underline;background:url('video-js.png') -125px -50px no-repeat}.vjs-default-skin .vjs-menu-button ul li:focus,.vjs-default-skin .vjs-menu-button ul li:hover,.vjs-default-skin .vjs-menu-button ul li.vjs-selected:focus,.vjs-default-skin .vjs-menu-button ul li.vjs-selected:hover{background-color:#ccc;color:#111;outline:0}.vjs-default-skin .vjs-menu-button ul li.vjs-menu-title{text-align:center;text-transform:uppercase;font-size:1em;line-height:2em;padding:0;margin:0 0 .3em 0;color:#fff;font-weight:bold;cursor:default;background:#4d4d4d;background:-moz-linear-gradient(top,#4d4d4d 0,#3f3f3f 50%,#333 50%,#252525 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#4d4d4d),color-stop(50%,#3f3f3f),color-stop(50%,#333),color-stop(100%,#252525));background:-webkit-linear-gradient(top,#4d4d4d 0,#3f3f3f 50%,#333 50%,#252525 100%);background:-o-linear-gradient(top,#4d4d4d 0,#3f3f3f 50%,#333 50%,#252525 100%);background:-ms-linear-gradient(top,#4d4d4d 0,#3f3f3f 50%,#333 50%,#252525 100%);background:linear-gradient(top,#4d4d4d 0,#3f3f3f 50%,#333 50%,#252525 100%)}.vjs-default-skin .vjs-captions-button div{background-position:-25px -75px}.vjs-default-skin .vjs-chapters-button div{background-position:-100px -75px}.vjs-default-skin .vjs-chapters-button ul{width:20em;left:-8.5em} \ No newline at end of file
diff --git a/extlib/video-js/video-js.png b/extlib/video-js/video-js.png
index c692d123..100bc7f8 100644
--- a/extlib/video-js/video-js.png
+++ b/extlib/video-js/video-js.png
Binary files differ
diff --git a/extlib/video-js/video-js.swf b/extlib/video-js/video-js.swf
deleted file mode 100644
index 3273af5a..00000000
--- a/extlib/video-js/video-js.swf
+++ /dev/null
Binary files differ
diff --git a/extlib/video-js/video.js b/extlib/video-js/video.js
deleted file mode 100644
index c41cceec..00000000
--- a/extlib/video-js/video.js
+++ /dev/null
@@ -1,3744 +0,0 @@
-/*!
-Video.js - HTML5 Video Player
-Version 3.1.0
-
-LGPL v3 LICENSE INFO
-This file is part of Video.js. Copyright 2011 Zencoder, Inc.
-
-Video.js is free software: you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Video.js 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 Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License
-along with Video.js. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-// Self-executing function to prevent global vars and help with minification
-;(function(window, undefined){
- var document = window.document;// HTML5 Shiv. Must be in <head> to support older browsers.
-document.createElement("video");document.createElement("audio");
-
-var VideoJS = function(id, addOptions, ready){
- var tag; // Element of ID
-
- // Allow for element or ID to be passed in
- // String ID
- if (typeof id == "string") {
-
- // Adjust for jQuery ID syntax
- if (id.indexOf("#") === 0) {
- id = id.slice(1);
- }
-
- // If a player instance has already been created for this ID return it.
- if (_V_.players[id]) {
- return _V_.players[id];
-
- // Otherwise get element for ID
- } else {
- tag = _V_.el(id)
- }
-
- // ID is a media element
- } else {
- tag = id;
- }
-
- // Check for a useable element
- if (!tag || !tag.nodeName) { // re: nodeName, could be a box div also
- throw new TypeError("The element or ID supplied is not valid. (VideoJS)"); // Returns
- }
-
- // Element may have a player attr referring to an already created player instance.
- // If not, set up a new player and return the instance.
- return tag.player || new _V_.Player(tag, addOptions, ready);
-},
-
-// Shortcut
-_V_ = VideoJS,
-
-// CDN Version. Used to target right flash swf.
-CDN_VERSION = "3.1";
-
-VideoJS.players = {};
-
-VideoJS.options = {
-
- // Default order of fallback technology
- techOrder: ["html5","flash"],
- // techOrder: ["flash","html5"],
-
- html5: {},
- flash: { swf: "http://vjs.zencdn.net/c/video-js.swf" },
-
- // Default of web browser is 300x150. Should rely on source width/height.
- width: "auto",
- height: "auto",
-
- // defaultVolume: 0.85,
- defaultVolume: 0.00, // The freakin seaguls are driving me crazy!
-
- // Included control sets
- components: {
- "poster": {},
- "loadingSpinner": {},
- "bigPlayButton": {},
- "controlBar": {},
- "subtitlesDisplay": {}
- }
-
- // components: [
- // "poster",
- // "loadingSpinner",
- // "bigPlayButton",
- // { name: "controlBar", options: {
- // components: [
- // "playToggle",
- // "fullscreenToggle",
- // "currentTimeDisplay",
- // "timeDivider",
- // "durationDisplay",
- // "remainingTimeDisplay",
- // { name: "progressControl", options: {
- // components: [
- // { name: "seekBar", options: {
- // components: [
- // "loadProgressBar",
- // "playProgressBar",
- // "seekHandle"
- // ]}
- // }
- // ]}
- // },
- // { name: "volumeControl", options: {
- // components: [
- // { name: "volumeBar", options: {
- // components: [
- // "volumeLevel",
- // "volumeHandle"
- // ]}
- // }
- // ]}
- // },
- // "muteToggle"
- // ]
- // }},
- // "subtitlesDisplay"/*, "replay"*/
- // ]
-};
-
-// Set CDN Version of swf
-if (CDN_VERSION != "GENERATED_CDN_VSN") {
- _V_.options.flash.swf = "http://vjs.zencdn.net/"+CDN_VERSION+"/video-js.swf"
-}
-
-// Automatically set up any tags that have a data-setup attribute
-_V_.autoSetup = function(){
- var options, vid, player,
- vids = document.getElementsByTagName("video");
-
- // Check if any media elements exist
- if (vids && vids.length > 0) {
-
- for (var i=0,j=vids.length; i<j; i++) {
- vid = vids[i];
-
- // Check if element exists, has getAttribute func.
- // IE seems to consider typeof el.getAttribute == "object" instead of "function" like expected, at least when loading the player immediately.
- if (vid && vid.getAttribute) {
-
- // Make sure this player hasn't already been set up.
- if (vid.player === undefined) {
- options = vid.getAttribute("data-setup");
-
- // Check if data-setup attr exists.
- // We only auto-setup if they've added the data-setup attr.
- if (options !== null) {
-
- // Parse options JSON
- // If empty string, make it a parsable json object.
- options = JSON.parse(options || "{}");
-
- // Create new video.js instance.
- player = _V_(vid, options);
- }
- }
-
- // If getAttribute isn't defined, we need to wait for the DOM.
- } else {
- _V_.autoSetupTimeout(1);
- break;
- }
- }
-
- // No videos were found, so keep looping unless page is finisehd loading.
- } else if (!_V_.windowLoaded) {
- _V_.autoSetupTimeout(1);
- }
-};
-
-// Pause to let the DOM keep processing
-_V_.autoSetupTimeout = function(wait){
- setTimeout(_V_.autoSetup, wait);
-};
-_V_.merge = function(obj1, obj2, safe){
- // Make sure second object exists
- if (!obj2) { obj2 = {}; };
-
- for (var attrname in obj2){
- if (obj2.hasOwnProperty(attrname) && (!safe || !obj1.hasOwnProperty(attrname))) { obj1[attrname]=obj2[attrname]; }
- }
- return obj1;
-};
-_V_.extend = function(obj){ this.merge(this, obj, true); };
-
-_V_.extend({
- tech: {}, // Holder for playback technology settings
- controlSets: {}, // Holder for control set definitions
-
- // Device Checks
- isIE: function(){ return !+"\v1"; },
- isFF: function(){ return !!_V_.ua.match("Firefox") },
- isIPad: function(){ return navigator.userAgent.match(/iPad/i) !== null; },
- isIPhone: function(){ return navigator.userAgent.match(/iPhone/i) !== null; },
- isIOS: function(){ return VideoJS.isIPhone() || VideoJS.isIPad(); },
- iOSVersion: function() {
- var match = navigator.userAgent.match(/OS (\d+)_/i);
- if (match && match[1]) { return match[1]; }
- },
- isAndroid: function(){ return navigator.userAgent.match(/Android.*AppleWebKit/i) !== null; },
- androidVersion: function() {
- var match = navigator.userAgent.match(/Android (\d+)\./i);
- if (match && match[1]) { return match[1]; }
- },
-
- testVid: document.createElement("video"),
- ua: navigator.userAgent,
- support: {},
-
- each: function(arr, fn){
- if (!arr || arr.length === 0) { return; }
- for (var i=0,j=arr.length; i<j; i++) {
- fn.call(this, arr[i], i);
- }
- },
-
- eachProp: function(obj, fn){
- if (!obj) { return; }
- for (var name in obj) {
- if (obj.hasOwnProperty(name)) {
- fn.call(this, name, obj[name]);
- }
- }
- },
-
- el: function(id){ return document.getElementById(id); },
- createElement: function(tagName, attributes){
- var el = document.createElement(tagName),
- attrname;
- for (attrname in attributes){
- if (attributes.hasOwnProperty(attrname)) {
- if (attrname.indexOf("-") !== -1) {
- el.setAttribute(attrname, attributes[attrname]);
- } else {
- el[attrname] = attributes[attrname];
- }
- }
- }
- return el;
- },
-
- insertFirst: function(node, parent){
- if (parent.firstChild) {
- parent.insertBefore(node, parent.firstChild);
- } else {
- parent.appendChild(node);
- }
- },
-
- addClass: function(element, classToAdd){
- if ((" "+element.className+" ").indexOf(" "+classToAdd+" ") == -1) {
- element.className = element.className === "" ? classToAdd : element.className + " " + classToAdd;
- }
- },
-
- removeClass: function(element, classToRemove){
- if (element.className.indexOf(classToRemove) == -1) { return; }
- var classNames = element.className.split(" ");
- classNames.splice(classNames.indexOf(classToRemove),1);
- element.className = classNames.join(" ");
- },
-
- remove: function(item, array){
- if (!array) return;
- var i = array.indexOf(item);
- if (i != -1) {
- return array.splice(i, 1)
- };
- },
-
- // Attempt to block the ability to select text while dragging controls
- blockTextSelection: function(){
- document.body.focus();
- document.onselectstart = function () { return false; };
- },
- // Turn off text selection blocking
- unblockTextSelection: function(){ document.onselectstart = function () { return true; }; },
-
- // Return seconds as H:MM:SS or M:SS
- // Supplying a guide (in seconds) will include enough leading zeros to cover the length of the guide
- formatTime: function(seconds, guide) {
- guide = guide || seconds; // Default to using seconds as guide
- var s = Math.floor(seconds % 60),
- m = Math.floor(seconds / 60 % 60),
- h = Math.floor(seconds / 3600),
- gm = Math.floor(guide / 60 % 60),
- gh = Math.floor(guide / 3600);
-
- // Check if we need to show hours
- h = (h > 0 || gh > 0) ? h + ":" : "";
-
- // If hours are showing, we may need to add a leading zero.
- // Always show at least one digit of minutes.
- m = (((h || gm >= 10) && m < 10) ? "0" + m : m) + ":";
-
- // Check if leading zero is need for seconds
- s = (s < 10) ? "0" + s : s;
-
- return h + m + s;
- },
-
- capitalize: function(string){
- return string.charAt(0).toUpperCase() + string.slice(1);
- },
-
- // Return the relative horizonal position of an event as a value from 0-1
- getRelativePosition: function(x, relativeElement){
- return Math.max(0, Math.min(1, (x - _V_.findPosX(relativeElement)) / relativeElement.offsetWidth));
- },
-
- getComputedStyleValue: function(element, style){
- return window.getComputedStyle(element, null).getPropertyValue(style);
- },
-
- trim: function(string){ return string.toString().replace(/^\s+/, "").replace(/\s+$/, ""); },
- round: function(num, dec) {
- if (!dec) { dec = 0; }
- return Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
- },
-
- isEmpty: function(object) {
- for (var prop in object) {
- return false;
- }
- return true;
- },
-
- // Mimic HTML5 TimeRange Spec.
- createTimeRange: function(start, end){
- return {
- length: 1,
- start: function() { return start; },
- end: function() { return end; }
- };
- },
-
- /* Element Data Store. Allows for binding data to an element without putting it directly on the element.
- Ex. Event listneres are stored here.
- (also from jsninja.com)
- ================================================================================ */
- cache: {}, // Where the data is stored
- guid: 1, // Unique ID for the element
- expando: "vdata" + (new Date).getTime(), // Unique attribute to store element's guid in
-
- // Returns the cache object where data for the element is stored
- getData: function(elem){
- var id = elem[_V_.expando];
- if (!id) {
- id = elem[_V_.expando] = _V_.guid++;
- _V_.cache[id] = {};
- }
- return _V_.cache[id];
- },
- // Delete data for the element from the cache and the guid attr from element
- removeData: function(elem){
- var id = elem[_V_.expando];
- if (!id) { return; }
- // Remove all stored data
- delete _V_.cache[id];
- // Remove the expando property from the DOM node
- try {
- delete elem[_V_.expando];
- } catch(e) {
- if (elem.removeAttribute) {
- elem.removeAttribute(_V_.expando);
- } else {
- // IE doesn't appear to support removeAttribute on the document element
- elem[_V_.expando] = null;
- }
- }
- },
-
- /* Proxy (a.k.a Bind or Context). A simple method for changing the context of a function
- It also stores a unique id on the function so it can be easily removed from events
- ================================================================================ */
- proxy: function(context, fn) {
- // Make sure the function has a unique ID
- if (!fn.guid) { fn.guid = _V_.guid++; }
- // Create the new function that changes the context
- var ret = function() {
- return fn.apply(context, arguments);
- };
-
- // Give the new function the same ID
- // (so that they are equivalent and can be easily removed)
- ret.guid = fn.guid;
-
- return ret;
- },
-
- get: function(url, onSuccess, onError){
- // if (netscape.security.PrivilegeManager.enablePrivilege) {
- // netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
- // }
-
- var local = (url.indexOf("file:") == 0 || (window.location.href.indexOf("file:") == 0 && url.indexOf("http:") == -1));
-
- if (typeof XMLHttpRequest == "undefined") {
- XMLHttpRequest = function () {
- try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e) {}
- try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (f) {}
- try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (g) {}
- throw new Error("This browser does not support XMLHttpRequest.");
- };
- }
-
- var request = new XMLHttpRequest();
-
- try {
- request.open("GET", url);
- } catch(e) {
- _V_.log("VideoJS XMLHttpRequest (open)", e);
- // onError(e);
- return false;
- }
-
- request.onreadystatechange = _V_.proxy(this, function() {
- if (request.readyState == 4) {
- if (request.status == 200 || local && request.status == 0) {
- onSuccess(request.responseText);
- } else {
- if (onError) {
- onError();
- }
- }
- }
- });
-
- try {
- request.send();
- } catch(e) {
- _V_.log("VideoJS XMLHttpRequest (send)", e);
- if (onError) {
- onError(e);
- }
- }
- },
-
- /* Local Storage
- ================================================================================ */
- setLocalStorage: function(key, value){
- // IE was throwing errors referencing the var anywhere without this
- var localStorage = localStorage || false;
- if (!localStorage) { return; }
- try {
- localStorage[key] = value;
- } catch(e) {
- if (e.code == 22 || e.code == 1014) { // Webkit == 22 / Firefox == 1014
- _V_.log("LocalStorage Full (VideoJS)", e);
- } else {
- _V_.log("LocalStorage Error (VideoJS)", e);
- }
- }
- }
-
-});
-
-// usage: log('inside coolFunc', this, arguments);
-// paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
-_V_.log = function(){
- _V_.log.history = _V_.log.history || [];// store logs to an array for reference
- _V_.log.history.push(arguments);
- if(window.console) {
- arguments.callee = arguments.callee.caller;
- var newarr = [].slice.call(arguments);
- (typeof console.log === 'object' ? _V_.log.apply.call(console.log, console, newarr) : console.log.apply(console, newarr));
- }
-};
-
-// make it safe to use console.log always
-(function(b){function c(){}for(var d="assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,timeStamp,profile,profileEnd,time,timeEnd,trace,warn".split(","),a;a=d.pop();){b[a]=b[a]||c}})((function(){try
-{console.log();return window.console;}catch(err){return window.console={};}})());
-
-// Offset Left
-// getBoundingClientRect technique from John Resig http://ejohn.org/blog/getboundingclientrect-is-awesome/
-if ("getBoundingClientRect" in document.documentElement) {
- _V_.findPosX = function(el) {
- var box;
-
- try {
- box = el.getBoundingClientRect();
- } catch(e) {}
-
- if (!box) { return 0; }
-
- var docEl = document.documentElement,
- body = document.body,
- clientLeft = docEl.clientLeft || body.clientLeft || 0,
- scrollLeft = window.pageXOffset || body.scrollLeft,
- left = box.left + scrollLeft - clientLeft;
-
- return left;
- };
-} else {
- _V_.findPosX = function(el) {
- var curleft = el.offsetLeft;
- // _V_.log(obj.className, obj.offsetLeft)
- while(el = obj.offsetParent) {
- if (el.className.indexOf("video-js") == -1) {
- // _V_.log(el.offsetParent, "OFFSETLEFT", el.offsetLeft)
- // _V_.log("-webkit-full-screen", el.webkitMatchesSelector("-webkit-full-screen"));
- // _V_.log("-webkit-full-screen", el.querySelectorAll(".video-js:-webkit-full-screen"));
- } else {
- }
- curleft += el.offsetLeft;
- }
- return curleft;
- };
-}// Using John Resig's Class implementation http://ejohn.org/blog/simple-javascript-inheritance/
-// (function(){var initializing=false, fnTest=/xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/; _V_.Class = function(){}; _V_.Class.extend = function(prop) { var _super = this.prototype; initializing = true; var prototype = new this(); initializing = false; for (var name in prop) { prototype[name] = typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name]) ? (function(name, fn){ return function() { var tmp = this._super; this._super = _super[name]; var ret = fn.apply(this, arguments); this._super = tmp; return ret; }; })(name, prop[name]) : prop[name]; } function Class() { if ( !initializing && this.init ) this.init.apply(this, arguments); } Class.prototype = prototype; Class.constructor = Class; Class.extend = arguments.callee; return Class;};})();
-(function(){
- var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
- _V_.Class = function(){};
- _V_.Class.extend = function(prop) {
- var _super = this.prototype;
- initializing = true;
- var prototype = new this();
- initializing = false;
- for (var name in prop) {
- prototype[name] = typeof prop[name] == "function" &&
- typeof _super[name] == "function" && fnTest.test(prop[name]) ?
- (function(name, fn){
- return function() {
- var tmp = this._super;
- this._super = _super[name];
- var ret = fn.apply(this, arguments);
- this._super = tmp;
- return ret;
- };
- })(name, prop[name]) :
- prop[name];
- }
- function Class() {
- if ( !initializing && this.init ) {
- return this.init.apply(this, arguments);
-
- // Attempting to recreate accessing function form of class.
- } else if (!initializing) {
- return arguments.callee.prototype.init()
- }
- }
- Class.prototype = prototype;
- Class.constructor = Class;
- Class.extend = arguments.callee;
- return Class;
- };
-})();
-
-/* Player Component- Base class for all UI objects
-================================================================================ */
-_V_.Component = _V_.Class.extend({
-
- init: function(player, options){
- this.player = player;
-
- // Allow for overridding default component options
- options = this.options = _V_.merge(this.options || {}, options);
-
- // Create element if one wasn't provided in options
- if (options.el) {
- this.el = options.el;
- } else {
- this.el = this.createElement();
- }
-
- // Add any components in options
- this.initComponents();
- },
-
- destroy: function(){},
-
- createElement: function(type, attrs){
- return _V_.createElement(type || "div", attrs);
- },
-
- buildCSSClass: function(){
- // Child classes can include a function that does:
- // return "CLASS NAME" + this._super();
- return "";
- },
-
- initComponents: function(){
- var options = this.options;
- if (options && options.components) {
- // Loop through components and add them to the player
- this.eachProp(options.components, function(name, opts){
-
- // Allow waiting to add components until a specific event is called
- var tempAdd = this.proxy(function(){
- this.addComponent(name, opts);
- });
-
- if (opts.loadEvent) {
- this.one(opts.loadEvent, tempAdd)
- } else {
- tempAdd();
- }
- });
- }
- },
-
- // Add child components to this component.
- // Will generate a new child component and then append child component's element to this component's element.
- // Takes either the name of the UI component class, or an object that contains a name, UI Class, and options.
- addComponent: function(name, options){
- var componentClass, component;
-
- // Make sure options is at least an empty object to protect against errors
- options = options || {};
-
- // Assume name of set is a lowercased name of the UI Class (PlayButton, etc.)
- componentClass = options.componentClass || _V_.capitalize(name);
-
- // Create a new object & element for this controls set
- // If there's no .player, this is a player
- component = new _V_[componentClass](this.player || this, options);
-
- // Add the UI object's element to the container div (box)
- this.el.appendChild(component.el);
-
- // Set property name on player. Could cause conflicts with other prop names, but it's worth making refs easy.
- this[name] = component;
- },
-
- /* Display
- ================================================================================ */
- show: function(){
- this.el.style.display = "block";
- },
-
- hide: function(){
- this.el.style.display = "none";
- },
-
- fadeIn: function(){
- this.removeClass("vjs-fade-out");
- this.addClass("vjs-fade-in");
- },
-
- fadeOut: function(){
- this.removeClass("vjs-fade-in");
- this.addClass("vjs-fade-out");
- },
-
- addClass: function(classToAdd){
- _V_.addClass(this.el, classToAdd);
- },
-
- removeClass: function(classToRemove){
- _V_.removeClass(this.el, classToRemove);
- },
-
- /* Events
- ================================================================================ */
- addEvent: function(type, fn){
- return _V_.addEvent(this.el, type, _V_.proxy(this, fn));
- },
- removeEvent: function(type, fn){
- return _V_.removeEvent(this.el, type, fn);
- },
- triggerEvent: function(type, e){
- return _V_.triggerEvent(this.el, type, e);
- },
- one: function(type, fn) {
- _V_.one.call(this, this.el, type, fn);
- },
-
- /* Ready - Trigger functions when component is ready
- ================================================================================ */
- ready: function(fn){
- if (!fn) return this;
-
- if (this.isReady) {
- fn.call(this);
- } else {
- if (this.readyQueue === undefined) {
- this.readyQueue = [];
- }
- this.readyQueue.push(fn);
- }
-
- return this;
- },
-
- triggerReady: function(){
- this.isReady = true;
- if (this.readyQueue && this.readyQueue.length > 0) {
- // Call all functions in ready queue
- this.each(this.readyQueue, function(fn){
- fn.call(this);
- });
-
- // Reset Ready Queue
- this.readyQueue = [];
- }
- },
-
- /* Utility
- ================================================================================ */
- each: function(arr, fn){ _V_.each.call(this, arr, fn); },
-
- eachProp: function(obj, fn){ _V_.eachProp.call(this, obj, fn); },
-
- extend: function(obj){ _V_.merge(this, obj) },
-
- // More easily attach 'this' to functions
- proxy: function(fn){ return _V_.proxy(this, fn); }
-
-});/* Control - Base class for all control elements
-================================================================================ */
-_V_.Control = _V_.Component.extend({
-
- buildCSSClass: function(){
- return "vjs-control " + this._super();
- }
-
-});
-
-/* Button - Base class for all buttons
-================================================================================ */
-_V_.Button = _V_.Control.extend({
-
- init: function(player, options){
- this._super(player, options);
-
- this.addEvent("click", this.onClick);
- this.addEvent("focus", this.onFocus);
- this.addEvent("blur", this.onBlur);
- },
-
- createElement: function(type, attrs){
- // Add standard Aria and Tabindex info
- attrs = _V_.merge({
- className: this.buildCSSClass(),
- innerHTML: '<div><span class="vjs-control-text">' + (this.buttonText || "Need Text") + '</span></div>',
- role: "button",
- tabIndex: 0
- }, attrs);
-
- return this._super(type, attrs);
- },
-
- // Click - Override with specific functionality for button
- onClick: function(){},
-
- // Focus - Add keyboard functionality to element
- onFocus: function(){
- _V_.addEvent(document, "keyup", _V_.proxy(this, this.onKeyPress));
- },
-
- // KeyPress (document level) - Trigger click when keys are pressed
- onKeyPress: function(event){
- // Check for space bar (32) or enter (13) keys
- if (event.which == 32 || event.which == 13) {
- event.preventDefault();
- this.onClick();
- }
- },
-
- // Blur - Remove keyboard triggers
- onBlur: function(){
- _V_.removeEvent(document, "keyup", _V_.proxy(this, this.onKeyPress));
- }
-
-});
-
-/* Play Button
-================================================================================ */
-_V_.PlayButton = _V_.Button.extend({
-
- buttonText: "Play",
-
- buildCSSClass: function(){
- return "vjs-play-button " + this._super();
- },
-
- onClick: function(){
- this.player.play();
- }
-
-});
-
-/* Pause Button
-================================================================================ */
-_V_.PauseButton = _V_.Button.extend({
-
- buttonText: "Pause",
-
- buildCSSClass: function(){
- return "vjs-pause-button " + this._super();
- },
-
- onClick: function(){
- this.player.pause();
- }
-
-});
-
-/* Play Toggle - Play or Pause Media
-================================================================================ */
-_V_.PlayToggle = _V_.Button.extend({
-
- buttonText: "Play",
-
- init: function(player, options){
- this._super(player, options);
-
- player.addEvent("play", _V_.proxy(this, this.onPlay));
- player.addEvent("pause", _V_.proxy(this, this.onPause));
- },
-
- buildCSSClass: function(){
- return "vjs-play-control " + this._super();
- },
-
- // OnClick - Toggle between play and pause
- onClick: function(){
- if (this.player.paused()) {
- this.player.play();
- } else {
- this.player.pause();
- }
- },
-
- // OnPlay - Add the vjs-playing class to the element so it can change appearance
- onPlay: function(){
- _V_.removeClass(this.el, "vjs-paused");
- _V_.addClass(this.el, "vjs-playing");
- },
-
- // OnPause - Add the vjs-paused class to the element so it can change appearance
- onPause: function(){
- _V_.removeClass(this.el, "vjs-playing");
- _V_.addClass(this.el, "vjs-paused");
- }
-
-});
-
-
-/* Fullscreen Toggle Behaviors
-================================================================================ */
-_V_.FullscreenToggle = _V_.Button.extend({
-
- buttonText: "Fullscreen",
-
- buildCSSClass: function(){
- return "vjs-fullscreen-control " + this._super();
- },
-
- onClick: function(){
- if (!this.player.isFullScreen) {
- this.player.requestFullScreen();
- } else {
- this.player.cancelFullScreen();
- }
- }
-
-});
-
-/* Big Play Button
-================================================================================ */
-_V_.BigPlayButton = _V_.Button.extend({
- init: function(player, options){
- this._super(player, options);
-
- player.addEvent("play", _V_.proxy(this, this.hide));
- player.addEvent("ended", _V_.proxy(this, this.show));
- },
-
- createElement: function(){
- return this._super("div", {
- className: "vjs-big-play-button",
- innerHTML: "<span></span>"
- });
- },
-
- onClick: function(){
- // Go back to the beginning if big play button is showing at the end.
- // Have to check for current time otherwise it might throw a 'not ready' error.
- if(this.player.currentTime()) {
- this.player.currentTime(0);
- }
- this.player.play();
- }
-});
-
-/* Loading Spinner
-================================================================================ */
-_V_.LoadingSpinner = _V_.Component.extend({
- init: function(player, options){
- this._super(player, options);
-
- player.addEvent("canplay", _V_.proxy(this, this.hide));
- player.addEvent("canplaythrough", _V_.proxy(this, this.hide));
- player.addEvent("playing", _V_.proxy(this, this.hide));
-
- player.addEvent("seeking", _V_.proxy(this, this.show));
- player.addEvent("error", _V_.proxy(this, this.show));
-
- // Not showing spinner on stalled any more. Browsers may stall and then not trigger any events that would remove the spinner.
- // Checked in Chrome 16 and Safari 5.1.2. http://help.videojs.com/discussions/problems/883-why-is-the-download-progress-showing
- // player.addEvent("stalled", _V_.proxy(this, this.show));
-
- player.addEvent("waiting", _V_.proxy(this, this.show));
- },
-
- createElement: function(){
-
- var classNameSpinner, innerHtmlSpinner;
-
- if ( typeof this.player.el.style.WebkitBorderRadius == "string"
- || typeof this.player.el.style.MozBorderRadius == "string"
- || typeof this.player.el.style.KhtmlBorderRadius == "string"
- || typeof this.player.el.style.borderRadius == "string")
- {
- classNameSpinner = "vjs-loading-spinner";
- innerHtmlSpinner = "<div class='ball1'></div><div class='ball2'></div><div class='ball3'></div><div class='ball4'></div><div class='ball5'></div><div class='ball6'></div><div class='ball7'></div><div class='ball8'></div>";
- } else {
- classNameSpinner = "vjs-loading-spinner-fallback";
- innerHtmlSpinner = "";
- }
-
- return this._super("div", {
- className: classNameSpinner,
- innerHTML: innerHtmlSpinner
- });
- }
-});
-
-/* Control Bar
-================================================================================ */
-_V_.ControlBar = _V_.Component.extend({
-
- options: {
- loadEvent: "play",
- components: {
- "playToggle": {},
- "fullscreenToggle": {},
- "currentTimeDisplay": {},
- "timeDivider": {},
- "durationDisplay": {},
- "remainingTimeDisplay": {},
- "progressControl": {},
- "volumeControl": {},
- "muteToggle": {}
- }
- },
-
- init: function(player, options){
- this._super(player, options);
-
- player.addEvent("play", this.proxy(function(){
- this.fadeIn();
- this.player.addEvent("mouseover", this.proxy(this.fadeIn));
- this.player.addEvent("mouseout", this.proxy(this.fadeOut));
- }));
- },
-
- createElement: function(){
- return _V_.createElement("div", {
- className: "vjs-controls"
- });
- },
-
- fadeIn: function(){
- this._super();
- this.player.triggerEvent("controlsvisible");
- },
-
- fadeOut: function(){
- this._super();
- this.player.triggerEvent("controlshidden");
- }
-});
-
-/* Time
-================================================================================ */
-_V_.CurrentTimeDisplay = _V_.Component.extend({
-
- init: function(player, options){
- this._super(player, options);
-
- player.addEvent("timeupdate", _V_.proxy(this, this.updateContent));
- },
-
- createElement: function(){
- var el = this._super("div", {
- className: "vjs-current-time vjs-time-controls vjs-control"
- });
-
- this.content = _V_.createElement("div", {
- className: "vjs-current-time-display",
- innerHTML: '0:00'
- });
-
- el.appendChild(_V_.createElement("div").appendChild(this.content));
- return el;
- },
-
- updateContent: function(){
- // Allows for smooth scrubbing, when player can't keep up.
- var time = (this.player.scrubbing) ? this.player.values.currentTime : this.player.currentTime();
- this.content.innerHTML = _V_.formatTime(time, this.player.duration());
- }
-
-});
-
-_V_.DurationDisplay = _V_.Component.extend({
-
- init: function(player, options){
- this._super(player, options);
-
- player.addEvent("timeupdate", _V_.proxy(this, this.updateContent));
- },
-
- createElement: function(){
- var el = this._super("div", {
- className: "vjs-duration vjs-time-controls vjs-control"
- });
-
- this.content = _V_.createElement("div", {
- className: "vjs-duration-display",
- innerHTML: '0:00'
- });
-
- el.appendChild(_V_.createElement("div").appendChild(this.content));
- return el;
- },
-
- updateContent: function(){
- if (this.player.duration()) { this.content.innerHTML = _V_.formatTime(this.player.duration()); }
- }
-
-});
-
-// Time Separator (Not used in main skin, but still available, and could be used as a 'spare element')
-_V_.TimeDivider = _V_.Component.extend({
-
- createElement: function(){
- return this._super("div", {
- className: "vjs-time-divider",
- innerHTML: '<div><span>/</span></div>'
- });
- }
-
-});
-
-_V_.RemainingTimeDisplay = _V_.Component.extend({
-
- init: function(player, options){
- this._super(player, options);
-
- player.addEvent("timeupdate", _V_.proxy(this, this.updateContent));
- },
-
- createElement: function(){
- var el = this._super("div", {
- className: "vjs-remaining-time vjs-time-controls vjs-control"
- });
-
- this.content = _V_.createElement("div", {
- className: "vjs-remaining-time-display",
- innerHTML: '-0:00'
- });
-
- el.appendChild(_V_.createElement("div").appendChild(this.content));
- return el;
- },
-
- updateContent: function(){
- if (this.player.duration()) { this.content.innerHTML = "-"+_V_.formatTime(this.player.remainingTime()); }
-
- // Allows for smooth scrubbing, when player can't keep up.
- // var time = (this.player.scrubbing) ? this.player.values.currentTime : this.player.currentTime();
- // this.content.innerHTML = _V_.formatTime(time, this.player.duration());
- }
-
-});
-
-/* Slider - Parent for seek bar and volume slider
-================================================================================ */
-_V_.Slider = _V_.Component.extend({
-
- init: function(player, options){
- this._super(player, options);
-
- player.addEvent(this.playerEvent, _V_.proxy(this, this.update));
-
- this.addEvent("mousedown", this.onMouseDown);
- this.addEvent("focus", this.onFocus);
- this.addEvent("blur", this.onBlur);
-
- this.player.addEvent("controlsvisible", this.proxy(this.update));
-
- // This is actually to fix the volume handle position. http://twitter.com/#!/gerritvanaaken/status/159046254519787520
- // this.player.one("timeupdate", this.proxy(this.update));
-
- this.update();
- },
-
- createElement: function(type, attrs) {
- attrs = _V_.merge({
- role: "slider",
- "aria-valuenow": 0,
- "aria-valuemin": 0,
- "aria-valuemax": 100,
- tabIndex: 0
- }, attrs);
-
- return this._super(type, attrs);
- },
-
- onMouseDown: function(event){
- event.preventDefault();
- _V_.blockTextSelection();
-
- _V_.addEvent(document, "mousemove", _V_.proxy(this, this.onMouseMove));
- _V_.addEvent(document, "mouseup", _V_.proxy(this, this.onMouseUp));
-
- this.onMouseMove(event);
- },
-
- onMouseUp: function(event) {
- _V_.unblockTextSelection();
- _V_.removeEvent(document, "mousemove", this.onMouseMove, false);
- _V_.removeEvent(document, "mouseup", this.onMouseUp, false);
-
- this.update();
- },
-
- update: function(){
- // If scrubbing, we could use a cached value to make the handle keep up with the user's mouse.
- // On HTML5 browsers scrubbing is really smooth, but some flash players are slow, so we might want to utilize this later.
- // var progress = (this.player.scrubbing) ? this.player.values.currentTime / this.player.duration() : this.player.currentTime() / this.player.duration();
-
- var barProgress,
- progress = this.getPercent();
- handle = this.handle,
- bar = this.bar;
-
- // Protect against no duration and other division issues
- if (isNaN(progress)) { progress = 0; }
-
- barProgress = progress;
-
- // If there is a handle, we need to account for the handle in our calculation for progress bar
- // so that it doesn't fall short of or extend past the handle.
- if (handle) {
-
- var box = this.el,
- boxWidth = box.offsetWidth,
-
- handleWidth = handle.el.offsetWidth,
-
- // The width of the handle in percent of the containing box
- // In IE, widths may not be ready yet causing NaN
- handlePercent = (handleWidth) ? handleWidth / boxWidth : 0,
-
- // Get the adjusted size of the box, considering that the handle's center never touches the left or right side.
- // There is a margin of half the handle's width on both sides.
- boxAdjustedPercent = 1 - handlePercent;
-
- // Adjust the progress that we'll use to set widths to the new adjusted box width
- adjustedProgress = progress * boxAdjustedPercent,
-
- // The bar does reach the left side, so we need to account for this in the bar's width
- barProgress = adjustedProgress + (handlePercent / 2);
-
- // Move the handle from the left based on the adjected progress
- handle.el.style.left = _V_.round(adjustedProgress * 100, 2) + "%";
- }
-
- // Set the new bar width
- bar.el.style.width = _V_.round(barProgress * 100, 2) + "%";
- },
-
- calculateDistance: function(event){
- var box = this.el,
- boxX = _V_.findPosX(box),
- boxW = box.offsetWidth,
- handle = this.handle;
-
- if (handle) {
- var handleW = handle.el.offsetWidth;
-
- // Adjusted X and Width, so handle doesn't go outside the bar
- boxX = boxX + (handleW / 2);
- boxW = boxW - handleW;
- }
-
- // Percent that the click is through the adjusted area
- return Math.max(0, Math.min(1, (event.pageX - boxX) / boxW));
- },
-
- onFocus: function(event){
- _V_.addEvent(document, "keyup", _V_.proxy(this, this.onKeyPress));
- },
-
- onKeyPress: function(event){
- if (event.which == 37) { // Left Arrow
- event.preventDefault();
- this.stepBack();
- } else if (event.which == 39) { // Right Arrow
- event.preventDefault();
- this.stepForward();
- }
- },
-
- onBlur: function(event){
- _V_.removeEvent(document, "keyup", _V_.proxy(this, this.onKeyPress));
- }
-});
-
-
-/* Progress
-================================================================================ */
-
-// Progress Control: Seek, Load Progress, and Play Progress
-_V_.ProgressControl = _V_.Component.extend({
-
- options: {
- components: {
- "seekBar": {}
- }
- },
-
- createElement: function(){
- return this._super("div", {
- className: "vjs-progress-control vjs-control"
- });
- }
-
-});
-
-// Seek Bar and holder for the progress bars
-_V_.SeekBar = _V_.Slider.extend({
-
- options: {
- components: {
- "loadProgressBar": {},
-
- // Set property names to bar and handle to match with the parent Slider class is looking for
- "bar": { componentClass: "PlayProgressBar" },
- "handle": { componentClass: "SeekHandle" }
- }
- },
-
- playerEvent: "timeupdate",
-
- init: function(player, options){
- this._super(player, options);
- },
-
- createElement: function(){
- return this._super("div", {
- className: "vjs-progress-holder"
- });
- },
-
- getPercent: function(){
- return this.player.currentTime() / this.player.duration();
- },
-
- onMouseDown: function(event){
- this._super(event);
-
- this.player.scrubbing = true;
-
- this.videoWasPlaying = !this.player.paused();
- this.player.pause();
- },
-
- onMouseMove: function(event){
- var newTime = this.calculateDistance(event) * this.player.duration();
-
- // Don't let video end while scrubbing.
- if (newTime == this.player.duration()) { newTime = newTime - 0.1; }
-
- // Set new time (tell player to seek to new time)
- this.player.currentTime(newTime);
- },
-
- onMouseUp: function(event){
- this._super(event);
-
- this.player.scrubbing = false;
- if (this.videoWasPlaying) {
- this.player.play();
- }
- },
-
- stepForward: function(){
- this.player.currentTime(this.player.currentTime() + 1);
- },
-
- stepBack: function(){
- this.player.currentTime(this.player.currentTime() - 1);
- }
-
-});
-
-// Load Progress Bar
-_V_.LoadProgressBar = _V_.Component.extend({
-
- init: function(player, options){
- this._super(player, options);
- player.addEvent("progress", _V_.proxy(this, this.update));
- },
-
- createElement: function(){
- return this._super("div", {
- className: "vjs-load-progress",
- innerHTML: '<span class="vjs-control-text">Loaded: 0%</span>'
- });
- },
-
- update: function(){
- if (this.el.style) { this.el.style.width = _V_.round(this.player.bufferedPercent() * 100, 2) + "%"; }
- }
-
-});
-
-// Play Progress Bar
-_V_.PlayProgressBar = _V_.Component.extend({
-
- createElement: function(){
- return this._super("div", {
- className: "vjs-play-progress",
- innerHTML: '<span class="vjs-control-text">Progress: 0%</span>'
- });
- }
-
-});
-
-// Seek Handle
-// SeekBar Behavior includes play progress bar, and seek handle
-// Needed so it can determine seek position based on handle position/size
-_V_.SeekHandle = _V_.Component.extend({
-
- createElement: function(){
- return this._super("div", {
- className: "vjs-seek-handle",
- innerHTML: '<span class="vjs-control-text">00:00</span>'
- });
- }
-
-});
-
-/* Volume Scrubber
-================================================================================ */
-// Progress Control: Seek, Load Progress, and Play Progress
-_V_.VolumeControl = _V_.Component.extend({
-
- options: {
- components: {
- "volumeBar": {}
- }
- },
-
- createElement: function(){
- return this._super("div", {
- className: "vjs-volume-control vjs-control"
- });
- }
-
-});
-
-_V_.VolumeBar = _V_.Slider.extend({
-
- options: {
- components: {
- "bar": { componentClass: "VolumeLevel" },
- "handle": { componentClass: "VolumeHandle" }
- }
- },
-
- playerEvent: "volumechange",
-
- createElement: function(){
- return this._super("div", {
- className: "vjs-volume-bar"
- });
- },
-
- onMouseMove: function(event) {
- this.player.volume(this.calculateDistance(event));
- },
-
- getPercent: function(){
- return this.player.volume();
- },
-
- stepForward: function(){
- this.player.volume(this.player.volume() + 0.1);
- },
-
- stepBack: function(){
- this.player.volume(this.player.volume() - 0.1);
- }
-});
-
-_V_.VolumeLevel = _V_.Component.extend({
-
- createElement: function(){
- return this._super("div", {
- className: "vjs-volume-level",
- innerHTML: '<span class="vjs-control-text"></span>'
- });
- }
-
-});
-
-_V_.VolumeHandle = _V_.Component.extend({
-
- createElement: function(){
- return this._super("div", {
- className: "vjs-volume-handle",
- innerHTML: '<span class="vjs-control-text"></span>'
- // tabindex: 0,
- // role: "slider", "aria-valuenow": 0, "aria-valuemin": 0, "aria-valuemax": 100
- });
- }
-
-});
-
-_V_.MuteToggle = _V_.Button.extend({
-
- init: function(player, options){
- this._super(player, options);
-
- player.addEvent("volumechange", _V_.proxy(this, this.update));
- },
-
- createElement: function(){
- return this._super("div", {
- className: "vjs-mute-control vjs-control",
- innerHTML: '<div><span class="vjs-control-text">Mute</span></div>'
- });
- },
-
- onClick: function(event){
- this.player.muted( this.player.muted() ? false : true );
- },
-
- update: function(event){
- var vol = this.player.volume(),
- level = 3;
-
- if (vol == 0 || this.player.muted()) {
- level = 0;
- } else if (vol < 0.33) {
- level = 1;
- } else if (vol < 0.67) {
- level = 2;
- }
-
- /* TODO improve muted icon classes */
- _V_.each.call(this, [0,1,2,3], function(i){
- _V_.removeClass(this.el, "vjs-vol-"+i);
- });
- _V_.addClass(this.el, "vjs-vol-"+level);
- }
-
-});
-
-
-/* Poster Image
-================================================================================ */
-_V_.Poster = _V_.Button.extend({
- init: function(player, options){
- this._super(player, options);
-
- if (!this.player.options.poster) {
- this.hide();
- }
-
- player.addEvent("play", _V_.proxy(this, this.hide));
- },
-
- createElement: function(){
- return _V_.createElement("img", {
- className: "vjs-poster",
- src: this.player.options.poster,
-
- // Don't want poster to be tabbable.
- tabIndex: -1
- });
- },
-
- onClick: function(){
- this.player.play();
- }
-});
-
-
-/* Text Track Displays
-================================================================================ */
-// Create a behavior type for each text track type (subtitlesDisplay, captionsDisplay, etc.).
-// Then you can easily do something like.
-// player.addBehavior(myDiv, "subtitlesDisplay");
-// And the myDiv's content will be updated with the text change.
-
-// Base class for all track displays. Should not be instantiated on its own.
-_V_.TextTrackDisplay = _V_.Component.extend({
-
- init: function(player, options){
- this._super(player, options);
-
- player.addEvent(this.trackType + "update", _V_.proxy(this, this.update));
- },
-
- createElement: function(){
- return this._super("div", {
- className: "vjs-" + this.trackType
- });
- },
-
- update: function(){
- this.el.innerHTML = this.player.textTrackValue(this.trackType);
- }
-
-});
-
-_V_.SubtitlesDisplay = _V_.TextTrackDisplay.extend({
-
- trackType: "subtitles"
-
-});
-
-_V_.CaptionsDisplay = _V_.TextTrackDisplay.extend({
-
- trackType: "captions"
-
-});
-
-_V_.ChaptersDisplay = _V_.TextTrackDisplay.extend({
-
- trackType: "chapters"
-
-});
-
-_V_.DescriptionsDisplay = _V_.TextTrackDisplay.extend({
-
- trackType: "descriptions"
-
-});// ECMA-262 is the standard for javascript.
-// The following methods are impelemented EXACTLY as described in the standard (according to Mozilla Docs), and do not override the default method if one exists.
-// This may conflict with other libraries that modify the array prototype, but those libs should update to use the standard.
-
-// [].indexOf
-// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
-if (!Array.prototype.indexOf) {
- Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
- "use strict";
- if (this === void 0 || this === null) {
- throw new TypeError();
- }
- var t = Object(this);
- var len = t.length >>> 0;
- if (len === 0) {
- return -1;
- }
- var n = 0;
- if (arguments.length > 0) {
- n = Number(arguments[1]);
- if (n !== n) { // shortcut for verifying if it's NaN
- n = 0;
- } else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) {
- n = (n > 0 || -1) * Math.floor(Math.abs(n));
- }
- }
- if (n >= len) {
- return -1;
- }
- var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
- for (; k < len; k++) {
- if (k in t && t[k] === searchElement) {
- return k;
- }
- }
- return -1;
- }
-}
-
-// NOT NEEDED YET
-// [].lastIndexOf
-// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf
-// if (!Array.prototype.lastIndexOf)
-// {
-// Array.prototype.lastIndexOf = function(searchElement /*, fromIndex*/)
-// {
-// "use strict";
-//
-// if (this === void 0 || this === null)
-// throw new TypeError();
-//
-// var t = Object(this);
-// var len = t.length >>> 0;
-// if (len === 0)
-// return -1;
-//
-// var n = len;
-// if (arguments.length > 1)
-// {
-// n = Number(arguments[1]);
-// if (n !== n)
-// n = 0;
-// else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0))
-// n = (n > 0 || -1) * Math.floor(Math.abs(n));
-// }
-//
-// var k = n >= 0
-// ? Math.min(n, len - 1)
-// : len - Math.abs(n);
-//
-// for (; k >= 0; k--)
-// {
-// if (k in t && t[k] === searchElement)
-// return k;
-// }
-// return -1;
-// };
-// }
-
-
-// NOT NEEDED YET
-// Array forEach per ECMA standard https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/foreach
-// Production steps of ECMA-262, Edition 5, 15.4.4.18
-// Reference: http://es5.github.com/#x15.4.4.18
-// if ( !Array.prototype.forEach ) {
-//
-// Array.prototype.forEach = function( callback, thisArg ) {
-//
-// var T, k;
-//
-// if ( this == null ) {
-// throw new TypeError( " this is null or not defined" );
-// }
-//
-// // 1. Let O be the result of calling ToObject passing the |this| value as the argument.
-// var O = Object(this);
-//
-// // 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
-// // 3. Let len be ToUint32(lenValue).
-// var len = O.length >>> 0;
-//
-// // 4. If IsCallable(callback) is false, throw a TypeError exception.
-// // See: http://es5.github.com/#x9.11
-// if ( {}.toString.call(callback) != "[object Function]" ) {
-// throw new TypeError( callback + " is not a function" );
-// }
-//
-// // 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
-// if ( thisArg ) {
-// T = thisArg;
-// }
-//
-// // 6. Let k be 0
-// k = 0;
-//
-// // 7. Repeat, while k < len
-// while( k < len ) {
-//
-// var kValue;
-//
-// // a. Let Pk be ToString(k).
-// // This is implicit for LHS operands of the in operator
-// // b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk.
-// // This step can be combined with c
-// // c. If kPresent is true, then
-// if ( k in O ) {
-//
-// // i. Let kValue be the result of calling the Get internal method of O with argument Pk.
-// kValue = O[ Pk ];
-//
-// // ii. Call the Call internal method of callback with T as the this value and
-// // argument list containing kValue, k, and O.
-// callback.call( T, kValue, k, O );
-// }
-// // d. Increase k by 1.
-// k++;
-// }
-// // 8. return undefined
-// };
-// }
-
-
-// NOT NEEDED YET
-// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/map
-// Production steps of ECMA-262, Edition 5, 15.4.4.19
-// Reference: http://es5.github.com/#x15.4.4.19
-// if (!Array.prototype.map) {
-// Array.prototype.map = function(callback, thisArg) {
-//
-// var T, A, k;
-//
-// if (this == null) {
-// throw new TypeError(" this is null or not defined");
-// }
-//
-// // 1. Let O be the result of calling ToObject passing the |this| value as the argument.
-// var O = Object(this);
-//
-// // 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
-// // 3. Let len be ToUint32(lenValue).
-// var len = O.length >>> 0;
-//
-// // 4. If IsCallable(callback) is false, throw a TypeError exception.
-// // See: http://es5.github.com/#x9.11
-// if ({}.toString.call(callback) != "[object Function]") {
-// throw new TypeError(callback + " is not a function");
-// }
-//
-// // 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
-// if (thisArg) {
-// T = thisArg;
-// }
-//
-// // 6. Let A be a new array created as if by the expression new Array(len) where Array is
-// // the standard built-in constructor with that name and len is the value of len.
-// A = new Array(len);
-//
-// // 7. Let k be 0
-// k = 0;
-//
-// // 8. Repeat, while k < len
-// while(k < len) {
-//
-// var kValue, mappedValue;
-//
-// // a. Let Pk be ToString(k).
-// // This is implicit for LHS operands of the in operator
-// // b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk.
-// // This step can be combined with c
-// // c. If kPresent is true, then
-// if (k in O) {
-//
-// // i. Let kValue be the result of calling the Get internal method of O with argument Pk.
-// kValue = O[ k ];
-//
-// // ii. Let mappedValue be the result of calling the Call internal method of callback
-// // with T as the this value and argument list containing kValue, k, and O.
-// mappedValue = callback.call(T, kValue, k, O);
-//
-// // iii. Call the DefineOwnProperty internal method of A with arguments
-// // Pk, Property Descriptor {Value: mappedValue, Writable: true, Enumerable: true, Configurable: true},
-// // and false.
-//
-// // In browsers that support Object.defineProperty, use the following:
-// // Object.defineProperty(A, Pk, { value: mappedValue, writable: true, enumerable: true, configurable: true });
-//
-// // For best browser support, use the following:
-// A[ k ] = mappedValue;
-// }
-// // d. Increase k by 1.
-// k++;
-// }
-//
-// // 9. return A
-// return A;
-// };
-// }
-// Event System (J.Resig - Secrets of a JS Ninja http://jsninja.com/ [Go read it, really])
-// (Book version isn't completely usable, so fixed some things and borrowed from jQuery where it's working)
-//
-// This should work very similarly to jQuery's events, however it's based off the book version which isn't as
-// robust as jquery's, so there's probably some differences.
-//
-// When you add an event listener using _V_.addEvent,
-// it stores the handler function in seperate cache object,
-// and adds a generic handler to the element's event,
-// along with a unique id (guid) to the element.
-
-_V_.extend({
-
- // Add an event listener to element
- // It stores the handler function in a separate cache object
- // and adds a generic handler to the element's event,
- // along with a unique id (guid) to the element.
- addEvent: function(elem, type, fn){
- var data = _V_.getData(elem), handlers;
-
- // We only need to generate one handler per element
- if (data && !data.handler) {
- // Our new meta-handler that fixes the event object and the context
- data.handler = function(event){
- event = _V_.fixEvent(event);
- var handlers = _V_.getData(elem).events[event.type];
- // Go through and call all the real bound handlers
- if (handlers) {
-
- // Copy handlers so if handlers are added/removed during the process it doesn't throw everything off.
- var handlersCopy = [];
- _V_.each(handlers, function(handler, i){
- handlersCopy[i] = handler;
- })
-
- for (var i = 0, l = handlersCopy.length; i < l; i++) {
- handlersCopy[i].call(elem, event);
- }
- }
- };
- }
-
- // We need a place to store all our event data
- if (!data.events) { data.events = {}; }
-
- // And a place to store the handlers for this event type
- handlers = data.events[type];
-
- if (!handlers) {
- handlers = data.events[ type ] = [];
-
- // Attach our meta-handler to the element, since one doesn't exist
- if (document.addEventListener) {
- elem.addEventListener(type, data.handler, false);
- } else if (document.attachEvent) {
- elem.attachEvent("on" + type, data.handler);
- }
- }
-
- if (!fn.guid) { fn.guid = _V_.guid++; }
-
- handlers.push(fn);
- },
-
- removeEvent: function(elem, type, fn) {
- var data = _V_.getData(elem), handlers;
- // If no events exist, nothing to unbind
- if (!data.events) { return; }
-
- // Are we removing all bound events?
- if (!type) {
- for (type in data.events) {
- _V_.cleanUpEvents(elem, type);
- }
- return;
- }
-
- // And a place to store the handlers for this event type
- handlers = data.events[type];
-
- // If no handlers exist, nothing to unbind
- if (!handlers) { return; }
-
- // See if we're only removing a single handler
- if (fn && fn.guid) {
- for (var i = 0; i < handlers.length; i++) {
- // We found a match (don't stop here, there could be a couple bound)
- if (handlers[i].guid === fn.guid) {
- // Remove the handler from the array of handlers
- handlers.splice(i--, 1);
- }
- }
- }
-
- _V_.cleanUpEvents(elem, type);
- },
-
- cleanUpEvents: function(elem, type) {
- var data = _V_.getData(elem);
- // Remove the events of a particular type if there are none left
-
- if (data.events[type].length === 0) {
- delete data.events[type];
-
- // Remove the meta-handler from the element
- if (document.removeEventListener) {
- elem.removeEventListener(type, data.handler, false);
- } else if (document.detachEvent) {
- elem.detachEvent("on" + type, data.handler);
- }
- }
-
- // Remove the events object if there are no types left
- if (_V_.isEmpty(data.events)) {
- delete data.events;
- delete data.handler;
- }
-
- // Finally remove the expando if there is no data left
- if (_V_.isEmpty(data)) {
- _V_.removeData(elem);
- }
- },
-
- fixEvent: function(event) {
- if (event[_V_.expando]) { return event; }
- // store a copy of the original event object
- // and "clone" to set read-only properties
- var originalEvent = event;
- event = new _V_.Event(originalEvent);
-
- for ( var i = _V_.Event.props.length, prop; i; ) {
- prop = _V_.Event.props[ --i ];
- event[prop] = originalEvent[prop];
- }
-
- // Fix target property, if necessary
- if (!event.target) { event.target = event.srcElement || document; }
-
- // check if target is a textnode (safari)
- if (event.target.nodeType === 3) { event.target = event.target.parentNode; }
-
- // Add relatedTarget, if necessary
- if (!event.relatedTarget && event.fromElement) {
- event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
- }
-
- // Calculate pageX/Y if missing and clientX/Y available
- if ( event.pageX == null && event.clientX != null ) {
- var eventDocument = event.target.ownerDocument || document,
- doc = eventDocument.documentElement,
- body = eventDocument.body;
-
- event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
- event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
- }
-
- // Add which for key events
- if (event.which == null && (event.charCode != null || event.keyCode != null)) {
- event.which = event.charCode != null ? event.charCode : event.keyCode;
- }
-
- // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
- if ( !event.metaKey && event.ctrlKey ) {
- event.metaKey = event.ctrlKey;
- }
-
- // Add which for click: 1 === left; 2 === middle; 3 === right
- // Note: button is not normalized, so don't use it
- if ( !event.which && event.button !== undefined ) {
- event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
- }
-
- return event;
- },
-
- triggerEvent: function(elem, event) {
- var data = _V_.getData(elem),
- parent = elem.parentNode || elem.ownerDocument,
- type = event.type || event,
- handler;
-
- if (data) { handler = data.handler }
-
- // Added in attion to book. Book code was broke.
- event = typeof event === "object" ?
- event[_V_.expando] ?
- event :
- new _V_.Event(type, event) :
- new _V_.Event(type);
-
- event.type = type;
- if (handler) {
- handler.call(elem, event);
- }
-
- // Clean up the event in case it is being reused
- event.result = undefined;
- event.target = elem;
-
- // Bubble the event up the tree to the document,
- // Unless it's been explicitly stopped
- // if (parent && !event.isPropagationStopped()) {
- // _V_.triggerEvent(parent, event);
- //
- // // We're at the top document so trigger the default action
- // } else if (!parent && !event.isDefaultPrevented()) {
- // // log(type);
- // var targetData = _V_.getData(event.target);
- // // log(targetData);
- // var targetHandler = targetData.handler;
- // // log("2");
- // if (event.target[event.type]) {
- // // Temporarily disable the bound handler,
- // // don't want to execute it twice
- // if (targetHandler) {
- // targetData.handler = function(){};
- // }
- //
- // // Trigger the native event (click, focus, blur)
- // event.target[event.type]();
- //
- // // Restore the handler
- // if (targetHandler) {
- // targetData.handler = targetHandler;
- // }
- // }
- // }
- },
-
- one: function(elem, type, fn) {
- _V_.addEvent(elem, type, function(){
- _V_.removeEvent(elem, type, arguments.callee)
- fn.apply(this, arguments);
- });
- }
-});
-
-// Custom Event object for standardizing event objects between browsers.
-_V_.Event = function(src, props){
- // Event object
- if (src && src.type) {
- this.originalEvent = src;
- this.type = src.type;
-
- // Events bubbling up the document may have been marked as prevented
- // by a handler lower down the tree; reflect the correct value.
- this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false ||
- src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;
-
- // Event type
- } else {
- this.type = src;
- }
-
- // Put explicitly provided properties onto the event object
- if (props) { _V_.merge(this, props); }
-
- this.timeStamp = (new Date).getTime();
-
- // Mark it as fixed
- this[_V_.expando] = true;
-};
-
-_V_.Event.prototype = {
- preventDefault: function() {
- this.isDefaultPrevented = returnTrue;
-
- var e = this.originalEvent;
- if (!e) { return; }
-
- // if preventDefault exists run it on the original event
- if (e.preventDefault) {
- e.preventDefault();
- // otherwise set the returnValue property of the original event to false (IE)
- } else {
- e.returnValue = false;
- }
- },
- stopPropagation: function() {
- this.isPropagationStopped = returnTrue;
-
- var e = this.originalEvent;
- if (!e) { return; }
- // if stopPropagation exists run it on the original event
- if (e.stopPropagation) { e.stopPropagation(); }
- // otherwise set the cancelBubble property of the original event to true (IE)
- e.cancelBubble = true;
- },
- stopImmediatePropagation: function() {
- this.isImmediatePropagationStopped = returnTrue;
- this.stopPropagation();
- },
- isDefaultPrevented: returnFalse,
- isPropagationStopped: returnFalse,
- isImmediatePropagationStopped: returnFalse
-};
-_V_.Event.props = "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" ");
-
-function returnTrue(){ return true; }
-function returnFalse(){ return false; }
-
-// Javascript JSON implementation
-// (Parse Method Only)
-// https://github.com/douglascrockford/JSON-js/blob/master/json2.js
-
-var JSON;
-if (!JSON) { JSON = {}; }
-
-(function(){
- var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
-
- if (typeof JSON.parse !== 'function') {
- JSON.parse = function (text, reviver) {
- var j;
-
- function walk(holder, key) {
- var k, v, value = holder[key];
- if (value && typeof value === 'object') {
- for (k in value) {
- if (Object.prototype.hasOwnProperty.call(value, k)) {
- v = walk(value, k);
- if (v !== undefined) {
- value[k] = v;
- } else {
- delete value[k];
- }
- }
- }
- }
- return reviver.call(holder, key, value);
- }
- text = String(text);
- cx.lastIndex = 0;
- if (cx.test(text)) {
- text = text.replace(cx, function (a) {
- return '\\u' +
- ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
- });
- }
-
- if (/^[\],:{}\s]*$/
- .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
- .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
- .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
-
- j = eval('(' + text + ')');
-
- return typeof reviver === 'function' ?
- walk({'': j}, '') : j;
- }
-
- throw new SyntaxError('JSON.parse');
- };
- }
-}());
-/* UI Component- Base class for all UI objects
-================================================================================ */
-_V_.Player = _V_.Component.extend({
-
- init: function(tag, addOptions, ready){
-
- this.tag = tag; // Store the original tag used to set options
-
- var el = this.el = _V_.createElement("div"), // Div to contain video and controls
- options = this.options = {},
- width = options.width = tag.getAttribute('width'),
- height = options.height = tag.getAttribute('height'),
-
- // Browsers default to 300x150 if there's no width/height or video size data.
- initWidth = width || 300,
- initHeight = height || 150;
-
- // Make player findable on elements
- tag.player = el.player = this;
-
- // Add callback to ready queue
- this.ready(ready);
-
- // Wrap video tag in div (el/box) container
- tag.parentNode.insertBefore(el, tag);
- el.appendChild(tag); // Breaks iPhone, fixed in HTML5 setup.
-
- // Give video tag properties to box
- el.id = this.id = tag.id; // ID will now reference box, not the video tag
- el.className = tag.className;
- // Update tag id/class for use as HTML5 playback tech
- tag.id += "_html5_api";
- tag.className = "vjs-tech";
-
- // Make player easily findable by ID
- _V_.players[el.id] = this;
-
- // Make box use width/height of tag, or default 300x150
- el.setAttribute("width", initWidth);
- el.setAttribute("height", initHeight);
- // Enforce with CSS since width/height attrs don't work on divs
- el.style.width = initWidth+"px";
- el.style.height = initHeight+"px";
- // Remove width/height attrs from tag so CSS can make it 100% width/height
- tag.removeAttribute("width");
- tag.removeAttribute("height");
-
- // Set Options
- _V_.merge(options, _V_.options); // Copy Global Defaults
- _V_.merge(options, this.getVideoTagSettings()); // Override with Video Tag Options
- _V_.merge(options, addOptions); // Override/extend with options from setup call
-
- // Store controls setting, and then remove immediately so native controls don't flash.
- tag.removeAttribute("controls");
-
- // Poster will be handled by a manual <img>
- tag.removeAttribute("poster");
-
- // Empty video tag sources and tracks so the built in player doesn't use them also.
- if (tag.hasChildNodes()) {
- for (var i=0,j=tag.childNodes;i<j.length;i++) {
- if (j[i].nodeName == "SOURCE" || j[i].nodeName == "TRACK") {
- tag.removeChild(j[i]);
- }
- }
- }
-
- // Holder for playback tech components
- this.techs = {};
-
- // Cache for video property values.
- this.values = {};
-
- this.addClass("vjs-paused");
-
- this.addEvent("ended", this.onEnded);
- this.addEvent("play", this.onPlay);
- this.addEvent("pause", this.onPause);
- this.addEvent("error", this.onError);
-
- // When the API is ready, loop through the components and add to the player.
- if (options.controls) {
- this.ready(function(){
- this.initComponents();
- });
- }
-
- // If there are no sources when the player is initialized,
- // load the first supported playback technology.
- if (!options.sources || options.sources.length == 0) {
- for (var i=0,j=options.techOrder; i<j.length; i++) {
- var techName = j[i],
- tech = _V_[techName];
-
- // Check if the browser supports this technology
- if (tech.isSupported()) {
- this.loadTech(techName);
- break;
- }
- }
- } else {
- // Loop through playback technologies (HTML5, Flash) and check for support
- // Then load the best source.
- this.src(options.sources);
- }
- },
-
- // Cache for video property values.
- values: {},
-
- destroy: function(){
- // Ensure that tracking progress and time progress will stop and plater deleted
- this.stopTrackingProgress();
- this.stopTrackingCurrentTime();
- delete _V_.players[this.id]
- },
-
- createElement: function(type, options){
-
- },
-
- getVideoTagSettings: function(){
- var options = {
- sources: [],
- tracks: []
- };
-
- options.src = this.tag.getAttribute("src");
- options.controls = this.tag.getAttribute("controls") !== null;
- options.poster = this.tag.getAttribute("poster");
- options.preload = this.tag.getAttribute("preload");
- options.autoplay = this.tag.getAttribute("autoplay") !== null; // hasAttribute not IE <8 compatible
- options.loop = this.tag.getAttribute("loop") !== null;
- options.muted = this.tag.getAttribute("muted") !== null;
-
- if (this.tag.hasChildNodes()) {
- for (var c,i=0,j=this.tag.childNodes;i<j.length;i++) {
- c = j[i];
- if (c.nodeName == "SOURCE") {
- options.sources.push({
- src: c.getAttribute('src'),
- type: c.getAttribute('type'),
- media: c.getAttribute('media'),
- title: c.getAttribute('title')
- });
- }
- if (c.nodeName == "TRACK") {
- options.tracks.push(new _V_.Track({
- src: c.getAttribute("src"),
- kind: c.getAttribute("kind"),
- srclang: c.getAttribute("srclang"),
- label: c.getAttribute("label"),
- 'default': c.getAttribute("default") !== null,
- title: c.getAttribute("title")
- }, this));
-
- }
- }
- }
- return options;
- },
-
- /* PLayback Technology (tech)
- ================================================================================ */
- // Load/Create an instance of playback technlogy including element and API methods
- // And append playback element in player div.
- loadTech: function(techName, source){
-
- // Pause and remove current playback technology
- if (this.tech) {
- this.unloadTech();
-
- // If the first time loading, HTML5 tag will exist but won't be initialized
- // So we need to remove it if we're not loading HTML5
- } else if (techName != "html5" && this.tag) {
- this.el.removeChild(this.tag);
- this.tag = false;
- }
-
- this.techName = techName;
-
- // Turn off API access because we're loading a new tech that might load asynchronously
- this.isReady = false;
-
- var techReady = function(){
- this.player.triggerReady();
-
- // Manually track progress in cases where the browser/flash player doesn't report it.
- if (!this.support.progressEvent) {
- this.player.manualProgressOn();
- }
-
- // Manually track timeudpates in cases where the browser/flash player doesn't report it.
- if (!this.support.timeupdateEvent) {
- this.player.manualTimeUpdatesOn();
- }
- }
-
- // Grab tech-specific options from player options and add source and parent element to use.
- var techOptions = _V_.merge({ source: source, parentEl: this.el }, this.options[techName])
-
- if (source) {
- if (source.src == this.values.src && this.values.currentTime > 0) {
- techOptions.startTime = this.values.currentTime;
- }
-
- this.values.src = source.src;
- }
-
- // Initialize tech instance
- this.tech = new _V_[techName](this, techOptions);
- this.tech.ready(techReady);
- },
-
- unloadTech: function(){
- this.tech.destroy();
-
- // Turn off any manual progress or timeupdate tracking
- if (this.manualProgress) { this.manualProgressOff(); }
-
- if (this.manualTimeUpdates) { this.manualTimeUpdatesOff(); }
-
- this.tech = false;
- },
-
- // There's many issues around changing the size of a Flash (or other plugin) object.
- // First is a plugin reload issue in Firefox that has been around for 11 years: https://bugzilla.mozilla.org/show_bug.cgi?id=90268
- // Then with the new fullscreen API, Mozilla and webkit browsers will reload the flash object after going to fullscreen.
- // To get around this, we're unloading the tech, caching source and currentTime values, and reloading the tech once the plugin is resized.
- // reloadTech: function(betweenFn){
- // _V_.log("unloadingTech")
- // this.unloadTech();
- // _V_.log("unloadedTech")
- // if (betweenFn) { betweenFn.call(); }
- // _V_.log("LoadingTech")
- // this.loadTech(this.techName, { src: this.values.src })
- // _V_.log("loadedTech")
- // },
-
- /* Fallbacks for unsupported event types
- ================================================================================ */
- // Manually trigger progress events based on changes to the buffered amount
- // Many flash players and older HTML5 browsers don't send progress or progress-like events
- manualProgressOn: function(){
- this.manualProgress = true;
-
- // Trigger progress watching when a source begins loading
- this.trackProgress();
-
- // Watch for a native progress event call on the tech element
- // In HTML5, some older versions don't support the progress event
- // So we're assuming they don't, and turning off manual progress if they do.
- this.tech.addEvent("progress", function(){
-
- // Remove this listener from the element
- this.removeEvent("progress", arguments.callee);
-
- // Update known progress support for this playback technology
- this.support.progressEvent = true;
-
- // Turn off manual progress tracking
- this.player.manualProgressOff();
- });
- },
-
- manualProgressOff: function(){
- this.manualProgress = false;
- this.stopTrackingProgress();
- },
-
- trackProgress: function(){
- this.progressInterval = setInterval(_V_.proxy(this, function(){
- // Don't trigger unless buffered amount is greater than last time
- // log(this.values.bufferEnd, this.buffered().end(0), this.duration())
- /* TODO: update for multiple buffered regions */
- if (this.values.bufferEnd < this.buffered().end(0)) {
- this.triggerEvent("progress");
- } else if (this.bufferedPercent() == 1) {
- this.stopTrackingProgress();
- this.triggerEvent("progress"); // Last update
- }
- }), 500);
- },
- stopTrackingProgress: function(){ clearInterval(this.progressInterval); },
-
- /* Time Tracking -------------------------------------------------------------- */
- manualTimeUpdatesOn: function(){
- this.manualTimeUpdates = true;
-
- this.addEvent("play", this.trackCurrentTime);
- this.addEvent("pause", this.stopTrackingCurrentTime);
- // timeupdate is also called by .currentTime whenever current time is set
-
- // Watch for native timeupdate event
- this.tech.addEvent("timeupdate", function(){
-
- // Remove this listener from the element
- this.removeEvent("timeupdate", arguments.callee);
-
- // Update known progress support for this playback technology
- this.support.timeupdateEvent = true;
-
- // Turn off manual progress tracking
- this.player.manualTimeUpdatesOff();
- });
- },
-
- manualTimeUpdatesOff: function(){
- this.manualTimeUpdates = false;
- this.stopTrackingCurrentTime();
- this.removeEvent("play", this.trackCurrentTime);
- this.removeEvent("pause", this.stopTrackingCurrentTime);
- },
-
- trackCurrentTime: function(){
- if (this.currentTimeInterval) { this.stopTrackingCurrentTime(); }
- this.currentTimeInterval = setInterval(_V_.proxy(this, function(){
- this.triggerEvent("timeupdate");
- }), 250); // 42 = 24 fps // 250 is what Webkit uses // FF uses 15
- },
-
- // Turn off play progress tracking (when paused or dragging)
- stopTrackingCurrentTime: function(){ clearInterval(this.currentTimeInterval); },
-
- /* Player event handlers (how the player reacts to certain events)
- ================================================================================ */
- onEnded: function(){
- if (this.options.loop) {
- this.currentTime(0);
- this.play();
- } else {
- this.pause();
- this.currentTime(0);
- this.pause();
- }
- },
-
- onPlay: function(){
- _V_.removeClass(this.el, "vjs-paused");
- _V_.addClass(this.el, "vjs-playing");
- },
-
- onPause: function(){
- _V_.removeClass(this.el, "vjs-playing");
- _V_.addClass(this.el, "vjs-paused");
- },
-
- onError: function(e) {
- _V_.log("Video Error", e);
- },
-
-/* Player API
-================================================================================ */
-
- apiCall: function(method, arg){
- if (this.isReady) {
- return this.tech[method](arg);
- } else {
- _V_.log("The playback technology API is not ready yet. Use player.ready(myFunction)."+" ["+method+"]", arguments.callee.caller.arguments.callee.caller.arguments.callee.caller)
- return false;
- // throw new Error("The playback technology API is not ready yet. Use player.ready(myFunction)."+" ["+method+"]");
- }
- },
-
- play: function(){
- this.apiCall("play"); return this;
- },
- pause: function(){
- this.apiCall("pause"); return this;
- },
- paused: function(){
- return this.apiCall("paused");
- },
-
- currentTime: function(seconds){
- if (seconds !== undefined) {
-
- // Cache the last set value for smoother scrubbing.
- this.values.lastSetCurrentTime = seconds;
-
- this.apiCall("setCurrentTime", seconds);
-
- if (this.manualTimeUpdates) {
- this.triggerEvent("timeupdate");
- }
- return this;
- }
-
- // Cache last currentTime and return
- return this.values.currentTime = this.apiCall("currentTime");
- },
- duration: function(){
- return this.apiCall("duration");
- },
- remainingTime: function(){
- return this.duration() - this.currentTime();
- },
-
- buffered: function(){
- var buffered = this.apiCall("buffered"),
- start = 0, end = this.values.bufferEnd = this.values.bufferEnd || 0,
- timeRange;
-
- if (buffered && buffered.length > 0 && buffered.end(0) !== end) {
- end = buffered.end(0);
- // Storing values allows them be overridden by setBufferedFromProgress
- this.values.bufferEnd = end;
- }
-
- return _V_.createTimeRange(start, end);
- },
-
- // Calculates amount of buffer is full
- bufferedPercent: function(){
- return (this.duration()) ? this.buffered().end(0) / this.duration() : 0;
- },
-
- volume: function(percentAsDecimal){
- if (percentAsDecimal !== undefined) {
- var vol = Math.max(0, Math.min(1, parseFloat(percentAsDecimal))); // Force value to between 0 and 1
- this.values.volume = vol;
- this.apiCall("setVolume", vol);
- _V_.setLocalStorage("volume", vol);
- return this;
- }
- // if (this.values.volume) { return this.values.volume; }
- return this.apiCall("volume");
- },
- muted: function(muted){
- if (muted !== undefined) {
- this.apiCall("setMuted", muted);
- return this;
- }
- return this.apiCall("muted");
- },
-
- width: function(width, skipListeners){
- if (width !== undefined) {
- this.el.width = width;
- this.el.style.width = width+"px";
- if (!skipListeners) { this.triggerEvent("resize"); }
- return this;
- }
- return parseInt(this.el.getAttribute("width"));
- },
- height: function(height){
- if (height !== undefined) {
- this.el.height = height;
- this.el.style.height = height+"px";
- this.triggerEvent("resize");
- return this;
- }
- return parseInt(this.el.getAttribute("height"));
- },
- size: function(width, height){
- // Skip resize listeners on width for optimization
- return this.width(width, true).height(height);
- },
-
- supportsFullScreen: function(){ return this.apiCall("supportsFullScreen"); },
-
- // Turn on fullscreen (or window) mode
- requestFullScreen: function(){
- var requestFullScreen = _V_.support.requestFullScreen;
-
- this.isFullScreen = true;
-
- // Check for browser element fullscreen support
- if (requestFullScreen) {
-
- // Flash and other plugins get reloaded when you take their parent to fullscreen.
- // To fix that we'll remove the tech, and reload it after the resize has finished.
- if (this.tech.support.fullscreenResize === false && this.options.flash.iFrameMode != true) {
-
- this.pause();
- this.unloadTech();
-
- _V_.addEvent(document, requestFullScreen.eventName, this.proxy(function(){
- _V_.removeEvent(document, requestFullScreen.eventName, arguments.callee);
- this.loadTech(this.techName, { src: this.values.src });
- }));
-
- this.el[requestFullScreen.requestFn]();
-
- } else {
- this.el[requestFullScreen.requestFn]();
- }
-
- // In case the user presses escape to exit fullscreen, we need to update fullscreen status
- _V_.addEvent(document, requestFullScreen.eventName, this.proxy(function(){
- this.isFullScreen = document[requestFullScreen.isFullScreen];
- }));
-
- } else if (this.tech.supportsFullScreen()) {
- this.apiCall("enterFullScreen");
-
- } else {
- this.enterFullWindow();
- }
-
- this.triggerEvent("fullscreenchange");
-
- return this;
- },
-
- cancelFullScreen: function(){
- var requestFullScreen = _V_.support.requestFullScreen;
-
- // Check for browser element fullscreen support
- if (requestFullScreen) {
-
- // Flash and other plugins get reloaded when you take their parent to fullscreen.
- // To fix that we'll remove the tech, and reload it after the resize has finished.
- if (this.tech.support.fullscreenResize === false && this.options.flash.iFrameMode != true) {
-
- this.pause();
- this.unloadTech();
-
- _V_.addEvent(document, requestFullScreen.eventName, this.proxy(function(){
- _V_.removeEvent(document, requestFullScreen.eventName, arguments.callee);
- this.loadTech(this.techName, { src: this.values.src })
- }));
-
- document[requestFullScreen.cancelFn]();
-
- } else {
- document[requestFullScreen.cancelFn]();
- }
-
- } else if (this.tech.supportsFullScreen()) {
- this.apiCall("exitFullScreen");
-
- } else {
- this.exitFullWindow();
- }
-
- this.isFullScreen = false;
- this.triggerEvent("fullscreenchange");
-
- return this;
- },
-
- enterFullWindow: function(){
- this.isFullWindow = true;
-
- // Storing original doc overflow value to return to when fullscreen is off
- this.docOrigOverflow = document.documentElement.style.overflow;
-
- // Add listener for esc key to exit fullscreen
- _V_.addEvent(document, "keydown", _V_.proxy(this, this.fullWindowOnEscKey));
-
- // Hide any scroll bars
- document.documentElement.style.overflow = 'hidden';
-
- // Apply fullscreen styles
- _V_.addClass(document.body, "vjs-full-window");
- _V_.addClass(this.el, "vjs-fullscreen");
-
- this.triggerEvent("enterFullWindow");
- },
-
- fullWindowOnEscKey: function(event){
- if (event.keyCode == 27) {
- if (this.isFullScreen == true) {
- this.cancelFullScreen();
- } else {
- this.exitFullWindow();
- }
- }
- },
-
- exitFullWindow: function(){
- this.isFullWindow = false;
- _V_.removeEvent(document, "keydown", this.fullWindowOnEscKey);
-
- // Unhide scroll bars.
- document.documentElement.style.overflow = this.docOrigOverflow;
-
- // Remove fullscreen styles
- _V_.removeClass(document.body, "vjs-full-window");
- _V_.removeClass(this.el, "vjs-fullscreen");
-
- // Resize the box, controller, and poster to original sizes
- // this.positionAll();
- this.triggerEvent("exitFullWindow");
- },
-
- // src is a pretty powerful function
- // If you pass it an array of source objects, it will find the best source to play and use that object.src
- // If the new source requires a new playback technology, it will switch to that.
- // If you pass it an object, it will set the source to object.src
- // If you pass it anything else (url string) it will set the video source to that
- src: function(source){
- // Case: Array of source objects to choose from and pick the best to play
- if (source instanceof Array) {
-
- var sources = source;
-
- techLoop: // Named loop for breaking both loops
- // Loop through each playback technology in the options order
- for (var i=0,j=this.options.techOrder;i<j.length;i++) {
- var techName = j[i],
- tech = _V_[techName];
- // tech = _V_.tech[techName];
-
- // Check if the browser supports this technology
- if (tech.isSupported()) {
-
- // Loop through each source object
- for (var a=0,b=sources;a<b.length;a++) {
- var source = b[a];
-
- // Check if source can be played with this technology
- if (tech.canPlaySource.call(this, source)) {
-
- // If this technology is already loaded, set source
- if (techName == this.techName) {
- this.src(source); // Passing the source object
-
- // Otherwise load this technology with chosen source
- } else {
- this.loadTech(techName, source);
- }
-
- break techLoop; // Break both loops
- }
- }
- }
- }
-
- // Case: Source object { src: "", type: "" ... }
- } else if (source instanceof Object) {
- if (_V_[this.techName].canPlaySource(source)) {
- this.src(source.src);
- } else {
- // Send through tech loop to check for a compatible technology.
- this.src([source]);
- }
- // Case: URL String (http://myvideo...)
- } else {
- // Cache for getting last set source
- this.values.src = source;
-
- if (!this.isReady) {
- this.ready(function(){
- this.src(source);
- });
- } else {
- this.apiCall("src", source);
- if (this.options.preload == "auto") {
- this.load();
- }
- if (this.options.autoplay) {
- this.play();
- }
- }
- }
- return this;
- },
-
- // Begin loading the src data
- load: function(){
- this.apiCall("load");
- return this;
- },
- currentSrc: function(){
- return this.apiCall("currentSrc");
- },
-
- textTrackValue: function(kind, value){
- if (value !== undefined) {
- this.values[kind] = value;
- this.triggerEvent(kind+"update");
- return this;
- }
- return this.values[kind];
- },
-
- // Attributes/Options
- preload: function(value){
- if (value !== undefined) {
- this.apiCall("setPreload", value);
- this.options.preload = value;
- return this;
- }
- return this.apiCall("preload", value);
- },
- autoplay: function(value){
- if (value !== undefined) {
- this.apiCall("setAutoplay", value);
- this.options.autoplay = value;
- return this;
- }
- return this.apiCall("autoplay", value);
- },
- loop: function(value){
- if (value !== undefined) {
- this.apiCall("setLoop", value);
- this.options.loop = value;
- return this;
- }
- return this.apiCall("loop", value);
- },
-
- controls: function(){ return this.options.controls; },
- textTracks: function(){ return this.options.tracks; },
- poster: function(){ return this.apiCall("poster"); },
-
- error: function(){ return this.apiCall("error"); },
- networkState: function(){ return this.apiCall("networkState"); },
- readyState: function(){ return this.apiCall("readyState"); },
- seeking: function(){ return this.apiCall("seeking"); },
- initialTime: function(){ return this.apiCall("initialTime"); },
- startOffsetTime: function(){ return this.apiCall("startOffsetTime"); },
- played: function(){ return this.apiCall("played"); },
- seekable: function(){ return this.apiCall("seekable"); },
- ended: function(){ return this.apiCall("ended"); },
- videoTracks: function(){ return this.apiCall("videoTracks"); },
- audioTracks: function(){ return this.apiCall("audioTracks"); },
- videoWidth: function(){ return this.apiCall("videoWidth"); },
- videoHeight: function(){ return this.apiCall("videoHeight"); },
- defaultPlaybackRate: function(){ return this.apiCall("defaultPlaybackRate"); },
- playbackRate: function(){ return this.apiCall("playbackRate"); },
- // mediaGroup: function(){ return this.apiCall("mediaGroup"); },
- // controller: function(){ return this.apiCall("controller"); },
- controls: function(){ return this.apiCall("controls"); },
- defaultMuted: function(){ return this.apiCall("defaultMuted"); }
-});
-
-// RequestFullscreen API
-(function(){
- var requestFn,
- cancelFn,
- eventName,
- isFullScreen,
- playerProto = _V_.Player.prototype;
-
- // Current W3C Spec
- // http://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html#api
- // Mozilla Draft: https://wiki.mozilla.org/Gecko:FullScreenAPI#fullscreenchange_event
- if (document.cancelFullscreen !== undefined) {
- requestFn = "requestFullscreen";
- cancelFn = "exitFullscreen";
- eventName = "fullscreenchange";
- isFullScreen = "fullScreen";
-
- // Webkit (Chrome/Safari) and Mozilla (Firefox) have working implementaitons
- // that use prefixes and vary slightly from the new W3C spec. Specifically, using 'exit' instead of 'cancel',
- // and lowercasing the 'S' in Fullscreen.
- // Other browsers don't have any hints of which version they might follow yet, so not going to try to predict by loopeing through all prefixes.
- } else {
-
- _V_.each(["moz", "webkit"], function(prefix){
-
- // https://github.com/zencoder/video-js/pull/128
- if ((prefix != "moz" || document.mozFullScreenEnabled) && document[prefix + "CancelFullScreen"] !== undefined) {
- requestFn = prefix + "RequestFullScreen";
- cancelFn = prefix + "CancelFullScreen";
- eventName = prefix + "fullscreenchange";
-
- if (prefix == "webkit") {
- isFullScreen = prefix + "IsFullScreen";
- } else {
- _V_.log("moz here")
- isFullScreen = prefix + "FullScreen";
- }
- }
-
- });
-
- }
-
- if (requestFn) {
- _V_.support.requestFullScreen = {
- requestFn: requestFn,
- cancelFn: cancelFn,
- eventName: eventName,
- isFullScreen: isFullScreen
- };
- }
-
-})();/* Playback Technology - Base class for playback technologies
-================================================================================ */
-_V_.PlaybackTech = _V_.Component.extend({
- init: function(player, options){
- // this._super(player, options);
-
- // Make playback element clickable
- // _V_.addEvent(this.el, "click", _V_.proxy(this, _V_.PlayToggle.prototype.onClick));
-
- // this.addEvent("click", this.proxy(this.onClick));
-
- // player.triggerEvent("techready");
- },
- // destroy: function(){},
- // createElement: function(){},
- onClick: function(){
- if (this.player.options.controls) {
- _V_.PlayToggle.prototype.onClick.call(this);
- }
- }
-});
-
-// Create placeholder methods for each that warn when a method isn't supported by the current playback technology
-_V_.apiMethods = "play,pause,paused,currentTime,setCurrentTime,duration,buffered,volume,setVolume,muted,setMuted,width,height,supportsFullScreen,enterFullScreen,src,load,currentSrc,preload,setPreload,autoplay,setAutoplay,loop,setLoop,error,networkState,readyState,seeking,initialTime,startOffsetTime,played,seekable,ended,videoTracks,audioTracks,videoWidth,videoHeight,textTracks,defaultPlaybackRate,playbackRate,mediaGroup,controller,controls,defaultMuted".split(",");
-_V_.each(_V_.apiMethods, function(methodName){
- _V_.PlaybackTech.prototype[methodName] = function(){
- throw new Error("The '"+method+"' method is not available on the playback technology's API");
- }
-});
-
-/* HTML5 Playback Technology - Wrapper for HTML5 Media API
-================================================================================ */
-_V_.html5 = _V_.PlaybackTech.extend({
-
- init: function(player, options, ready){
- this.player = player;
- this.el = this.createElement();
- this.ready(ready);
-
- this.addEvent("click", this.proxy(this.onClick));
-
- var source = options.source;
-
- // If the element source is already set, we may have missed the loadstart event, and want to trigger it.
- // We don't want to set the source again and interrupt playback.
- if (source && this.el.currentSrc == source.src) {
- player.triggerEvent("loadstart");
-
- // Otherwise set the source if one was provided.
- } else if (source) {
- this.el.src = source.src;
- }
-
- // Chrome and Safari both have issues with autoplay.
- // In Safari (5.1.1), when we move the video element into the container div, autoplay doesn't work.
- // In Chrome (15), if you have autoplay + a poster + no controls, the video gets hidden (but audio plays)
- // This fixes both issues. Need to wait for API, so it updates displays correctly
- player.ready(function(){
- if (this.options.autoplay && this.paused()) {
- this.tag.poster = null; // Chrome Fix. Fixed in Chrome v16.
- this.play();
- }
- });
-
- this.setupTriggers();
-
- this.triggerReady();
- },
-
- destroy: function(){
- this.player.tag = false;
- this.removeTriggers();
- this.el.parentNode.removeChild(this.el);
- },
-
- createElement: function(){
- var html5 = _V_.html5,
- player = this.player,
-
- // If possible, reuse original tag for HTML5 playback technology element
- el = player.tag,
- newEl;
-
- // Check if this browser supports moving the element into the box.
- // On the iPhone video will break if you move the element,
- // So we have to create a brand new element.
- if (!el || this.support.movingElementInDOM === false) {
-
- // If the original tag is still there, remove it.
- if (el) {
- player.el.removeChild(el);
- }
-
- newEl = _V_.createElement("video", {
- id: el.id || player.el.id + "_html5_api",
- className: el.className || "vjs-tech"
- });
-
- el = newEl;
- _V_.insertFirst(el, player.el);
- }
-
- // Update tag settings, in case they were overridden
- _V_.each(["autoplay","preload","loop","muted"], function(attr){ // ,"poster"
- el[attr] = player.options[attr];
- }, this);
-
- return el;
- },
-
- // Make video events trigger player events
- // May seem verbose here, but makes other APIs possible.
- setupTriggers: function(){
- _V_.each.call(this, _V_.html5.events, function(type){
- _V_.addEvent(this.el, type, _V_.proxy(this.player, this.eventHandler));
- });
- },
- removeTriggers: function(){
- _V_.each.call(this, _V_.html5.events, function(type){
- _V_.removeEvent(this.el, type, _V_.proxy(this.player, this.eventHandler));
- });
- },
- eventHandler: function(e){
- e.stopPropagation();
- this.triggerEvent(e);
- },
-
- play: function(){ this.el.play(); },
- pause: function(){ this.el.pause(); },
- paused: function(){ return this.el.paused; },
-
- currentTime: function(){ return this.el.currentTime; },
- setCurrentTime: function(seconds){
- try {
- this.el.currentTime = seconds;
- } catch(e) {
- _V_.log(e, "Video isn't ready. (VideoJS)");
- // this.warning(VideoJS.warnings.videoNotReady);
- }
- },
-
- duration: function(){ return this.el.duration || 0; },
- buffered: function(){ return this.el.buffered; },
-
- volume: function(){ return this.el.volume; },
- setVolume: function(percentAsDecimal){ this.el.volume = percentAsDecimal; },
- muted: function(){ return this.el.muted; },
- setMuted: function(muted){ this.el.muted = muted },
-
- width: function(){ return this.el.offsetWidth; },
- height: function(){ return this.el.offsetHeight; },
-
- supportsFullScreen: function(){
- if (typeof this.el.webkitEnterFullScreen == 'function') {
-
- // Seems to be broken in Chromium/Chrome && Safari in Leopard
- if (!navigator.userAgent.match("Chrome") && !navigator.userAgent.match("Mac OS X 10.5")) {
- return true;
- }
- }
- return false;
- },
-
- enterFullScreen: function(){
- try {
- this.el.webkitEnterFullScreen();
- } catch (e) {
- if (e.code == 11) {
- // this.warning(VideoJS.warnings.videoNotReady);
- _V_.log("VideoJS: Video not ready.")
- }
- }
- },
- src: function(src){ this.el.src = src; },
- load: function(){ this.el.load(); },
- currentSrc: function(){ return this.el.currentSrc; },
-
- preload: function(){ return this.el.preload; },
- setPreload: function(val){ this.el.preload = val; },
- autoplay: function(){ return this.el.autoplay; },
- setAutoplay: function(val){ this.el.autoplay = val; },
- loop: function(){ return this.el.loop; },
- setLoop: function(val){ this.el.loop = val; },
-
- error: function(){ return this.el.error; },
- // networkState: function(){ return this.el.networkState; },
- // readyState: function(){ return this.el.readyState; },
- seeking: function(){ return this.el.seeking; },
- // initialTime: function(){ return this.el.initialTime; },
- // startOffsetTime: function(){ return this.el.startOffsetTime; },
- // played: function(){ return this.el.played; },
- // seekable: function(){ return this.el.seekable; },
- ended: function(){ return this.el.ended; },
- // videoTracks: function(){ return this.el.videoTracks; },
- // audioTracks: function(){ return this.el.audioTracks; },
- // videoWidth: function(){ return this.el.videoWidth; },
- // videoHeight: function(){ return this.el.videoHeight; },
- // textTracks: function(){ return this.el.textTracks; },
- // defaultPlaybackRate: function(){ return this.el.defaultPlaybackRate; },
- // playbackRate: function(){ return this.el.playbackRate; },
- // mediaGroup: function(){ return this.el.mediaGroup; },
- // controller: function(){ return this.el.controller; },
- controls: function(){ return this.player.options.controls; },
- defaultMuted: function(){ return this.el.defaultMuted; }
-});
-
-/* HTML5 Support Testing -------------------------------------------------------- */
-
-_V_.html5.isSupported = function(){
- return !!document.createElement("video").canPlayType;
-};
-
-_V_.html5.canPlaySource = function(srcObj){
- return !!document.createElement("video").canPlayType(srcObj.type);
- // TODO: Check Type
- // If no Type, check ext
- // Check Media Type
-};
-
-// List of all HTML5 events (various uses).
-_V_.html5.events = "loadstart,suspend,abort,error,emptied,stalled,loadedmetadata,loadeddata,canplay,canplaythrough,playing,waiting,seeking,seeked,ended,durationchange,timeupdate,progress,play,pause,ratechange,volumechange".split(",");
-
-/* HTML5 Device Fixes ---------------------------------------------------------- */
-
-_V_.html5.prototype.support = {
-
- // Support for tech specific full screen. (webkitEnterFullScreen, not requestFullscreen)
- // http://developer.apple.com/library/safari/#documentation/AudioVideo/Reference/HTMLVideoElementClassReference/HTMLVideoElement/HTMLVideoElement.html
- // Seems to be broken in Chromium/Chrome && Safari in Leopard
- fullscreen: (typeof _V_.testVid.webkitEnterFullScreen !== undefined) ? (!_V_.ua.match("Chrome") && !_V_.ua.match("Mac OS X 10.5") ? true : false) : false,
-
- // In iOS, if you move a video element in the DOM, it breaks video playback.
- movingElementInDOM: !_V_.isIOS()
-
-};
-
-// Android
-if (_V_.isAndroid()) {
-
- // Override Android 2.2 and less canPlayType method which is broken
- if (_V_.androidVersion() < 3) {
- document.createElement("video").constructor.prototype.canPlayType = function(type){
- return (type && type.toLowerCase().indexOf("video/mp4") != -1) ? "maybe" : "";
- };
- }
-}
-
-
-/* VideoJS-SWF - Custom Flash Player with HTML5-ish API - https://github.com/zencoder/video-js-swf
-================================================================================ */
-_V_.flash = _V_.PlaybackTech.extend({
-
- init: function(player, options){
- this.player = player;
-
- var source = options.source,
-
- // Which element to embed in
- parentEl = options.parentEl,
-
- // Create a temporary element to be replaced by swf object
- placeHolder = this.el = _V_.createElement("div", { id: parentEl.id + "_temp_flash" }),
-
- // Generate ID for swf object
- objId = player.el.id+"_flash_api",
-
- // Store player options in local var for optimization
- playerOptions = player.options,
-
- // Merge default flashvars with ones passed in to init
- flashVars = _V_.merge({
-
- // SWF Callback Functions
- readyFunction: "_V_.flash.onReady",
- eventProxyFunction: "_V_.flash.onEvent",
- errorEventProxyFunction: "_V_.flash.onError",
-
- // Player Settings
- autoplay: playerOptions.autoplay,
- preload: playerOptions.preload,
- loop: playerOptions.loop,
- muted: playerOptions.muted
-
- }, options.flashVars),
-
- // Merge default parames with ones passed in
- params = _V_.merge({
- wmode: "opaque", // Opaque is needed to overlay controls, but can affect playback performance
- bgcolor: "#000000" // Using bgcolor prevents a white flash when the object is loading
- }, options.params),
-
- // Merge default attributes with ones passed in
- attributes = _V_.merge({
- id: objId,
- name: objId, // Both ID and Name needed or swf to identifty itself
- 'class': 'vjs-tech'
- }, options.attributes)
- ;
-
- // If source was supplied pass as a flash var.
- if (source) {
- flashVars.src = encodeURIComponent(source.src);
- }
-
- // Add placeholder to player div
- _V_.insertFirst(placeHolder, parentEl);
-
- // Having issues with Flash reloading on certain page actions (hide/resize/fullscreen) in certain browsers
- // This allows resetting the playhead when we catch the reload
- if (options.startTime) {
- this.ready(function(){
- this.load();
- this.play();
- this.currentTime(options.startTime);
- });
- }
-
- // Flash iFrame Mode
- // In web browsers there are multiple instances where changing the parent element or visibility of a plugin causes the plugin to reload.
- // - Firefox just about always. https://bugzilla.mozilla.org/show_bug.cgi?id=90268 (might be fixed by version 13)
- // - Webkit when hiding the plugin
- // - Webkit and Firefox when using requestFullScreen on a parent element
- // Loading the flash plugin into a dynamically generated iFrame gets around most of these issues.
- // Issues that remain include hiding the element and requestFullScreen in Firefox specifically
-
- // There's on particularly annoying issue with this method which is that Firefox throws a security error on an offsite Flash object loaded into a dynamically created iFrame.
- // Even though the iframe was inserted into a page on the web, Firefox + Flash considers it a local app trying to access an internet file.
- // I tried mulitple ways of setting the iframe src attribute but couldn't find a src that worked well. Tried a real/fake source, in/out of domain.
- // Also tried a method from stackoverflow that caused a security error in all browsers. http://stackoverflow.com/questions/2486901/how-to-set-document-domain-for-a-dynamically-generated-iframe
- // In the end the solution I found to work was setting the iframe window.location.href right before doing a document.write of the Flash object.
- // The only downside of this it seems to trigger another http request to the original page (no matter what's put in the href). Not sure why that is.
-
- // NOTE (2012-01-29): Cannot get Firefox to load the remote hosted SWF into a dynamically created iFrame
- // Firefox 9 throws a security error, unleess you call location.href right before doc.write.
- // Not sure why that even works, but it causes the browser to look like it's continuously trying to load the page.
- // Firefox 3.6 keeps calling the iframe onload function anytime I write to it, causing an endless loop.
-
- if (options.iFrameMode == true && !_V_.isFF) {
-
- // Create iFrame with vjs-tech class so it's 100% width/height
- var iFrm = _V_.createElement("iframe", {
- id: objId + "_iframe",
- name: objId + "_iframe",
- className: "vjs-tech",
- scrolling: "no",
- marginWidth: 0,
- marginHeight: 0,
- frameBorder: 0
- });
-
- // Update ready function names in flash vars for iframe window
- flashVars.readyFunction = "ready";
- flashVars.eventProxyFunction = "events";
- flashVars.errorEventProxyFunction = "errors";
-
- // Tried multiple methods to get this to work in all browsers
-
- // Tried embedding the flash object in the page first, and then adding a place holder to the iframe, then replacing the placeholder with the page object.
- // The goal here was to try to load the swf URL in the parent page first and hope that got around the firefox security error
- // var newObj = _V_.flash.embed(options.swf, placeHolder, flashVars, params, attributes);
- // (in onload)
- // var temp = _V_.createElement("a", { id:"asdf", innerHTML: "asdf" } );
- // iDoc.body.appendChild(temp);
-
- // Tried embedding the flash object through javascript in the iframe source.
- // This works in webkit but still triggers the firefox security error
- // iFrm.src = "javascript: document.write('"+_V_.flash.getEmbedCode(options.swf, flashVars, params, attributes)+"');";
-
- // Tried an actual local iframe just to make sure that works, but it kills the easiness of the CDN version if you require the user to host an iframe
- // We should add an option to host the iframe locally though, because it could help a lot of issues.
- // iFrm.src = "iframe.html";
-
- // Wait until iFrame has loaded to write into it.
- _V_.addEvent(iFrm, "load", _V_.proxy(this, function(){
-
- var iDoc, objTag, swfLoc,
- iWin = iFrm.contentWindow,
- varString = "";
-
-
- // The one working method I found was to use the iframe's document.write() to create the swf object
- // This got around the security issue in all browsers except firefox.
- // I did find a hack where if I call the iframe's window.location.href="", it would get around the security error
- // However, the main page would look like it was loading indefinitely (URL bar loading spinner would never stop)
- // Plus Firefox 3.6 didn't work no matter what I tried.
- // if (_V_.ua.match("Firefox")) {
- // iWin.location.href = "";
- // }
-
- // Get the iFrame's document depending on what the browser supports
- iDoc = iFrm.contentDocument ? iFrm.contentDocument : iFrm.contentWindow.document;
-
- // Tried ensuring both document domains were the same, but they already were, so that wasn't the issue.
- // Even tried adding /. that was mentioned in a browser security writeup
- // document.domain = document.domain+"/.";
- // iDoc.domain = document.domain+"/.";
-
- // Tried adding the object to the iframe doc's innerHTML. Security error in all browsers.
- // iDoc.body.innerHTML = swfObjectHTML;
-
- // Tried appending the object to the iframe doc's body. Security error in all browsers.
- // iDoc.body.appendChild(swfObject);
-
- // Using document.write actually got around the security error that browsers were throwing.
- // Again, it's a dynamically generated (same domain) iframe, loading an external Flash swf.
- // Not sure why that's a security issue, but apparently it is.
- iDoc.write(_V_.flash.getEmbedCode(options.swf, flashVars, params, attributes));
-
- // Setting variables on the window needs to come after the doc write because otherwise they can get reset in some browsers
- // So far no issues with swf ready event being called before it's set on the window.
- iWin.player = this.player;
-
- // Create swf ready function for iFrame window
- iWin.ready = _V_.proxy(this.player, function(currSwf){
- var el = iDoc.getElementById(currSwf),
- player = this,
- tech = player.tech;
-
- // Update reference to playback technology element
- tech.el = el;
-
- // Now that the element is ready, make a click on the swf play the video
- _V_.addEvent(el, "click", tech.proxy(tech.onClick));
-
- // Make sure swf is actually ready. Sometimes the API isn't actually yet.
- _V_.flash.checkReady(tech);
- });
-
- // Create event listener for all swf events
- iWin.events = _V_.proxy(this.player, function(swfID, eventName, other){
- var player = this;
- if (player && player.techName == "flash") {
- player.triggerEvent(eventName);
- }
- });
-
- // Create error listener for all swf errors
- iWin.errors = _V_.proxy(this.player, function(swfID, eventName){
- _V_.log("Flash Error", eventName);
- });
-
- }));
-
- // Replace placeholder with iFrame (it will load now)
- placeHolder.parentNode.replaceChild(iFrm, placeHolder);
-
- // If not using iFrame mode, embed as normal object
- } else {
- _V_.flash.embed(options.swf, placeHolder, flashVars, params, attributes);
- }
- },
-
- destroy: function(){
- this.el.parentNode.removeChild(this.el);
- },
-
- // setupTriggers: function(){}, // Using global onEvent func to distribute events
-
- play: function(){ this.el.vjs_play(); },
- pause: function(){ this.el.vjs_pause(); },
- src: function(src){
- this.el.vjs_src(src);
-
- // Currently the SWF doesn't autoplay if you load a source later.
- // e.g. Load player w/ no source, wait 2s, set src.
- if (this.player.autoplay) {
- var tech = this;
- setTimeout(function(){ tech.play(); }, 0);
- }
- },
- load: function(){ this.el.vjs_load(); },
- poster: function(){ this.el.vjs_getProperty("poster"); },
-
- buffered: function(){
- return _V_.createTimeRange(0, this.el.vjs_getProperty("buffered"));
- },
-
- supportsFullScreen: function(){
- return false; // Flash does not allow fullscreen through javascript
- },
- enterFullScreen: function(){
- return false;
- }
-});
-
-// Create setters and getters for attributes
-(function(){
-
- var api = _V_.flash.prototype,
- readWrite = "preload,currentTime,defaultPlaybackRate,playbackRate,autoplay,loop,mediaGroup,controller,controls,volume,muted,defaultMuted".split(","),
- readOnly = "error,currentSrc,networkState,readyState,seeking,initialTime,duration,startOffsetTime,paused,played,seekable,ended,videoTracks,audioTracks,videoWidth,videoHeight,textTracks".split(","),
- callOnly = "load,play,pause".split(",");
- // Overridden: buffered
-
- createSetter = function(attr){
- var attrUpper = attr.charAt(0).toUpperCase() + attr.slice(1);
- api["set"+attrUpper] = function(val){ return this.el.vjs_setProperty(attr, val); };
- },
-
- createGetter = function(attr){
- api[attr] = function(){ return this.el.vjs_getProperty(attr); };
- }
- ;
-
- // Create getter and setters for all read/write attributes
- _V_.each(readWrite, function(attr){
- createGetter(attr);
- createSetter(attr);
- });
-
- // Create getters for read-only attributes
- _V_.each(readOnly, function(attr){
- createGetter(attr);
- });
-
-})();
-
-/* Flash Support Testing -------------------------------------------------------- */
-
-_V_.flash.isSupported = function(){
- return _V_.flash.version()[0] >= 10;
- // return swfobject.hasFlashPlayerVersion("10");
-};
-
-_V_.flash.canPlaySource = function(srcObj){
- if (srcObj.type in _V_.flash.prototype.support.formats) { return "maybe"; }
-};
-
-_V_.flash.prototype.support = {
- formats: {
- "video/flv": "FLV",
- "video/x-flv": "FLV",
- "video/mp4": "MP4",
- "video/m4v": "MP4"
- },
-
- // Optional events that we can manually mimic with timers
- progressEvent: false,
- timeupdateEvent: false,
-
- // Resizing plugins using request fullscreen reloads the plugin
- fullscreenResize: false,
-
- // Resizing plugins in Firefox always reloads the plugin (e.g. full window mode)
- parentResize: !(_V_.ua.match("Firefox"))
-};
-
-_V_.flash.onReady = function(currSwf){
-
- var el = _V_.el(currSwf);
-
- // Get player from box
- // On firefox reloads, el might already have a player
- var player = el.player || el.parentNode.player,
- tech = player.tech;
-
- // Reference player on tech element
- el.player = player;
-
- // Update reference to playback technology element
- tech.el = el;
-
- // Now that the element is ready, make a click on the swf play the video
- tech.addEvent("click", tech.onClick);
-
- _V_.flash.checkReady(tech);
-};
-
-// The SWF isn't alwasy ready when it says it is. Sometimes the API functions still need to be added to the object.
-// If it's not ready, we set a timeout to check again shortly.
-_V_.flash.checkReady = function(tech){
-
- // Check if API property exists
- if (tech.el.vjs_getProperty) {
-
- // If so, tell tech it's ready
- tech.triggerReady();
-
- // Otherwise wait longer.
- } else {
-
- setTimeout(function(){
- _V_.flash.checkReady(tech);
- }, 50);
-
- }
-};
-
-// Trigger events from the swf on the player
-_V_.flash.onEvent = function(swfID, eventName){
- var player = _V_.el(swfID).player;
- player.triggerEvent(eventName);
-};
-
-// Log errors from the swf
-_V_.flash.onError = function(swfID, err){
- _V_.log("Flash Error", err, swfID);
-};
-
-// Flash Version Check
-_V_.flash.version = function(){
- var version = '0,0,0'
-
- // IE
- try {
- version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
-
- // other browsers
- } catch(e) {
- try {
- if (navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){
- version = (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g, ",").match(/^,?(.+),?$/)[1];
- }
- } catch(e) {}
- }
- return version.split(",");
-}
-
-// Flash embedding method. Only used in non-iframe mode
-_V_.flash.embed = function(swf, placeHolder, flashVars, params, attributes){
- var code = _V_.flash.getEmbedCode(swf, flashVars, params, attributes),
-
- // Get element by embedding code and retrieving created element
- obj = _V_.createElement("div", { innerHTML: code }).childNodes[0],
-
- par = placeHolder.parentNode
- ;
-
- placeHolder.parentNode.replaceChild(obj, placeHolder);
-
- // IE6 seems to have an issue where it won't initialize the swf object after injecting it.
- // This is a dumb temporary fix
- if (_V_.isIE()) {
- var newObj = par.childNodes[0];
- setTimeout(function(){
- newObj.style.display = "block";
- }, 1000);
- }
-
- return obj;
-
-};
-
-_V_.flash.getEmbedCode = function(swf, flashVars, params, attributes){
-
- var objTag = '<object type="application/x-shockwave-flash"',
- flashVarsString = '',
- paramsString = ''
- attrsString = '';
-
- // Convert flash vars to string
- if (flashVars) {
- _V_.eachProp(flashVars, function(key, val){
- flashVarsString += (key + "=" + val + "&amp;");
- });
- }
-
- // Add swf, flashVars, and other default params
- params = _V_.merge({
- movie: swf,
- flashvars: flashVarsString,
- allowScriptAccess: "always", // Required to talk to swf
- allowNetworking: "all" // All should be default, but having security issues.
- }, params);
-
- // Create param tags string
- _V_.eachProp(params, function(key, val){
- paramsString += '<param name="'+key+'" value="'+val+'" />';
- });
-
- attributes = _V_.merge({
- // Add swf to attributes (need both for IE and Others to work)
- data: swf,
-
- // Default to 100% width/height
- width: "100%",
- height: "100%"
-
- }, attributes);
-
- // Create Attributes string
- _V_.eachProp(attributes, function(key, val){
- attrsString += (key + '="' + val + '" ');
- });
-
- return objTag + attrsString + '>' + paramsString + '</object>';
-}
-_V_.Track = function(attributes, player){
- // Store reference to the parent player
- this.player = player;
-
- this.src = attributes.src;
- this.kind = attributes.kind;
- this.srclang = attributes.srclang;
- this.label = attributes.label;
- this["default"] = attributes["default"]; // 'default' is reserved-ish
- this.title = attributes.title;
-
- this.cues = [];
- this.currentCue = false;
- this.lastCueIndex = 0;
-
- // Update current cue on timeupdate
- player.addEvent("timeupdate", _V_.proxy(this, this.update));
-
- // Reset cue time on media end
- player.addEvent("ended", _V_.proxy(this, function() { this.lastCueIndex = 0; }));
-
- // Load Track File
- _V_.get(attributes.src, _V_.proxy(this, this.parseCues));
-};
-
-_V_.Track.prototype = {
-
- parseCues: function(srcContent) {
- var cue, time, text,
- lines = srcContent.split("\n"),
- line = "";
-
- for (var i=0; i<lines.length; i++) {
- line = _V_.trim(lines[i]); // Trim whitespace and linebreaks
- if (line) { // Loop until a line with content
-
- // First line - Number
- cue = {
- id: line, // Cue Number
- index: this.cues.length // Position in Array
- };
-
- // Second line - Time
- line = _V_.trim(lines[++i]);
- time = line.split(" --> ");
- cue.startTime = this.parseCueTime(time[0]);
- cue.endTime = this.parseCueTime(time[1]);
-
- // Additional lines - Cue Text
- text = [];
- for (var j=i; j<lines.length; j++) { // Loop until a blank line or end of lines
- line = _V_.trim(lines[++i]);
- if (!line) { break; }
- text.push(line);
- }
- cue.text = text.join('<br/>');
-
- // Add this cue
- this.cues.push(cue);
- }
- }
- },
-
- parseCueTime: function(timeText) {
- var parts = timeText.split(':'),
- time = 0;
- // hours => seconds
- time += parseFloat(parts[0])*60*60;
- // minutes => seconds
- time += parseFloat(parts[1])*60;
- // get seconds
- var seconds = parts[2].split(/\.|,/); // Either . or ,
- time += parseFloat(seconds[0]);
- // add miliseconds
- ms = parseFloat(seconds[1]);
- if (ms) { time += ms/1000; }
- return time;
- },
-
- update: function(){
- // Assuming all cues are in order by time, and do not overlap
- if (this.cues && this.cues.length > 0) {
- var time = this.player.currentTime();
- // If current cue should stay showing, don't do anything. Otherwise, find new cue.
- if (!this.currentCue || this.currentCue.startTime >= time || this.currentCue.endTime < time) {
- var newSubIndex = false,
- // Loop in reverse if lastCue is after current time (optimization)
- // Meaning the user is scrubbing in reverse or rewinding
- reverse = (this.cues[this.lastCueIndex].startTime > time),
- // If reverse, step back 1 becase we know it's not the lastCue
- i = this.lastCueIndex - (reverse ? 1 : 0);
- while (true) { // Loop until broken
- if (reverse) { // Looping in reverse
- // Stop if no more, or this cue ends before the current time (no earlier cues should apply)
- if (i < 0 || this.cues[i].endTime < time) { break; }
- // End is greater than time, so if start is less, show this cue
- if (this.cues[i].startTime < time) {
- newSubIndex = i;
- break;
- }
- i--;
- } else { // Looping forward
- // Stop if no more, or this cue starts after time (no later cues should apply)
- if (i >= this.cues.length || this.cues[i].startTime > time) { break; }
- // Start is less than time, so if end is later, show this cue
- if (this.cues[i].endTime > time) {
- newSubIndex = i;
- break;
- }
- i++;
- }
- }
-
- // Set or clear current cue
- if (newSubIndex !== false) {
- this.currentCue = this.cues[newSubIndex];
- this.lastCueIndex = newSubIndex;
- this.updatePlayer(this.currentCue.text);
- } else if (this.currentCue) {
- this.currentCue = false;
- this.updatePlayer("");
- }
- }
- }
- },
-
- // Update the stored value for the current track kind
- // and trigger an event to update all text track displays.
- updatePlayer: function(text){
- this.player.textTrackValue(this.kind, text);
- }
-};
-_V_.addEvent(window, "load", function(){
- _V_.windowLoaded = true;
-});
-
-// Run Auto-load players
-_V_.autoSetup();
-// Expose to global
-window.VideoJS = window._V_ = VideoJS;
-
-// End self-executing function
-})(window);
diff --git a/extlib/video-js/video.min.js b/extlib/video-js/video.min.js
index 026a0126..1c33af55 100644
--- a/extlib/video-js/video.min.js
+++ b/extlib/video-js/video.min.js
@@ -1,6 +1,6 @@
/*!
Video.js - HTML5 Video Player
-Version 3.1.0
+Version GENERATED_AT_BUILD
LGPL v3 LICENSE INFO
This file is part of Video.js. Copyright 2011 Zencoder, Inc.
@@ -18,4 +18,4 @@ GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Video.js. If not, see <http://www.gnu.org/licenses/>.
*/
-(function(window,undefined){var document=window.document;document.createElement("video");document.createElement("audio");var VideoJS=function(id,addOptions,ready){var tag;if(typeof id=="string"){if(id.indexOf("#")===0){id=id.slice(1)}if(_V_.players[id]){return _V_.players[id]}else{tag=_V_.el(id)}}else{tag=id}if(!tag||!tag.nodeName){throw new TypeError("The element or ID supplied is not valid. (VideoJS)")}return tag.player||new _V_.Player(tag,addOptions,ready)},_V_=VideoJS,CDN_VERSION="3.1";VideoJS.players={};VideoJS.options={techOrder:["html5","flash"],html5:{},flash:{swf:"http://vjs.zencdn.net/c/video-js.swf"},width:"auto",height:"auto",defaultVolume:0,components:{poster:{},loadingSpinner:{},bigPlayButton:{},controlBar:{},subtitlesDisplay:{}}};if(CDN_VERSION!="GENERATED_CDN_VSN"){_V_.options.flash.swf="http://vjs.zencdn.net/"+CDN_VERSION+"/video-js.swf"}_V_.autoSetup=function(){var options,vid,player,vids=document.getElementsByTagName("video");if(vids&&vids.length>0){for(var i=0,j=vids.length;i<j;i++){vid=vids[i];if(vid&&vid.getAttribute){if(vid.player===undefined){options=vid.getAttribute("data-setup");if(options!==null){options=JSON.parse(options||"{}");player=_V_(vid,options)}}}else{_V_.autoSetupTimeout(1);break}}}else{if(!_V_.windowLoaded){_V_.autoSetupTimeout(1)}}};_V_.autoSetupTimeout=function(wait){setTimeout(_V_.autoSetup,wait)};_V_.merge=function(obj1,obj2,safe){if(!obj2){obj2={}}for(var attrname in obj2){if(obj2.hasOwnProperty(attrname)&&(!safe||!obj1.hasOwnProperty(attrname))){obj1[attrname]=obj2[attrname]}}return obj1};_V_.extend=function(obj){this.merge(this,obj,true)};_V_.extend({tech:{},controlSets:{},isIE:function(){return !+"\v1"},isFF:function(){return !!_V_.ua.match("Firefox")},isIPad:function(){return navigator.userAgent.match(/iPad/i)!==null},isIPhone:function(){return navigator.userAgent.match(/iPhone/i)!==null},isIOS:function(){return VideoJS.isIPhone()||VideoJS.isIPad()},iOSVersion:function(){var match=navigator.userAgent.match(/OS (\d+)_/i);if(match&&match[1]){return match[1]}},isAndroid:function(){return navigator.userAgent.match(/Android.*AppleWebKit/i)!==null},androidVersion:function(){var match=navigator.userAgent.match(/Android (\d+)\./i);if(match&&match[1]){return match[1]}},testVid:document.createElement("video"),ua:navigator.userAgent,support:{},each:function(arr,fn){if(!arr||arr.length===0){return}for(var i=0,j=arr.length;i<j;i++){fn.call(this,arr[i],i)}},eachProp:function(obj,fn){if(!obj){return}for(var name in obj){if(obj.hasOwnProperty(name)){fn.call(this,name,obj[name])}}},el:function(id){return document.getElementById(id)},createElement:function(tagName,attributes){var el=document.createElement(tagName),attrname;for(attrname in attributes){if(attributes.hasOwnProperty(attrname)){if(attrname.indexOf("-")!==-1){el.setAttribute(attrname,attributes[attrname])}else{el[attrname]=attributes[attrname]}}}return el},insertFirst:function(node,parent){if(parent.firstChild){parent.insertBefore(node,parent.firstChild)}else{parent.appendChild(node)}},addClass:function(element,classToAdd){if((" "+element.className+" ").indexOf(" "+classToAdd+" ")==-1){element.className=element.className===""?classToAdd:element.className+" "+classToAdd}},removeClass:function(element,classToRemove){if(element.className.indexOf(classToRemove)==-1){return}var classNames=element.className.split(" ");classNames.splice(classNames.indexOf(classToRemove),1);element.className=classNames.join(" ")},remove:function(item,array){if(!array){return}var i=array.indexOf(item);if(i!=-1){return array.splice(i,1)}},blockTextSelection:function(){document.body.focus();document.onselectstart=function(){return false}},unblockTextSelection:function(){document.onselectstart=function(){return true}},formatTime:function(seconds,guide){guide=guide||seconds;var s=Math.floor(seconds%60),m=Math.floor(seconds/60%60),h=Math.floor(seconds/3600),gm=Math.floor(guide/60%60),gh=Math.floor(guide/3600);h=(h>0||gh>0)?h+":":"";m=(((h||gm>=10)&&m<10)?"0"+m:m)+":";s=(s<10)?"0"+s:s;return h+m+s},capitalize:function(string){return string.charAt(0).toUpperCase()+string.slice(1)},getRelativePosition:function(x,relativeElement){return Math.max(0,Math.min(1,(x-_V_.findPosX(relativeElement))/relativeElement.offsetWidth))},getComputedStyleValue:function(element,style){return window.getComputedStyle(element,null).getPropertyValue(style)},trim:function(string){return string.toString().replace(/^\s+/,"").replace(/\s+$/,"")},round:function(num,dec){if(!dec){dec=0}return Math.round(num*Math.pow(10,dec))/Math.pow(10,dec)},isEmpty:function(object){for(var prop in object){return false}return true},createTimeRange:function(start,end){return{length:1,start:function(){return start},end:function(){return end}}},cache:{},guid:1,expando:"vdata"+(new Date).getTime(),getData:function(elem){var id=elem[_V_.expando];if(!id){id=elem[_V_.expando]=_V_.guid++;_V_.cache[id]={}}return _V_.cache[id]},removeData:function(elem){var id=elem[_V_.expando];if(!id){return}delete _V_.cache[id];try{delete elem[_V_.expando]}catch(e){if(elem.removeAttribute){elem.removeAttribute(_V_.expando)}else{elem[_V_.expando]=null}}},proxy:function(context,fn){if(!fn.guid){fn.guid=_V_.guid++}var ret=function(){return fn.apply(context,arguments)};ret.guid=fn.guid;return ret},get:function(url,onSuccess,onError){var local=(url.indexOf("file:")==0||(window.location.href.indexOf("file:")==0&&url.indexOf("http:")==-1));if(typeof XMLHttpRequest=="undefined"){XMLHttpRequest=function(){try{return new ActiveXObject("Msxml2.XMLHTTP.6.0")}catch(e){}try{return new ActiveXObject("Msxml2.XMLHTTP.3.0")}catch(f){}try{return new ActiveXObject("Msxml2.XMLHTTP")}catch(g){}throw new Error("This browser does not support XMLHttpRequest.")}}var request=new XMLHttpRequest();try{request.open("GET",url)}catch(e){_V_.log("VideoJS XMLHttpRequest (open)",e);return false}request.onreadystatechange=_V_.proxy(this,function(){if(request.readyState==4){if(request.status==200||local&&request.status==0){onSuccess(request.responseText)}else{if(onError){onError()}}}});try{request.send()}catch(e){_V_.log("VideoJS XMLHttpRequest (send)",e);if(onError){onError(e)}}},setLocalStorage:function(key,value){var localStorage=localStorage||false;if(!localStorage){return}try{localStorage[key]=value}catch(e){if(e.code==22||e.code==1014){_V_.log("LocalStorage Full (VideoJS)",e)}else{_V_.log("LocalStorage Error (VideoJS)",e)}}}});_V_.log=function(){_V_.log.history=_V_.log.history||[];_V_.log.history.push(arguments);if(window.console){arguments.callee=arguments.callee.caller;var newarr=[].slice.call(arguments);(typeof console.log==="object"?_V_.log.apply.call(console.log,console,newarr):console.log.apply(console,newarr))}};(function(b){function c(){}for(var d="assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,timeStamp,profile,profileEnd,time,timeEnd,trace,warn".split(","),a;a=d.pop();){b[a]=b[a]||c}})((function(){try{console.log();return window.console}catch(err){return window.console={}}})());if("getBoundingClientRect" in document.documentElement){_V_.findPosX=function(el){var box;try{box=el.getBoundingClientRect()}catch(e){}if(!box){return 0}var docEl=document.documentElement,body=document.body,clientLeft=docEl.clientLeft||body.clientLeft||0,scrollLeft=window.pageXOffset||body.scrollLeft,left=box.left+scrollLeft-clientLeft;return left}}else{_V_.findPosX=function(el){var curleft=el.offsetLeft;while(el=obj.offsetParent){if(el.className.indexOf("video-js")==-1){}else{}curleft+=el.offsetLeft}return curleft}}(function(){var initializing=false,fnTest=/xyz/.test(function(){xyz})?/\b_super\b/:/.*/;_V_.Class=function(){};_V_.Class.extend=function(prop){var _super=this.prototype;initializing=true;var prototype=new this();initializing=false;for(var name in prop){prototype[name]=typeof prop[name]=="function"&&typeof _super[name]=="function"&&fnTest.test(prop[name])?(function(name,fn){return function(){var tmp=this._super;this._super=_super[name];var ret=fn.apply(this,arguments);this._super=tmp;return ret}})(name,prop[name]):prop[name]}function Class(){if(!initializing&&this.init){return this.init.apply(this,arguments)}else{if(!initializing){return arguments.callee.prototype.init()}}}Class.prototype=prototype;Class.constructor=Class;Class.extend=arguments.callee;return Class}})();_V_.Component=_V_.Class.extend({init:function(player,options){this.player=player;options=this.options=_V_.merge(this.options||{},options);if(options.el){this.el=options.el}else{this.el=this.createElement()}this.initComponents()},destroy:function(){},createElement:function(type,attrs){return _V_.createElement(type||"div",attrs)},buildCSSClass:function(){return""},initComponents:function(){var options=this.options;if(options&&options.components){this.eachProp(options.components,function(name,opts){var tempAdd=this.proxy(function(){this.addComponent(name,opts)});if(opts.loadEvent){this.one(opts.loadEvent,tempAdd)}else{tempAdd()}})}},addComponent:function(name,options){var componentClass,component;options=options||{};componentClass=options.componentClass||_V_.capitalize(name);component=new _V_[componentClass](this.player||this,options);this.el.appendChild(component.el);this[name]=component},show:function(){this.el.style.display="block"},hide:function(){this.el.style.display="none"},fadeIn:function(){this.removeClass("vjs-fade-out");this.addClass("vjs-fade-in")},fadeOut:function(){this.removeClass("vjs-fade-in");this.addClass("vjs-fade-out")},addClass:function(classToAdd){_V_.addClass(this.el,classToAdd)},removeClass:function(classToRemove){_V_.removeClass(this.el,classToRemove)},addEvent:function(type,fn){return _V_.addEvent(this.el,type,_V_.proxy(this,fn))},removeEvent:function(type,fn){return _V_.removeEvent(this.el,type,fn)},triggerEvent:function(type,e){return _V_.triggerEvent(this.el,type,e)},one:function(type,fn){_V_.one.call(this,this.el,type,fn)},ready:function(fn){if(!fn){return this}if(this.isReady){fn.call(this)}else{if(this.readyQueue===undefined){this.readyQueue=[]}this.readyQueue.push(fn)}return this},triggerReady:function(){this.isReady=true;if(this.readyQueue&&this.readyQueue.length>0){this.each(this.readyQueue,function(fn){fn.call(this)});this.readyQueue=[]}},each:function(arr,fn){_V_.each.call(this,arr,fn)},eachProp:function(obj,fn){_V_.eachProp.call(this,obj,fn)},extend:function(obj){_V_.merge(this,obj)},proxy:function(fn){return _V_.proxy(this,fn)}});_V_.Control=_V_.Component.extend({buildCSSClass:function(){return"vjs-control "+this._super()}});_V_.Button=_V_.Control.extend({init:function(player,options){this._super(player,options);this.addEvent("click",this.onClick);this.addEvent("focus",this.onFocus);this.addEvent("blur",this.onBlur)},createElement:function(type,attrs){attrs=_V_.merge({className:this.buildCSSClass(),innerHTML:'<div><span class="vjs-control-text">'+(this.buttonText||"Need Text")+"</span></div>",role:"button",tabIndex:0},attrs);return this._super(type,attrs)},onClick:function(){},onFocus:function(){_V_.addEvent(document,"keyup",_V_.proxy(this,this.onKeyPress))},onKeyPress:function(event){if(event.which==32||event.which==13){event.preventDefault();this.onClick()}},onBlur:function(){_V_.removeEvent(document,"keyup",_V_.proxy(this,this.onKeyPress))}});_V_.PlayButton=_V_.Button.extend({buttonText:"Play",buildCSSClass:function(){return"vjs-play-button "+this._super()},onClick:function(){this.player.play()}});_V_.PauseButton=_V_.Button.extend({buttonText:"Pause",buildCSSClass:function(){return"vjs-pause-button "+this._super()},onClick:function(){this.player.pause()}});_V_.PlayToggle=_V_.Button.extend({buttonText:"Play",init:function(player,options){this._super(player,options);player.addEvent("play",_V_.proxy(this,this.onPlay));player.addEvent("pause",_V_.proxy(this,this.onPause))},buildCSSClass:function(){return"vjs-play-control "+this._super()},onClick:function(){if(this.player.paused()){this.player.play()}else{this.player.pause()}},onPlay:function(){_V_.removeClass(this.el,"vjs-paused");_V_.addClass(this.el,"vjs-playing")},onPause:function(){_V_.removeClass(this.el,"vjs-playing");_V_.addClass(this.el,"vjs-paused")}});_V_.FullscreenToggle=_V_.Button.extend({buttonText:"Fullscreen",buildCSSClass:function(){return"vjs-fullscreen-control "+this._super()},onClick:function(){if(!this.player.isFullScreen){this.player.requestFullScreen()}else{this.player.cancelFullScreen()}}});_V_.BigPlayButton=_V_.Button.extend({init:function(player,options){this._super(player,options);player.addEvent("play",_V_.proxy(this,this.hide));player.addEvent("ended",_V_.proxy(this,this.show))},createElement:function(){return this._super("div",{className:"vjs-big-play-button",innerHTML:"<span></span>"})},onClick:function(){if(this.player.currentTime()){this.player.currentTime(0)}this.player.play()}});_V_.LoadingSpinner=_V_.Component.extend({init:function(player,options){this._super(player,options);player.addEvent("canplay",_V_.proxy(this,this.hide));player.addEvent("canplaythrough",_V_.proxy(this,this.hide));player.addEvent("playing",_V_.proxy(this,this.hide));player.addEvent("seeking",_V_.proxy(this,this.show));player.addEvent("error",_V_.proxy(this,this.show));player.addEvent("waiting",_V_.proxy(this,this.show))},createElement:function(){var classNameSpinner,innerHtmlSpinner;if(typeof this.player.el.style.WebkitBorderRadius=="string"||typeof this.player.el.style.MozBorderRadius=="string"||typeof this.player.el.style.KhtmlBorderRadius=="string"||typeof this.player.el.style.borderRadius=="string"){classNameSpinner="vjs-loading-spinner";innerHtmlSpinner="<div class='ball1'></div><div class='ball2'></div><div class='ball3'></div><div class='ball4'></div><div class='ball5'></div><div class='ball6'></div><div class='ball7'></div><div class='ball8'></div>"}else{classNameSpinner="vjs-loading-spinner-fallback";innerHtmlSpinner=""}return this._super("div",{className:classNameSpinner,innerHTML:innerHtmlSpinner})}});_V_.ControlBar=_V_.Component.extend({options:{loadEvent:"play",components:{playToggle:{},fullscreenToggle:{},currentTimeDisplay:{},timeDivider:{},durationDisplay:{},remainingTimeDisplay:{},progressControl:{},volumeControl:{},muteToggle:{}}},init:function(player,options){this._super(player,options);player.addEvent("play",this.proxy(function(){this.fadeIn();this.player.addEvent("mouseover",this.proxy(this.fadeIn));this.player.addEvent("mouseout",this.proxy(this.fadeOut))}))},createElement:function(){return _V_.createElement("div",{className:"vjs-controls"})},fadeIn:function(){this._super();this.player.triggerEvent("controlsvisible")},fadeOut:function(){this._super();this.player.triggerEvent("controlshidden")}});_V_.CurrentTimeDisplay=_V_.Component.extend({init:function(player,options){this._super(player,options);player.addEvent("timeupdate",_V_.proxy(this,this.updateContent))},createElement:function(){var el=this._super("div",{className:"vjs-current-time vjs-time-controls vjs-control"});this.content=_V_.createElement("div",{className:"vjs-current-time-display",innerHTML:"0:00"});el.appendChild(_V_.createElement("div").appendChild(this.content));return el},updateContent:function(){var time=(this.player.scrubbing)?this.player.values.currentTime:this.player.currentTime();this.content.innerHTML=_V_.formatTime(time,this.player.duration())}});_V_.DurationDisplay=_V_.Component.extend({init:function(player,options){this._super(player,options);player.addEvent("timeupdate",_V_.proxy(this,this.updateContent))},createElement:function(){var el=this._super("div",{className:"vjs-duration vjs-time-controls vjs-control"});this.content=_V_.createElement("div",{className:"vjs-duration-display",innerHTML:"0:00"});el.appendChild(_V_.createElement("div").appendChild(this.content));return el},updateContent:function(){if(this.player.duration()){this.content.innerHTML=_V_.formatTime(this.player.duration())}}});_V_.TimeDivider=_V_.Component.extend({createElement:function(){return this._super("div",{className:"vjs-time-divider",innerHTML:"<div><span>/</span></div>"})}});_V_.RemainingTimeDisplay=_V_.Component.extend({init:function(player,options){this._super(player,options);player.addEvent("timeupdate",_V_.proxy(this,this.updateContent))},createElement:function(){var el=this._super("div",{className:"vjs-remaining-time vjs-time-controls vjs-control"});this.content=_V_.createElement("div",{className:"vjs-remaining-time-display",innerHTML:"-0:00"});el.appendChild(_V_.createElement("div").appendChild(this.content));return el},updateContent:function(){if(this.player.duration()){this.content.innerHTML="-"+_V_.formatTime(this.player.remainingTime())}}});_V_.Slider=_V_.Component.extend({init:function(player,options){this._super(player,options);player.addEvent(this.playerEvent,_V_.proxy(this,this.update));this.addEvent("mousedown",this.onMouseDown);this.addEvent("focus",this.onFocus);this.addEvent("blur",this.onBlur);this.player.addEvent("controlsvisible",this.proxy(this.update));this.update()},createElement:function(type,attrs){attrs=_V_.merge({role:"slider","aria-valuenow":0,"aria-valuemin":0,"aria-valuemax":100,tabIndex:0},attrs);return this._super(type,attrs)},onMouseDown:function(event){event.preventDefault();_V_.blockTextSelection();_V_.addEvent(document,"mousemove",_V_.proxy(this,this.onMouseMove));_V_.addEvent(document,"mouseup",_V_.proxy(this,this.onMouseUp));this.onMouseMove(event)},onMouseUp:function(event){_V_.unblockTextSelection();_V_.removeEvent(document,"mousemove",this.onMouseMove,false);_V_.removeEvent(document,"mouseup",this.onMouseUp,false);this.update()},update:function(){var barProgress,progress=this.getPercent();handle=this.handle,bar=this.bar;if(isNaN(progress)){progress=0}barProgress=progress;if(handle){var box=this.el,boxWidth=box.offsetWidth,handleWidth=handle.el.offsetWidth,handlePercent=(handleWidth)?handleWidth/boxWidth:0,boxAdjustedPercent=1-handlePercent;adjustedProgress=progress*boxAdjustedPercent,barProgress=adjustedProgress+(handlePercent/2);handle.el.style.left=_V_.round(adjustedProgress*100,2)+"%"}bar.el.style.width=_V_.round(barProgress*100,2)+"%"},calculateDistance:function(event){var box=this.el,boxX=_V_.findPosX(box),boxW=box.offsetWidth,handle=this.handle;if(handle){var handleW=handle.el.offsetWidth;boxX=boxX+(handleW/2);boxW=boxW-handleW}return Math.max(0,Math.min(1,(event.pageX-boxX)/boxW))},onFocus:function(event){_V_.addEvent(document,"keyup",_V_.proxy(this,this.onKeyPress))},onKeyPress:function(event){if(event.which==37){event.preventDefault();this.stepBack()}else{if(event.which==39){event.preventDefault();this.stepForward()}}},onBlur:function(event){_V_.removeEvent(document,"keyup",_V_.proxy(this,this.onKeyPress))}});_V_.ProgressControl=_V_.Component.extend({options:{components:{seekBar:{}}},createElement:function(){return this._super("div",{className:"vjs-progress-control vjs-control"})}});_V_.SeekBar=_V_.Slider.extend({options:{components:{loadProgressBar:{},bar:{componentClass:"PlayProgressBar"},handle:{componentClass:"SeekHandle"}}},playerEvent:"timeupdate",init:function(player,options){this._super(player,options)},createElement:function(){return this._super("div",{className:"vjs-progress-holder"})},getPercent:function(){return this.player.currentTime()/this.player.duration()},onMouseDown:function(event){this._super(event);this.player.scrubbing=true;this.videoWasPlaying=!this.player.paused();this.player.pause()},onMouseMove:function(event){var newTime=this.calculateDistance(event)*this.player.duration();if(newTime==this.player.duration()){newTime=newTime-0.1}this.player.currentTime(newTime)},onMouseUp:function(event){this._super(event);this.player.scrubbing=false;if(this.videoWasPlaying){this.player.play()}},stepForward:function(){this.player.currentTime(this.player.currentTime()+1)},stepBack:function(){this.player.currentTime(this.player.currentTime()-1)}});_V_.LoadProgressBar=_V_.Component.extend({init:function(player,options){this._super(player,options);player.addEvent("progress",_V_.proxy(this,this.update))},createElement:function(){return this._super("div",{className:"vjs-load-progress",innerHTML:'<span class="vjs-control-text">Loaded: 0%</span>'})},update:function(){if(this.el.style){this.el.style.width=_V_.round(this.player.bufferedPercent()*100,2)+"%"}}});_V_.PlayProgressBar=_V_.Component.extend({createElement:function(){return this._super("div",{className:"vjs-play-progress",innerHTML:'<span class="vjs-control-text">Progress: 0%</span>'})}});_V_.SeekHandle=_V_.Component.extend({createElement:function(){return this._super("div",{className:"vjs-seek-handle",innerHTML:'<span class="vjs-control-text">00:00</span>'})}});_V_.VolumeControl=_V_.Component.extend({options:{components:{volumeBar:{}}},createElement:function(){return this._super("div",{className:"vjs-volume-control vjs-control"})}});_V_.VolumeBar=_V_.Slider.extend({options:{components:{bar:{componentClass:"VolumeLevel"},handle:{componentClass:"VolumeHandle"}}},playerEvent:"volumechange",createElement:function(){return this._super("div",{className:"vjs-volume-bar"})},onMouseMove:function(event){this.player.volume(this.calculateDistance(event))},getPercent:function(){return this.player.volume()},stepForward:function(){this.player.volume(this.player.volume()+0.1)},stepBack:function(){this.player.volume(this.player.volume()-0.1)}});_V_.VolumeLevel=_V_.Component.extend({createElement:function(){return this._super("div",{className:"vjs-volume-level",innerHTML:'<span class="vjs-control-text"></span>'})}});_V_.VolumeHandle=_V_.Component.extend({createElement:function(){return this._super("div",{className:"vjs-volume-handle",innerHTML:'<span class="vjs-control-text"></span>'})}});_V_.MuteToggle=_V_.Button.extend({init:function(player,options){this._super(player,options);player.addEvent("volumechange",_V_.proxy(this,this.update))},createElement:function(){return this._super("div",{className:"vjs-mute-control vjs-control",innerHTML:'<div><span class="vjs-control-text">Mute</span></div>'})},onClick:function(event){this.player.muted(this.player.muted()?false:true)},update:function(event){var vol=this.player.volume(),level=3;if(vol==0||this.player.muted()){level=0}else{if(vol<0.33){level=1}else{if(vol<0.67){level=2}}}_V_.each.call(this,[0,1,2,3],function(i){_V_.removeClass(this.el,"vjs-vol-"+i)});_V_.addClass(this.el,"vjs-vol-"+level)}});_V_.Poster=_V_.Button.extend({init:function(player,options){this._super(player,options);if(!this.player.options.poster){this.hide()}player.addEvent("play",_V_.proxy(this,this.hide))},createElement:function(){return _V_.createElement("img",{className:"vjs-poster",src:this.player.options.poster,tabIndex:-1})},onClick:function(){this.player.play()}});_V_.TextTrackDisplay=_V_.Component.extend({init:function(player,options){this._super(player,options);player.addEvent(this.trackType+"update",_V_.proxy(this,this.update))},createElement:function(){return this._super("div",{className:"vjs-"+this.trackType})},update:function(){this.el.innerHTML=this.player.textTrackValue(this.trackType)}});_V_.SubtitlesDisplay=_V_.TextTrackDisplay.extend({trackType:"subtitles"});_V_.CaptionsDisplay=_V_.TextTrackDisplay.extend({trackType:"captions"});_V_.ChaptersDisplay=_V_.TextTrackDisplay.extend({trackType:"chapters"});_V_.DescriptionsDisplay=_V_.TextTrackDisplay.extend({trackType:"descriptions"});if(!Array.prototype.indexOf){Array.prototype.indexOf=function(searchElement){if(this===void 0||this===null){throw new TypeError()}var t=Object(this);var len=t.length>>>0;if(len===0){return -1}var n=0;if(arguments.length>0){n=Number(arguments[1]);if(n!==n){n=0}else{if(n!==0&&n!==(1/0)&&n!==-(1/0)){n=(n>0||-1)*Math.floor(Math.abs(n))}}}if(n>=len){return -1}var k=n>=0?n:Math.max(len-Math.abs(n),0);for(;k<len;k++){if(k in t&&t[k]===searchElement){return k}}return -1}}_V_.extend({addEvent:function(elem,type,fn){var data=_V_.getData(elem),handlers;if(data&&!data.handler){data.handler=function(event){event=_V_.fixEvent(event);var handlers=_V_.getData(elem).events[event.type];if(handlers){var handlersCopy=[];_V_.each(handlers,function(handler,i){handlersCopy[i]=handler});for(var i=0,l=handlersCopy.length;i<l;i++){handlersCopy[i].call(elem,event)}}}}if(!data.events){data.events={}}handlers=data.events[type];if(!handlers){handlers=data.events[type]=[];if(document.addEventListener){elem.addEventListener(type,data.handler,false)}else{if(document.attachEvent){elem.attachEvent("on"+type,data.handler)}}}if(!fn.guid){fn.guid=_V_.guid++}handlers.push(fn)},removeEvent:function(elem,type,fn){var data=_V_.getData(elem),handlers;if(!data.events){return}if(!type){for(type in data.events){_V_.cleanUpEvents(elem,type)}return}handlers=data.events[type];if(!handlers){return}if(fn&&fn.guid){for(var i=0;i<handlers.length;i++){if(handlers[i].guid===fn.guid){handlers.splice(i--,1)}}}_V_.cleanUpEvents(elem,type)},cleanUpEvents:function(elem,type){var data=_V_.getData(elem);if(data.events[type].length===0){delete data.events[type];if(document.removeEventListener){elem.removeEventListener(type,data.handler,false)}else{if(document.detachEvent){elem.detachEvent("on"+type,data.handler)}}}if(_V_.isEmpty(data.events)){delete data.events;delete data.handler}if(_V_.isEmpty(data)){_V_.removeData(elem)}},fixEvent:function(event){if(event[_V_.expando]){return event}var originalEvent=event;event=new _V_.Event(originalEvent);for(var i=_V_.Event.props.length,prop;i;){prop=_V_.Event.props[--i];event[prop]=originalEvent[prop]}if(!event.target){event.target=event.srcElement||document}if(event.target.nodeType===3){event.target=event.target.parentNode}if(!event.relatedTarget&&event.fromElement){event.relatedTarget=event.fromElement===event.target?event.toElement:event.fromElement}if(event.pageX==null&&event.clientX!=null){var eventDocument=event.target.ownerDocument||document,doc=eventDocument.documentElement,body=eventDocument.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc&&doc.clientLeft||body&&body.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc&&doc.clientTop||body&&body.clientTop||0)}if(event.which==null&&(event.charCode!=null||event.keyCode!=null)){event.which=event.charCode!=null?event.charCode:event.keyCode}if(!event.metaKey&&event.ctrlKey){event.metaKey=event.ctrlKey}if(!event.which&&event.button!==undefined){event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)))}return event},triggerEvent:function(elem,event){var data=_V_.getData(elem),parent=elem.parentNode||elem.ownerDocument,type=event.type||event,handler;if(data){handler=data.handler}event=typeof event==="object"?event[_V_.expando]?event:new _V_.Event(type,event):new _V_.Event(type);event.type=type;if(handler){handler.call(elem,event)}event.result=undefined;event.target=elem},one:function(elem,type,fn){_V_.addEvent(elem,type,function(){_V_.removeEvent(elem,type,arguments.callee);fn.apply(this,arguments)})}});_V_.Event=function(src,props){if(src&&src.type){this.originalEvent=src;this.type=src.type;this.isDefaultPrevented=(src.defaultPrevented||src.returnValue===false||src.getPreventDefault&&src.getPreventDefault())?returnTrue:returnFalse}else{this.type=src}if(props){_V_.merge(this,props)}this.timeStamp=(new Date).getTime();this[_V_.expando]=true};_V_.Event.prototype={preventDefault:function(){this.isDefaultPrevented=returnTrue;var e=this.originalEvent;if(!e){return}if(e.preventDefault){e.preventDefault()}else{e.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=returnTrue;var e=this.originalEvent;if(!e){return}if(e.stopPropagation){e.stopPropagation()}e.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=returnTrue;this.stopPropagation()},isDefaultPrevented:returnFalse,isPropagationStopped:returnFalse,isImmediatePropagationStopped:returnFalse};_V_.Event.props="altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" ");function returnTrue(){return true}function returnFalse(){return false}var JSON;if(!JSON){JSON={}}(function(){var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;if(typeof JSON.parse!=="function"){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==="object"){for(k in value){if(Object.prototype.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v}else{delete value[k]}}}}return reviver.call(holder,key,value)}text=String(text);cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver==="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")}}}());_V_.Player=_V_.Component.extend({init:function(tag,addOptions,ready){this.tag=tag;var el=this.el=_V_.createElement("div"),options=this.options={},width=options.width=tag.getAttribute("width"),height=options.height=tag.getAttribute("height"),initWidth=width||300,initHeight=height||150;tag.player=el.player=this;this.ready(ready);tag.parentNode.insertBefore(el,tag);el.appendChild(tag);el.id=this.id=tag.id;el.className=tag.className;tag.id+="_html5_api";tag.className="vjs-tech";_V_.players[el.id]=this;el.setAttribute("width",initWidth);el.setAttribute("height",initHeight);el.style.width=initWidth+"px";el.style.height=initHeight+"px";tag.removeAttribute("width");tag.removeAttribute("height");_V_.merge(options,_V_.options);_V_.merge(options,this.getVideoTagSettings());_V_.merge(options,addOptions);tag.removeAttribute("controls");tag.removeAttribute("poster");if(tag.hasChildNodes()){for(var i=0,j=tag.childNodes;i<j.length;i++){if(j[i].nodeName=="SOURCE"||j[i].nodeName=="TRACK"){tag.removeChild(j[i])}}}this.techs={};this.values={};this.addClass("vjs-paused");this.addEvent("ended",this.onEnded);this.addEvent("play",this.onPlay);this.addEvent("pause",this.onPause);this.addEvent("error",this.onError);if(options.controls){this.ready(function(){this.initComponents()})}if(!options.sources||options.sources.length==0){for(var i=0,j=options.techOrder;i<j.length;i++){var techName=j[i],tech=_V_[techName];if(tech.isSupported()){this.loadTech(techName);break}}}else{this.src(options.sources)}},values:{},destroy:function(){this.stopTrackingProgress();this.stopTrackingCurrentTime();delete _V_.players[this.id]},createElement:function(type,options){},getVideoTagSettings:function(){var options={sources:[],tracks:[]};options.src=this.tag.getAttribute("src");options.controls=this.tag.getAttribute("controls")!==null;options.poster=this.tag.getAttribute("poster");options.preload=this.tag.getAttribute("preload");options.autoplay=this.tag.getAttribute("autoplay")!==null;options.loop=this.tag.getAttribute("loop")!==null;options.muted=this.tag.getAttribute("muted")!==null;if(this.tag.hasChildNodes()){for(var c,i=0,j=this.tag.childNodes;i<j.length;i++){c=j[i];if(c.nodeName=="SOURCE"){options.sources.push({src:c.getAttribute("src"),type:c.getAttribute("type"),media:c.getAttribute("media"),title:c.getAttribute("title")})}if(c.nodeName=="TRACK"){options.tracks.push(new _V_.Track({src:c.getAttribute("src"),kind:c.getAttribute("kind"),srclang:c.getAttribute("srclang"),label:c.getAttribute("label"),"default":c.getAttribute("default")!==null,title:c.getAttribute("title")},this))}}}return options},loadTech:function(techName,source){if(this.tech){this.unloadTech()}else{if(techName!="html5"&&this.tag){this.el.removeChild(this.tag);this.tag=false}}this.techName=techName;this.isReady=false;var techReady=function(){this.player.triggerReady();if(!this.support.progressEvent){this.player.manualProgressOn()}if(!this.support.timeupdateEvent){this.player.manualTimeUpdatesOn()}};var techOptions=_V_.merge({source:source,parentEl:this.el},this.options[techName]);if(source){if(source.src==this.values.src&&this.values.currentTime>0){techOptions.startTime=this.values.currentTime}this.values.src=source.src}this.tech=new _V_[techName](this,techOptions);this.tech.ready(techReady)},unloadTech:function(){this.tech.destroy();if(this.manualProgress){this.manualProgressOff()}if(this.manualTimeUpdates){this.manualTimeUpdatesOff()}this.tech=false},manualProgressOn:function(){this.manualProgress=true;this.trackProgress();this.tech.addEvent("progress",function(){this.removeEvent("progress",arguments.callee);this.support.progressEvent=true;this.player.manualProgressOff()})},manualProgressOff:function(){this.manualProgress=false;this.stopTrackingProgress()},trackProgress:function(){this.progressInterval=setInterval(_V_.proxy(this,function(){if(this.values.bufferEnd<this.buffered().end(0)){this.triggerEvent("progress")}else{if(this.bufferedPercent()==1){this.stopTrackingProgress();this.triggerEvent("progress")}}}),500)},stopTrackingProgress:function(){clearInterval(this.progressInterval)},manualTimeUpdatesOn:function(){this.manualTimeUpdates=true;this.addEvent("play",this.trackCurrentTime);this.addEvent("pause",this.stopTrackingCurrentTime);this.tech.addEvent("timeupdate",function(){this.removeEvent("timeupdate",arguments.callee);this.support.timeupdateEvent=true;this.player.manualTimeUpdatesOff()})},manualTimeUpdatesOff:function(){this.manualTimeUpdates=false;this.stopTrackingCurrentTime();this.removeEvent("play",this.trackCurrentTime);this.removeEvent("pause",this.stopTrackingCurrentTime)},trackCurrentTime:function(){if(this.currentTimeInterval){this.stopTrackingCurrentTime()}this.currentTimeInterval=setInterval(_V_.proxy(this,function(){this.triggerEvent("timeupdate")}),250)},stopTrackingCurrentTime:function(){clearInterval(this.currentTimeInterval)},onEnded:function(){if(this.options.loop){this.currentTime(0);this.play()}else{this.pause();this.currentTime(0);this.pause()}},onPlay:function(){_V_.removeClass(this.el,"vjs-paused");_V_.addClass(this.el,"vjs-playing")},onPause:function(){_V_.removeClass(this.el,"vjs-playing");_V_.addClass(this.el,"vjs-paused")},onError:function(e){_V_.log("Video Error",e)},apiCall:function(method,arg){if(this.isReady){return this.tech[method](arg)}else{_V_.log("The playback technology API is not ready yet. Use player.ready(myFunction). ["+method+"]",arguments.callee.caller.arguments.callee.caller.arguments.callee.caller);return false}},play:function(){this.apiCall("play");return this},pause:function(){this.apiCall("pause");return this},paused:function(){return this.apiCall("paused")},currentTime:function(seconds){if(seconds!==undefined){this.values.lastSetCurrentTime=seconds;this.apiCall("setCurrentTime",seconds);if(this.manualTimeUpdates){this.triggerEvent("timeupdate")}return this}return this.values.currentTime=this.apiCall("currentTime")},duration:function(){return this.apiCall("duration")},remainingTime:function(){return this.duration()-this.currentTime()},buffered:function(){var buffered=this.apiCall("buffered"),start=0,end=this.values.bufferEnd=this.values.bufferEnd||0,timeRange;if(buffered&&buffered.length>0&&buffered.end(0)!==end){end=buffered.end(0);this.values.bufferEnd=end}return _V_.createTimeRange(start,end)},bufferedPercent:function(){return(this.duration())?this.buffered().end(0)/this.duration():0},volume:function(percentAsDecimal){if(percentAsDecimal!==undefined){var vol=Math.max(0,Math.min(1,parseFloat(percentAsDecimal)));this.values.volume=vol;this.apiCall("setVolume",vol);_V_.setLocalStorage("volume",vol);return this}return this.apiCall("volume")},muted:function(muted){if(muted!==undefined){this.apiCall("setMuted",muted);return this}return this.apiCall("muted")},width:function(width,skipListeners){if(width!==undefined){this.el.width=width;this.el.style.width=width+"px";if(!skipListeners){this.triggerEvent("resize")}return this}return parseInt(this.el.getAttribute("width"))},height:function(height){if(height!==undefined){this.el.height=height;this.el.style.height=height+"px";this.triggerEvent("resize");return this}return parseInt(this.el.getAttribute("height"))},size:function(width,height){return this.width(width,true).height(height)},supportsFullScreen:function(){return this.apiCall("supportsFullScreen")},requestFullScreen:function(){var requestFullScreen=_V_.support.requestFullScreen;this.isFullScreen=true;if(requestFullScreen){if(this.tech.support.fullscreenResize===false&&this.options.flash.iFrameMode!=true){this.pause();this.unloadTech();_V_.addEvent(document,requestFullScreen.eventName,this.proxy(function(){_V_.removeEvent(document,requestFullScreen.eventName,arguments.callee);this.loadTech(this.techName,{src:this.values.src})}));this.el[requestFullScreen.requestFn]()}else{this.el[requestFullScreen.requestFn]()}_V_.addEvent(document,requestFullScreen.eventName,this.proxy(function(){this.isFullScreen=document[requestFullScreen.isFullScreen]}))}else{if(this.tech.supportsFullScreen()){this.apiCall("enterFullScreen")}else{this.enterFullWindow()}}this.triggerEvent("fullscreenchange");return this},cancelFullScreen:function(){var requestFullScreen=_V_.support.requestFullScreen;if(requestFullScreen){if(this.tech.support.fullscreenResize===false&&this.options.flash.iFrameMode!=true){this.pause();this.unloadTech();_V_.addEvent(document,requestFullScreen.eventName,this.proxy(function(){_V_.removeEvent(document,requestFullScreen.eventName,arguments.callee);this.loadTech(this.techName,{src:this.values.src})}));document[requestFullScreen.cancelFn]()}else{document[requestFullScreen.cancelFn]()}}else{if(this.tech.supportsFullScreen()){this.apiCall("exitFullScreen")}else{this.exitFullWindow()}}this.isFullScreen=false;this.triggerEvent("fullscreenchange");return this},enterFullWindow:function(){this.isFullWindow=true;this.docOrigOverflow=document.documentElement.style.overflow;_V_.addEvent(document,"keydown",_V_.proxy(this,this.fullWindowOnEscKey));document.documentElement.style.overflow="hidden";_V_.addClass(document.body,"vjs-full-window");_V_.addClass(this.el,"vjs-fullscreen");this.triggerEvent("enterFullWindow")},fullWindowOnEscKey:function(event){if(event.keyCode==27){if(this.isFullScreen==true){this.cancelFullScreen()}else{this.exitFullWindow()}}},exitFullWindow:function(){this.isFullWindow=false;_V_.removeEvent(document,"keydown",this.fullWindowOnEscKey);document.documentElement.style.overflow=this.docOrigOverflow;_V_.removeClass(document.body,"vjs-full-window");_V_.removeClass(this.el,"vjs-fullscreen");this.triggerEvent("exitFullWindow")},src:function(source){if(source instanceof Array){var sources=source;techLoop:for(var i=0,j=this.options.techOrder;i<j.length;i++){var techName=j[i],tech=_V_[techName];if(tech.isSupported()){for(var a=0,b=sources;a<b.length;a++){var source=b[a];if(tech.canPlaySource.call(this,source)){if(techName==this.techName){this.src(source)}else{this.loadTech(techName,source)}break techLoop}}}}}else{if(source instanceof Object){if(_V_[this.techName].canPlaySource(source)){this.src(source.src)}else{this.src([source])}}else{this.values.src=source;if(!this.isReady){this.ready(function(){this.src(source)})}else{this.apiCall("src",source);if(this.options.preload=="auto"){this.load()}if(this.options.autoplay){this.play()}}}}return this},load:function(){this.apiCall("load");return this},currentSrc:function(){return this.apiCall("currentSrc")},textTrackValue:function(kind,value){if(value!==undefined){this.values[kind]=value;this.triggerEvent(kind+"update");return this}return this.values[kind]},preload:function(value){if(value!==undefined){this.apiCall("setPreload",value);this.options.preload=value;return this}return this.apiCall("preload",value)},autoplay:function(value){if(value!==undefined){this.apiCall("setAutoplay",value);this.options.autoplay=value;return this}return this.apiCall("autoplay",value)},loop:function(value){if(value!==undefined){this.apiCall("setLoop",value);this.options.loop=value;return this}return this.apiCall("loop",value)},controls:function(){return this.options.controls},textTracks:function(){return this.options.tracks},poster:function(){return this.apiCall("poster")},error:function(){return this.apiCall("error")},networkState:function(){return this.apiCall("networkState")},readyState:function(){return this.apiCall("readyState")},seeking:function(){return this.apiCall("seeking")},initialTime:function(){return this.apiCall("initialTime")},startOffsetTime:function(){return this.apiCall("startOffsetTime")},played:function(){return this.apiCall("played")},seekable:function(){return this.apiCall("seekable")},ended:function(){return this.apiCall("ended")},videoTracks:function(){return this.apiCall("videoTracks")},audioTracks:function(){return this.apiCall("audioTracks")},videoWidth:function(){return this.apiCall("videoWidth")},videoHeight:function(){return this.apiCall("videoHeight")},defaultPlaybackRate:function(){return this.apiCall("defaultPlaybackRate")},playbackRate:function(){return this.apiCall("playbackRate")},controls:function(){return this.apiCall("controls")},defaultMuted:function(){return this.apiCall("defaultMuted")}});(function(){var requestFn,cancelFn,eventName,isFullScreen,playerProto=_V_.Player.prototype;if(document.cancelFullscreen!==undefined){requestFn="requestFullscreen";cancelFn="exitFullscreen";eventName="fullscreenchange";isFullScreen="fullScreen"}else{_V_.each(["moz","webkit"],function(prefix){if((prefix!="moz"||document.mozFullScreenEnabled)&&document[prefix+"CancelFullScreen"]!==undefined){requestFn=prefix+"RequestFullScreen";cancelFn=prefix+"CancelFullScreen";eventName=prefix+"fullscreenchange";if(prefix=="webkit"){isFullScreen=prefix+"IsFullScreen"}else{_V_.log("moz here");isFullScreen=prefix+"FullScreen"}}})}if(requestFn){_V_.support.requestFullScreen={requestFn:requestFn,cancelFn:cancelFn,eventName:eventName,isFullScreen:isFullScreen}}})();_V_.PlaybackTech=_V_.Component.extend({init:function(player,options){},onClick:function(){if(this.player.options.controls){_V_.PlayToggle.prototype.onClick.call(this)}}});_V_.apiMethods="play,pause,paused,currentTime,setCurrentTime,duration,buffered,volume,setVolume,muted,setMuted,width,height,supportsFullScreen,enterFullScreen,src,load,currentSrc,preload,setPreload,autoplay,setAutoplay,loop,setLoop,error,networkState,readyState,seeking,initialTime,startOffsetTime,played,seekable,ended,videoTracks,audioTracks,videoWidth,videoHeight,textTracks,defaultPlaybackRate,playbackRate,mediaGroup,controller,controls,defaultMuted".split(",");_V_.each(_V_.apiMethods,function(methodName){_V_.PlaybackTech.prototype[methodName]=function(){throw new Error("The '"+method+"' method is not available on the playback technology's API")}});_V_.html5=_V_.PlaybackTech.extend({init:function(player,options,ready){this.player=player;this.el=this.createElement();this.ready(ready);this.addEvent("click",this.proxy(this.onClick));var source=options.source;if(source&&this.el.currentSrc==source.src){player.triggerEvent("loadstart")}else{if(source){this.el.src=source.src}}player.ready(function(){if(this.options.autoplay&&this.paused()){this.tag.poster=null;this.play()}});this.setupTriggers();this.triggerReady()},destroy:function(){this.player.tag=false;this.removeTriggers();this.el.parentNode.removeChild(this.el)},createElement:function(){var html5=_V_.html5,player=this.player,el=player.tag,newEl;if(!el||this.support.movingElementInDOM===false){if(el){player.el.removeChild(el)}newEl=_V_.createElement("video",{id:el.id||player.el.id+"_html5_api",className:el.className||"vjs-tech"});el=newEl;_V_.insertFirst(el,player.el)}_V_.each(["autoplay","preload","loop","muted"],function(attr){el[attr]=player.options[attr]},this);return el},setupTriggers:function(){_V_.each.call(this,_V_.html5.events,function(type){_V_.addEvent(this.el,type,_V_.proxy(this.player,this.eventHandler))})},removeTriggers:function(){_V_.each.call(this,_V_.html5.events,function(type){_V_.removeEvent(this.el,type,_V_.proxy(this.player,this.eventHandler))})},eventHandler:function(e){e.stopPropagation();this.triggerEvent(e)},play:function(){this.el.play()},pause:function(){this.el.pause()},paused:function(){return this.el.paused},currentTime:function(){return this.el.currentTime},setCurrentTime:function(seconds){try{this.el.currentTime=seconds}catch(e){_V_.log(e,"Video isn't ready. (VideoJS)")}},duration:function(){return this.el.duration||0},buffered:function(){return this.el.buffered},volume:function(){return this.el.volume},setVolume:function(percentAsDecimal){this.el.volume=percentAsDecimal},muted:function(){return this.el.muted},setMuted:function(muted){this.el.muted=muted},width:function(){return this.el.offsetWidth},height:function(){return this.el.offsetHeight},supportsFullScreen:function(){if(typeof this.el.webkitEnterFullScreen=="function"){if(!navigator.userAgent.match("Chrome")&&!navigator.userAgent.match("Mac OS X 10.5")){return true}}return false},enterFullScreen:function(){try{this.el.webkitEnterFullScreen()}catch(e){if(e.code==11){_V_.log("VideoJS: Video not ready.")}}},src:function(src){this.el.src=src},load:function(){this.el.load()},currentSrc:function(){return this.el.currentSrc},preload:function(){return this.el.preload},setPreload:function(val){this.el.preload=val},autoplay:function(){return this.el.autoplay},setAutoplay:function(val){this.el.autoplay=val},loop:function(){return this.el.loop},setLoop:function(val){this.el.loop=val},error:function(){return this.el.error},seeking:function(){return this.el.seeking},ended:function(){return this.el.ended},controls:function(){return this.player.options.controls},defaultMuted:function(){return this.el.defaultMuted}});_V_.html5.isSupported=function(){return !!document.createElement("video").canPlayType};_V_.html5.canPlaySource=function(srcObj){return !!document.createElement("video").canPlayType(srcObj.type)};_V_.html5.events="loadstart,suspend,abort,error,emptied,stalled,loadedmetadata,loadeddata,canplay,canplaythrough,playing,waiting,seeking,seeked,ended,durationchange,timeupdate,progress,play,pause,ratechange,volumechange".split(",");_V_.html5.prototype.support={fullscreen:(typeof _V_.testVid.webkitEnterFullScreen!==undefined)?(!_V_.ua.match("Chrome")&&!_V_.ua.match("Mac OS X 10.5")?true:false):false,movingElementInDOM:!_V_.isIOS()};if(_V_.isAndroid()){if(_V_.androidVersion()<3){document.createElement("video").constructor.prototype.canPlayType=function(type){return(type&&type.toLowerCase().indexOf("video/mp4")!=-1)?"maybe":""}}}_V_.flash=_V_.PlaybackTech.extend({init:function(player,options){this.player=player;var source=options.source,parentEl=options.parentEl,placeHolder=this.el=_V_.createElement("div",{id:parentEl.id+"_temp_flash"}),objId=player.el.id+"_flash_api",playerOptions=player.options,flashVars=_V_.merge({readyFunction:"_V_.flash.onReady",eventProxyFunction:"_V_.flash.onEvent",errorEventProxyFunction:"_V_.flash.onError",autoplay:playerOptions.autoplay,preload:playerOptions.preload,loop:playerOptions.loop,muted:playerOptions.muted},options.flashVars),params=_V_.merge({wmode:"opaque",bgcolor:"#000000"},options.params),attributes=_V_.merge({id:objId,name:objId,"class":"vjs-tech"},options.attributes);if(source){flashVars.src=encodeURIComponent(source.src)}_V_.insertFirst(placeHolder,parentEl);if(options.startTime){this.ready(function(){this.load();this.play();this.currentTime(options.startTime)})}if(options.iFrameMode==true&&!_V_.isFF){var iFrm=_V_.createElement("iframe",{id:objId+"_iframe",name:objId+"_iframe",className:"vjs-tech",scrolling:"no",marginWidth:0,marginHeight:0,frameBorder:0});flashVars.readyFunction="ready";flashVars.eventProxyFunction="events";flashVars.errorEventProxyFunction="errors";_V_.addEvent(iFrm,"load",_V_.proxy(this,function(){var iDoc,objTag,swfLoc,iWin=iFrm.contentWindow,varString="";iDoc=iFrm.contentDocument?iFrm.contentDocument:iFrm.contentWindow.document;iDoc.write(_V_.flash.getEmbedCode(options.swf,flashVars,params,attributes));iWin.player=this.player;iWin.ready=_V_.proxy(this.player,function(currSwf){var el=iDoc.getElementById(currSwf),player=this,tech=player.tech;tech.el=el;_V_.addEvent(el,"click",tech.proxy(tech.onClick));_V_.flash.checkReady(tech)});iWin.events=_V_.proxy(this.player,function(swfID,eventName,other){var player=this;if(player&&player.techName=="flash"){player.triggerEvent(eventName)}});iWin.errors=_V_.proxy(this.player,function(swfID,eventName){_V_.log("Flash Error",eventName)})}));placeHolder.parentNode.replaceChild(iFrm,placeHolder)}else{_V_.flash.embed(options.swf,placeHolder,flashVars,params,attributes)}},destroy:function(){this.el.parentNode.removeChild(this.el)},play:function(){this.el.vjs_play()},pause:function(){this.el.vjs_pause()},src:function(src){this.el.vjs_src(src);if(this.player.autoplay){var tech=this;setTimeout(function(){tech.play()},0)}},load:function(){this.el.vjs_load()},poster:function(){this.el.vjs_getProperty("poster")},buffered:function(){return _V_.createTimeRange(0,this.el.vjs_getProperty("buffered"))},supportsFullScreen:function(){return false},enterFullScreen:function(){return false}});(function(){var api=_V_.flash.prototype,readWrite="preload,currentTime,defaultPlaybackRate,playbackRate,autoplay,loop,mediaGroup,controller,controls,volume,muted,defaultMuted".split(","),readOnly="error,currentSrc,networkState,readyState,seeking,initialTime,duration,startOffsetTime,paused,played,seekable,ended,videoTracks,audioTracks,videoWidth,videoHeight,textTracks".split(","),callOnly="load,play,pause".split(",");createSetter=function(attr){var attrUpper=attr.charAt(0).toUpperCase()+attr.slice(1);api["set"+attrUpper]=function(val){return this.el.vjs_setProperty(attr,val)}},createGetter=function(attr){api[attr]=function(){return this.el.vjs_getProperty(attr)}};_V_.each(readWrite,function(attr){createGetter(attr);createSetter(attr)});_V_.each(readOnly,function(attr){createGetter(attr)})})();_V_.flash.isSupported=function(){return _V_.flash.version()[0]>=10};_V_.flash.canPlaySource=function(srcObj){if(srcObj.type in _V_.flash.prototype.support.formats){return"maybe"}};_V_.flash.prototype.support={formats:{"video/flv":"FLV","video/x-flv":"FLV","video/mp4":"MP4","video/m4v":"MP4"},progressEvent:false,timeupdateEvent:false,fullscreenResize:false,parentResize:!(_V_.ua.match("Firefox"))};_V_.flash.onReady=function(currSwf){var el=_V_.el(currSwf);var player=el.player||el.parentNode.player,tech=player.tech;el.player=player;tech.el=el;tech.addEvent("click",tech.onClick);_V_.flash.checkReady(tech)};_V_.flash.checkReady=function(tech){if(tech.el.vjs_getProperty){tech.triggerReady()}else{setTimeout(function(){_V_.flash.checkReady(tech)},50)}};_V_.flash.onEvent=function(swfID,eventName){var player=_V_.el(swfID).player;player.triggerEvent(eventName)};_V_.flash.onError=function(swfID,err){_V_.log("Flash Error",err,swfID)};_V_.flash.version=function(){var version="0,0,0";try{version=new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version").replace(/\D+/g,",").match(/^,?(.+),?$/)[1]}catch(e){try{if(navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){version=(navigator.plugins["Shockwave Flash 2.0"]||navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g,",").match(/^,?(.+),?$/)[1]}}catch(e){}}return version.split(",")};_V_.flash.embed=function(swf,placeHolder,flashVars,params,attributes){var code=_V_.flash.getEmbedCode(swf,flashVars,params,attributes),obj=_V_.createElement("div",{innerHTML:code}).childNodes[0],par=placeHolder.parentNode;placeHolder.parentNode.replaceChild(obj,placeHolder);if(_V_.isIE()){var newObj=par.childNodes[0];setTimeout(function(){newObj.style.display="block"},1000)}return obj};_V_.flash.getEmbedCode=function(swf,flashVars,params,attributes){var objTag='<object type="application/x-shockwave-flash"',flashVarsString="",paramsString="";attrsString="";if(flashVars){_V_.eachProp(flashVars,function(key,val){flashVarsString+=(key+"="+val+"&amp;")})}params=_V_.merge({movie:swf,flashvars:flashVarsString,allowScriptAccess:"always",allowNetworking:"all"},params);_V_.eachProp(params,function(key,val){paramsString+='<param name="'+key+'" value="'+val+'" />'});attributes=_V_.merge({data:swf,width:"100%",height:"100%"},attributes);_V_.eachProp(attributes,function(key,val){attrsString+=(key+'="'+val+'" ')});return objTag+attrsString+">"+paramsString+"</object>"};_V_.Track=function(attributes,player){this.player=player;this.src=attributes.src;this.kind=attributes.kind;this.srclang=attributes.srclang;this.label=attributes.label;this["default"]=attributes["default"];this.title=attributes.title;this.cues=[];this.currentCue=false;this.lastCueIndex=0;player.addEvent("timeupdate",_V_.proxy(this,this.update));player.addEvent("ended",_V_.proxy(this,function(){this.lastCueIndex=0}));_V_.get(attributes.src,_V_.proxy(this,this.parseCues))};_V_.Track.prototype={parseCues:function(srcContent){var cue,time,text,lines=srcContent.split("\n"),line="";for(var i=0;i<lines.length;i++){line=_V_.trim(lines[i]);if(line){cue={id:line,index:this.cues.length};line=_V_.trim(lines[++i]);time=line.split(" --> ");cue.startTime=this.parseCueTime(time[0]);cue.endTime=this.parseCueTime(time[1]);text=[];for(var j=i;j<lines.length;j++){line=_V_.trim(lines[++i]);if(!line){break}text.push(line)}cue.text=text.join("<br/>");this.cues.push(cue)}}},parseCueTime:function(timeText){var parts=timeText.split(":"),time=0;time+=parseFloat(parts[0])*60*60;time+=parseFloat(parts[1])*60;var seconds=parts[2].split(/\.|,/);time+=parseFloat(seconds[0]);ms=parseFloat(seconds[1]);if(ms){time+=ms/1000}return time},update:function(){if(this.cues&&this.cues.length>0){var time=this.player.currentTime();if(!this.currentCue||this.currentCue.startTime>=time||this.currentCue.endTime<time){var newSubIndex=false,reverse=(this.cues[this.lastCueIndex].startTime>time),i=this.lastCueIndex-(reverse?1:0);while(true){if(reverse){if(i<0||this.cues[i].endTime<time){break}if(this.cues[i].startTime<time){newSubIndex=i;break}i--}else{if(i>=this.cues.length||this.cues[i].startTime>time){break}if(this.cues[i].endTime>time){newSubIndex=i;break}i++}}if(newSubIndex!==false){this.currentCue=this.cues[newSubIndex];this.lastCueIndex=newSubIndex;this.updatePlayer(this.currentCue.text)}else{if(this.currentCue){this.currentCue=false;this.updatePlayer("")}}}}},updatePlayer:function(text){this.player.textTrackValue(this.kind,text)}};_V_.addEvent(window,"load",function(){_V_.windowLoaded=true});_V_.autoSetup();window.VideoJS=window._V_=VideoJS})(window);
+(function(window,undefined){var document=window.document;document.createElement("video");document.createElement("audio");var VideoJS=function(id,addOptions,ready){var tag;if(typeof id=="string"){if(id.indexOf("#")===0){id=id.slice(1)}if(_V_.players[id]){return _V_.players[id]}else{tag=_V_.el(id)}}else{tag=id}if(!tag||!tag.nodeName){throw new TypeError("The element or ID supplied is not valid. (VideoJS)")}return tag.player||new _V_.Player(tag,addOptions,ready)},_V_=VideoJS,CDN_VERSION="GENERATED_CDN_VSN";VideoJS.players={};VideoJS.options={techOrder:["html5","flash"],html5:{},flash:{swf:"http://vjs.zencdn.net/c/video-js.swf"},width:300,height:150,defaultVolume:0,components:{posterImage:{},textTrackDisplay:{},loadingSpinner:{},bigPlayButton:{},controlBar:{}}};if(CDN_VERSION!="GENERATED_CDN_VSN"){_V_.options.flash.swf="http://vjs.zencdn.net/"+CDN_VERSION+"/video-js.swf"}_V_.merge=function(obj1,obj2,safe){if(!obj2){obj2={}}for(var attrname in obj2){if(obj2.hasOwnProperty(attrname)&&(!safe||!obj1.hasOwnProperty(attrname))){obj1[attrname]=obj2[attrname]}}return obj1};_V_.extend=function(obj){this.merge(this,obj,true)};_V_.extend({tech:{},controlSets:{},isIE:function(){return !+"\v1"},isFF:function(){return !!_V_.ua.match("Firefox")},isIPad:function(){return navigator.userAgent.match(/iPad/i)!==null},isIPhone:function(){return navigator.userAgent.match(/iPhone/i)!==null},isIOS:function(){return VideoJS.isIPhone()||VideoJS.isIPad()},iOSVersion:function(){var match=navigator.userAgent.match(/OS (\d+)_/i);if(match&&match[1]){return match[1]}},isAndroid:function(){return navigator.userAgent.match(/Android.*AppleWebKit/i)!==null},androidVersion:function(){var match=navigator.userAgent.match(/Android (\d+)\./i);if(match&&match[1]){return match[1]}},testVid:document.createElement("video"),ua:navigator.userAgent,support:{},each:function(arr,fn){if(!arr||arr.length===0){return}for(var i=0,j=arr.length;i<j;i++){fn.call(this,arr[i],i)}},eachProp:function(obj,fn){if(!obj){return}for(var name in obj){if(obj.hasOwnProperty(name)){fn.call(this,name,obj[name])}}},el:function(id){return document.getElementById(id)},createElement:function(tagName,attributes){var el=document.createElement(tagName),attrname;for(attrname in attributes){if(attributes.hasOwnProperty(attrname)){if(attrname.indexOf("-")!==-1){el.setAttribute(attrname,attributes[attrname])}else{el[attrname]=attributes[attrname]}}}return el},insertFirst:function(node,parent){if(parent.firstChild){parent.insertBefore(node,parent.firstChild)}else{parent.appendChild(node)}},addClass:function(element,classToAdd){if((" "+element.className+" ").indexOf(" "+classToAdd+" ")==-1){element.className=element.className===""?classToAdd:element.className+" "+classToAdd}},removeClass:function(element,classToRemove){if(element.className.indexOf(classToRemove)==-1){return}var classNames=element.className.split(" ");classNames.splice(classNames.indexOf(classToRemove),1);element.className=classNames.join(" ")},remove:function(item,array){if(!array){return}var i=array.indexOf(item);if(i!=-1){return array.splice(i,1)}},blockTextSelection:function(){document.body.focus();document.onselectstart=function(){return false}},unblockTextSelection:function(){document.onselectstart=function(){return true}},formatTime:function(seconds,guide){guide=guide||seconds;var s=Math.floor(seconds%60),m=Math.floor(seconds/60%60),h=Math.floor(seconds/3600),gm=Math.floor(guide/60%60),gh=Math.floor(guide/3600);h=(h>0||gh>0)?h+":":"";m=(((h||gm>=10)&&m<10)?"0"+m:m)+":";s=(s<10)?"0"+s:s;return h+m+s},uc:function(string){return string.charAt(0).toUpperCase()+string.slice(1)},getRelativePosition:function(x,relativeElement){return Math.max(0,Math.min(1,(x-_V_.findPosX(relativeElement))/relativeElement.offsetWidth))},getComputedStyleValue:function(element,style){return window.getComputedStyle(element,null).getPropertyValue(style)},trim:function(string){return string.toString().replace(/^\s+/,"").replace(/\s+$/,"")},round:function(num,dec){if(!dec){dec=0}return Math.round(num*Math.pow(10,dec))/Math.pow(10,dec)},isEmpty:function(object){for(var prop in object){return false}return true},createTimeRange:function(start,end){return{length:1,start:function(){return start},end:function(){return end}}},cache:{},guid:1,expando:"vdata"+(new Date).getTime(),getData:function(elem){var id=elem[_V_.expando];if(!id){id=elem[_V_.expando]=_V_.guid++;_V_.cache[id]={}}return _V_.cache[id]},removeData:function(elem){var id=elem[_V_.expando];if(!id){return}delete _V_.cache[id];try{delete elem[_V_.expando]}catch(e){if(elem.removeAttribute){elem.removeAttribute(_V_.expando)}else{elem[_V_.expando]=null}}},proxy:function(context,fn,uid){if(!fn.guid){fn.guid=_V_.guid++}var ret=function(){return fn.apply(context,arguments)};ret.guid=(uid)?uid+"_"+fn.guid:fn.guid;return ret},get:function(url,onSuccess,onError){var local=(url.indexOf("file:")==0||(window.location.href.indexOf("file:")==0&&url.indexOf("http:")==-1));if(typeof XMLHttpRequest=="undefined"){XMLHttpRequest=function(){try{return new ActiveXObject("Msxml2.XMLHTTP.6.0")}catch(e){}try{return new ActiveXObject("Msxml2.XMLHTTP.3.0")}catch(f){}try{return new ActiveXObject("Msxml2.XMLHTTP")}catch(g){}throw new Error("This browser does not support XMLHttpRequest.")}}var request=new XMLHttpRequest();try{request.open("GET",url)}catch(e){_V_.log("VideoJS XMLHttpRequest (open)",e);return false}request.onreadystatechange=_V_.proxy(this,function(){if(request.readyState==4){if(request.status==200||local&&request.status==0){onSuccess(request.responseText)}else{if(onError){onError()}}}});try{request.send()}catch(e){_V_.log("VideoJS XMLHttpRequest (send)",e);if(onError){onError(e)}}},setLocalStorage:function(key,value){var localStorage=window.localStorage||false;if(!localStorage){return}try{localStorage[key]=value}catch(e){if(e.code==22||e.code==1014){_V_.log("LocalStorage Full (VideoJS)",e)}else{_V_.log("LocalStorage Error (VideoJS)",e)}}},getAbsoluteURL:function(url){if(!url.match(/^https?:\/\//)){url=_V_.createElement("div",{innerHTML:'<a href="'+url+'">x</a>'}).firstChild.href}return url}});_V_.log=function(){_V_.log.history=_V_.log.history||[];_V_.log.history.push(arguments);if(window.console){arguments.callee=arguments.callee.caller;var newarr=[].slice.call(arguments);(typeof console.log==="object"?_V_.log.apply.call(console.log,console,newarr):console.log.apply(console,newarr))}};(function(b){function c(){}for(var d="assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,timeStamp,profile,profileEnd,time,timeEnd,trace,warn".split(","),a;a=d.pop();){b[a]=b[a]||c}})((function(){try{console.log();return window.console}catch(err){return window.console={}}})());if("getBoundingClientRect" in document.documentElement){_V_.findPosX=function(el){var box;try{box=el.getBoundingClientRect()}catch(e){}if(!box){return 0}var docEl=document.documentElement,body=document.body,clientLeft=docEl.clientLeft||body.clientLeft||0,scrollLeft=window.pageXOffset||body.scrollLeft,left=box.left+scrollLeft-clientLeft;return left}}else{_V_.findPosX=function(el){var curleft=el.offsetLeft;while(el=obj.offsetParent){if(el.className.indexOf("video-js")==-1){}else{}curleft+=el.offsetLeft}return curleft}}if(!Array.prototype.indexOf){Array.prototype.indexOf=function(searchElement){if(this===void 0||this===null){throw new TypeError()}var t=Object(this);var len=t.length>>>0;if(len===0){return -1}var n=0;if(arguments.length>0){n=Number(arguments[1]);if(n!==n){n=0}else{if(n!==0&&n!==(1/0)&&n!==-(1/0)){n=(n>0||-1)*Math.floor(Math.abs(n))}}}if(n>=len){return -1}var k=n>=0?n:Math.max(len-Math.abs(n),0);for(;k<len;k++){if(k in t&&t[k]===searchElement){return k}}return -1}}var JSON;if(!JSON){JSON={}}(function(){var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;if(typeof JSON.parse!=="function"){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==="object"){for(k in value){if(Object.prototype.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v}else{delete value[k]}}}}return reviver.call(holder,key,value)}text=String(text);cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver==="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")}}}());_V_.extend({addEvent:function(elem,type,fn){var data=_V_.getData(elem),handlers;if(data&&!data.handler){data.handler=function(event){event=_V_.fixEvent(event);var handlers=_V_.getData(elem).events[event.type];if(handlers){var handlersCopy=[];_V_.each(handlers,function(handler,i){handlersCopy[i]=handler});for(var i=0,l=handlersCopy.length;i<l;i++){handlersCopy[i].call(elem,event)}}}}if(!data.events){data.events={}}handlers=data.events[type];if(!handlers){handlers=data.events[type]=[];if(document.addEventListener){elem.addEventListener(type,data.handler,false)}else{if(document.attachEvent){elem.attachEvent("on"+type,data.handler)}}}if(!fn.guid){fn.guid=_V_.guid++}handlers.push(fn)},removeEvent:function(elem,type,fn){var data=_V_.getData(elem),handlers;if(!data.events){return}if(!type){for(type in data.events){_V_.cleanUpEvents(elem,type)}return}handlers=data.events[type];if(!handlers){return}if(fn&&fn.guid){for(var i=0;i<handlers.length;i++){if(handlers[i].guid===fn.guid){handlers.splice(i--,1)}}}_V_.cleanUpEvents(elem,type)},cleanUpEvents:function(elem,type){var data=_V_.getData(elem);if(data.events[type].length===0){delete data.events[type];if(document.removeEventListener){elem.removeEventListener(type,data.handler,false)}else{if(document.detachEvent){elem.detachEvent("on"+type,data.handler)}}}if(_V_.isEmpty(data.events)){delete data.events;delete data.handler}if(_V_.isEmpty(data)){_V_.removeData(elem)}},fixEvent:function(event){if(event[_V_.expando]){return event}var originalEvent=event;event=new _V_.Event(originalEvent);for(var i=_V_.Event.props.length,prop;i;){prop=_V_.Event.props[--i];event[prop]=originalEvent[prop]}if(!event.target){event.target=event.srcElement||document}if(event.target.nodeType===3){event.target=event.target.parentNode}if(!event.relatedTarget&&event.fromElement){event.relatedTarget=event.fromElement===event.target?event.toElement:event.fromElement}if(event.pageX==null&&event.clientX!=null){var eventDocument=event.target.ownerDocument||document,doc=eventDocument.documentElement,body=eventDocument.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc&&doc.clientLeft||body&&body.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc&&doc.clientTop||body&&body.clientTop||0)}if(event.which==null&&(event.charCode!=null||event.keyCode!=null)){event.which=event.charCode!=null?event.charCode:event.keyCode}if(!event.metaKey&&event.ctrlKey){event.metaKey=event.ctrlKey}if(!event.which&&event.button!==undefined){event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)))}return event},triggerEvent:function(elem,event){var data=_V_.getData(elem),parent=elem.parentNode||elem.ownerDocument,type=event.type||event,handler;if(data){handler=data.handler}event=typeof event==="object"?event[_V_.expando]?event:new _V_.Event(type,event):new _V_.Event(type);event.type=type;if(handler){handler.call(elem,event)}event.result=undefined;event.target=elem},one:function(elem,type,fn){_V_.addEvent(elem,type,function(){_V_.removeEvent(elem,type,arguments.callee);fn.apply(this,arguments)})}});_V_.Event=function(src,props){if(src&&src.type){this.originalEvent=src;this.type=src.type;this.isDefaultPrevented=(src.defaultPrevented||src.returnValue===false||src.getPreventDefault&&src.getPreventDefault())?returnTrue:returnFalse}else{this.type=src}if(props){_V_.merge(this,props)}this.timeStamp=(new Date).getTime();this[_V_.expando]=true};_V_.Event.prototype={preventDefault:function(){this.isDefaultPrevented=returnTrue;var e=this.originalEvent;if(!e){return}if(e.preventDefault){e.preventDefault()}else{e.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=returnTrue;var e=this.originalEvent;if(!e){return}if(e.stopPropagation){e.stopPropagation()}e.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=returnTrue;this.stopPropagation()},isDefaultPrevented:returnFalse,isPropagationStopped:returnFalse,isImmediatePropagationStopped:returnFalse};_V_.Event.props="altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" ");function returnTrue(){return true}function returnFalse(){return false}(function(){var initializing=false,fnTest=/xyz/.test(function(){xyz})?/\b_super\b/:/.*/;_V_.Class=function(){};_V_.Class.extend=function(prop){var _super=this.prototype;initializing=true;var prototype=new this();initializing=false;for(var name in prop){prototype[name]=typeof prop[name]=="function"&&typeof _super[name]=="function"&&fnTest.test(prop[name])?(function(name,fn){return function(){var tmp=this._super;this._super=_super[name];var ret=fn.apply(this,arguments);this._super=tmp;return ret}})(name,prop[name]):prop[name]}function Class(){if(!initializing&&this.init){return this.init.apply(this,arguments)}else{if(!initializing){return arguments.callee.prototype.init()}}}Class.prototype=prototype;Class.constructor=Class;Class.extend=arguments.callee;return Class}})();_V_.Component=_V_.Class.extend({init:function(player,options){this.player=player;options=this.options=_V_.merge(this.options||{},options);if(options.el){this.el=options.el}else{this.el=this.createElement()}this.initComponents()},destroy:function(){},createElement:function(type,attrs){return _V_.createElement(type||"div",attrs)},buildCSSClass:function(){return""},initComponents:function(){var options=this.options;if(options&&options.components){this.eachProp(options.components,function(name,opts){var tempAdd=this.proxy(function(){this[name]=this.addComponent(name,opts)});if(opts.loadEvent){this.one(opts.loadEvent,tempAdd)}else{tempAdd()}})}},addComponent:function(name,options){var component,componentClass;if(typeof name=="string"){options=options||{};componentClass=options.componentClass||_V_.uc(name);component=new _V_[componentClass](this.player||this,options)}else{component=name}this.el.appendChild(component.el);return component},removeComponent:function(component){this.el.removeChild(component.el)},show:function(){this.el.style.display="block"},hide:function(){this.el.style.display="none"},fadeIn:function(){this.removeClass("vjs-fade-out");this.addClass("vjs-fade-in")},fadeOut:function(){this.removeClass("vjs-fade-in");this.addClass("vjs-fade-out")},lockShowing:function(){var style=this.el.style;style.display="block";style.opacity=1;style.visiblity="visible"},unlockShowing:function(){var style=this.el.style;style.display="";style.opacity="";style.visiblity=""},addClass:function(classToAdd){_V_.addClass(this.el,classToAdd)},removeClass:function(classToRemove){_V_.removeClass(this.el,classToRemove)},addEvent:function(type,fn,uid){return _V_.addEvent(this.el,type,_V_.proxy(this,fn))},removeEvent:function(type,fn){return _V_.removeEvent(this.el,type,fn)},triggerEvent:function(type,e){return _V_.triggerEvent(this.el,type,e)},one:function(type,fn){_V_.one(this.el,type,_V_.proxy(this,fn))},ready:function(fn){if(!fn){return this}if(this.isReady){fn.call(this)}else{if(this.readyQueue===undefined){this.readyQueue=[]}this.readyQueue.push(fn)}return this},triggerReady:function(){this.isReady=true;if(this.readyQueue&&this.readyQueue.length>0){this.each(this.readyQueue,function(fn){fn.call(this)});this.readyQueue=[];this.triggerEvent("ready")}},each:function(arr,fn){_V_.each.call(this,arr,fn)},eachProp:function(obj,fn){_V_.eachProp.call(this,obj,fn)},extend:function(obj){_V_.merge(this,obj)},proxy:function(fn,uid){return _V_.proxy(this,fn,uid)}});_V_.Player=_V_.Component.extend({init:function(tag,addOptions,ready){this.tag=tag;var el=this.el=_V_.createElement("div"),options=this.options={};_V_.merge(options,_V_.options);_V_.merge(options,this.getVideoTagSettings());_V_.merge(options,addOptions);this.ready(ready);tag.removeAttribute("controls");tag.removeAttribute("poster");tag.player=el.player=this;tag.parentNode.insertBefore(el,tag);el.appendChild(tag);this.id=el.id=tag.id;el.className=tag.className;tag.id+="_html5_api";tag.className="vjs-tech";_V_.players[el.id]=this;el.setAttribute("width",options.width);el.setAttribute("height",options.height);el.style.width=options.width+"px";el.style.height=options.height+"px";tag.removeAttribute("width");tag.removeAttribute("height");if(tag.hasChildNodes()){for(var i=0,j=tag.childNodes;i<j.length;i++){if(j[i].nodeName=="SOURCE"||j[i].nodeName=="TRACK"){tag.removeChild(j[i])}}}this.values={};this.addClass("vjs-paused");this.addEvent("ended",this.onEnded);this.addEvent("play",this.onPlay);this.addEvent("pause",this.onPause);this.addEvent("progress",this.onProgress);this.addEvent("error",this.onError);if(options.controls){this.ready(function(){this.initComponents()})}this.textTracks=[];if(options.tracks&&options.tracks.length>0){this.addTextTracks(options.tracks)}if(!options.sources||options.sources.length==0){for(var i=0,j=options.techOrder;i<j.length;i++){var techName=j[i],tech=_V_[techName];if(tech.isSupported()){this.loadTech(techName);break}}}else{this.src(options.sources)}},values:{},destroy:function(){this.stopTrackingProgress();this.stopTrackingCurrentTime();_V_.players[this.id]=null;delete _V_.players[this.id];this.tech.destroy();this.el.parentNode.removeChild(this.el)},createElement:function(type,options){},getVideoTagSettings:function(){var options={sources:[],tracks:[]},tag=this.tag,getAttribute="getAttribute";options.src=tag[getAttribute]("src");options.controls=tag[getAttribute]("controls")!==null;options.poster=tag[getAttribute]("poster");options.preload=tag[getAttribute]("preload");options.autoplay=tag[getAttribute]("autoplay")!==null;options.loop=tag[getAttribute]("loop")!==null;options.muted=tag[getAttribute]("muted")!==null;if(this.tag.hasChildNodes()){for(var c,i=0,j=this.tag.childNodes;i<j.length;i++){c=j[i];if(c.nodeName=="SOURCE"){options.sources.push({src:c[getAttribute]("src"),type:c[getAttribute]("type"),media:c[getAttribute]("media"),title:c[getAttribute]("title")})}if(c.nodeName=="TRACK"){options.tracks.push({src:c[getAttribute]("src"),kind:c[getAttribute]("kind"),srclang:c[getAttribute]("srclang"),label:c[getAttribute]("label"),"default":c[getAttribute]("default")!==null,title:c[getAttribute]("title")})}}}return options},loadTech:function(techName,source){if(this.tech){this.unloadTech()}else{if(techName!="html5"&&this.tag){this.el.removeChild(this.tag);this.tag=false}}this.techName=techName;this.isReady=false;var techReady=function(){this.player.triggerReady();if(!this.support.progressEvent){this.player.manualProgressOn()}if(!this.support.timeupdateEvent){this.player.manualTimeUpdatesOn()}};var techOptions=_V_.merge({source:source,parentEl:this.el},this.options[techName]);if(source){if(source.src==this.values.src&&this.values.currentTime>0){techOptions.startTime=this.values.currentTime}this.values.src=source.src}this.tech=new _V_[techName](this,techOptions);this.tech.ready(techReady)},unloadTech:function(){this.tech.destroy();if(this.manualProgress){this.manualProgressOff()}if(this.manualTimeUpdates){this.manualTimeUpdatesOff()}this.tech=false},manualProgressOn:function(){this.manualProgress=true;this.trackProgress();this.tech.addEvent("progress",function(){this.removeEvent("progress",arguments.callee);this.support.progressEvent=true;this.player.manualProgressOff()})},manualProgressOff:function(){this.manualProgress=false;this.stopTrackingProgress()},trackProgress:function(){this.progressInterval=setInterval(_V_.proxy(this,function(){if(this.values.bufferEnd<this.buffered().end(0)){this.triggerEvent("progress")}else{if(this.bufferedPercent()==1){this.stopTrackingProgress();this.triggerEvent("progress")}}}),500)},stopTrackingProgress:function(){clearInterval(this.progressInterval)},manualTimeUpdatesOn:function(){this.manualTimeUpdates=true;this.addEvent("play",this.trackCurrentTime);this.addEvent("pause",this.stopTrackingCurrentTime);this.tech.addEvent("timeupdate",function(){this.removeEvent("timeupdate",arguments.callee);this.support.timeupdateEvent=true;this.player.manualTimeUpdatesOff()})},manualTimeUpdatesOff:function(){this.manualTimeUpdates=false;this.stopTrackingCurrentTime();this.removeEvent("play",this.trackCurrentTime);this.removeEvent("pause",this.stopTrackingCurrentTime)},trackCurrentTime:function(){if(this.currentTimeInterval){this.stopTrackingCurrentTime()}this.currentTimeInterval=setInterval(_V_.proxy(this,function(){this.triggerEvent("timeupdate")}),250)},stopTrackingCurrentTime:function(){clearInterval(this.currentTimeInterval)},onEnded:function(){if(this.options.loop){this.currentTime(0);this.play()}else{this.pause();this.currentTime(0);this.pause()}},onPlay:function(){_V_.removeClass(this.el,"vjs-paused");_V_.addClass(this.el,"vjs-playing")},onPause:function(){_V_.removeClass(this.el,"vjs-playing");_V_.addClass(this.el,"vjs-paused")},onProgress:function(){if(this.bufferedPercent()==1){this.triggerEvent("loadedalldata")}},onError:function(e){_V_.log("Video Error",e)},techCall:function(method,arg){if(!this.tech.isReady){this.tech.ready(function(){this[method](arg)})}else{try{this.tech[method](arg)}catch(e){_V_.log(e)}}},techGet:function(method){if(this.tech.isReady){try{return this.tech[method]()}catch(e){if(this.tech[method]===undefined){_V_.log("Video.js: "+method+" method not defined for "+this.techName+" playback technology.",e)}else{if(e.name=="TypeError"){_V_.log("Video.js: "+method+" unavailable on "+this.techName+" playback technology element.",e);this.tech.isReady=false}else{_V_.log(e)}}}}return},play:function(){this.techCall("play");return this},pause:function(){this.techCall("pause");return this},paused:function(){return(this.techGet("paused")===false)?false:true},currentTime:function(seconds){if(seconds!==undefined){this.values.lastSetCurrentTime=seconds;this.techCall("setCurrentTime",seconds);if(this.manualTimeUpdates){this.triggerEvent("timeupdate")}return this}return this.values.currentTime=(this.techGet("currentTime")||0)},duration:function(){return parseFloat(this.techGet("duration"))},remainingTime:function(){return this.duration()-this.currentTime()},buffered:function(){var buffered=this.techGet("buffered"),start=0,end=this.values.bufferEnd=this.values.bufferEnd||0,timeRange;if(buffered&&buffered.length>0&&buffered.end(0)!==end){end=buffered.end(0);this.values.bufferEnd=end}return _V_.createTimeRange(start,end)},bufferedPercent:function(){return(this.duration())?this.buffered().end(0)/this.duration():0},volume:function(percentAsDecimal){var vol;if(percentAsDecimal!==undefined){vol=Math.max(0,Math.min(1,parseFloat(percentAsDecimal)));this.values.volume=vol;this.techCall("setVolume",vol);_V_.setLocalStorage("volume",vol);return this}vol=parseFloat(this.techGet("volume"));return(isNaN(vol))?1:vol},muted:function(muted){if(muted!==undefined){this.techCall("setMuted",muted);return this}return this.techGet("muted")||false},width:function(width,skipListeners){if(width!==undefined){this.el.width=width;this.el.style.width=width+"px";if(!skipListeners){this.triggerEvent("resize")}return this}return parseInt(this.el.getAttribute("width"))},height:function(height){if(height!==undefined){this.el.height=height;this.el.style.height=height+"px";this.triggerEvent("resize");return this}return parseInt(this.el.getAttribute("height"))},size:function(width,height){return this.width(width,true).height(height)},supportsFullScreen:function(){return this.techGet("supportsFullScreen")||false},requestFullScreen:function(){var requestFullScreen=_V_.support.requestFullScreen;this.isFullScreen=true;if(requestFullScreen){_V_.addEvent(document,requestFullScreen.eventName,this.proxy(function(){this.isFullScreen=document[requestFullScreen.isFullScreen];if(this.isFullScreen==false){_V_.removeEvent(document,requestFullScreen.eventName,arguments.callee)}this.triggerEvent("fullscreenchange")}));if(this.tech.support.fullscreenResize===false&&this.options.flash.iFrameMode!=true){this.pause();this.unloadTech();_V_.addEvent(document,requestFullScreen.eventName,this.proxy(function(){_V_.removeEvent(document,requestFullScreen.eventName,arguments.callee);this.loadTech(this.techName,{src:this.values.src})}));this.el[requestFullScreen.requestFn]()}else{this.el[requestFullScreen.requestFn]()}}else{if(this.tech.supportsFullScreen()){this.triggerEvent("fullscreenchange");this.techCall("enterFullScreen")}else{this.triggerEvent("fullscreenchange");this.enterFullWindow()}}return this},cancelFullScreen:function(){var requestFullScreen=_V_.support.requestFullScreen;this.isFullScreen=false;if(requestFullScreen){if(this.tech.support.fullscreenResize===false&&this.options.flash.iFrameMode!=true){this.pause();this.unloadTech();_V_.addEvent(document,requestFullScreen.eventName,this.proxy(function(){_V_.removeEvent(document,requestFullScreen.eventName,arguments.callee);this.loadTech(this.techName,{src:this.values.src})}));document[requestFullScreen.cancelFn]()}else{document[requestFullScreen.cancelFn]()}}else{if(this.tech.supportsFullScreen()){this.techCall("exitFullScreen");this.triggerEvent("fullscreenchange")}else{this.exitFullWindow();this.triggerEvent("fullscreenchange")}}return this},enterFullWindow:function(){this.isFullWindow=true;this.docOrigOverflow=document.documentElement.style.overflow;_V_.addEvent(document,"keydown",_V_.proxy(this,this.fullWindowOnEscKey));document.documentElement.style.overflow="hidden";_V_.addClass(document.body,"vjs-full-window");_V_.addClass(this.el,"vjs-fullscreen");this.triggerEvent("enterFullWindow")},fullWindowOnEscKey:function(event){if(event.keyCode==27){if(this.isFullScreen==true){this.cancelFullScreen()}else{this.exitFullWindow()}}},exitFullWindow:function(){this.isFullWindow=false;_V_.removeEvent(document,"keydown",this.fullWindowOnEscKey);document.documentElement.style.overflow=this.docOrigOverflow;_V_.removeClass(document.body,"vjs-full-window");_V_.removeClass(this.el,"vjs-fullscreen");this.triggerEvent("exitFullWindow")},selectSource:function(sources){for(var i=0,j=this.options.techOrder;i<j.length;i++){var techName=j[i],tech=_V_[techName];if(tech.isSupported()){for(var a=0,b=sources;a<b.length;a++){var source=b[a];if(tech.canPlaySource.call(this,source)){return{source:source,tech:techName}}}}}return false},src:function(source){if(source instanceof Array){var sourceTech=this.selectSource(source),source,techName;if(sourceTech){source=sourceTech.source;techName=sourceTech.tech;if(techName==this.techName){this.src(source)}else{this.loadTech(techName,source)}}else{_V_.log("No compatible source and playback technology were found.")}}else{if(source instanceof Object){if(_V_[this.techName].canPlaySource(source)){this.src(source.src)}else{this.src([source])}}else{this.values.src=source;if(!this.isReady){this.ready(function(){this.src(source)})}else{this.techCall("src",source);if(this.options.preload=="auto"){this.load()}if(this.options.autoplay){this.play()}}}}return this},load:function(){this.techCall("load");return this},currentSrc:function(){return this.techGet("currentSrc")||this.values.src||""},preload:function(value){if(value!==undefined){this.techCall("setPreload",value);this.options.preload=value;return this}return this.techGet("preload")},autoplay:function(value){if(value!==undefined){this.techCall("setAutoplay",value);this.options.autoplay=value;return this}return this.techGet("autoplay",value)},loop:function(value){if(value!==undefined){this.techCall("setLoop",value);this.options.loop=value;return this}return this.techGet("loop")},controls:function(){return this.options.controls},poster:function(){return this.techGet("poster")},error:function(){return this.techGet("error")},ended:function(){return this.techGet("ended")}});(function(){var requestFn,cancelFn,eventName,isFullScreen,playerProto=_V_.Player.prototype;if(document.cancelFullscreen!==undefined){requestFn="requestFullscreen";cancelFn="exitFullscreen";eventName="fullscreenchange";isFullScreen="fullScreen"}else{_V_.each(["moz","webkit"],function(prefix){if((prefix!="moz"||document.mozFullScreenEnabled)&&document[prefix+"CancelFullScreen"]!==undefined){requestFn=prefix+"RequestFullScreen";cancelFn=prefix+"CancelFullScreen";eventName=prefix+"fullscreenchange";if(prefix=="webkit"){isFullScreen=prefix+"IsFullScreen"}else{isFullScreen=prefix+"FullScreen"}}})}if(requestFn){_V_.support.requestFullScreen={requestFn:requestFn,cancelFn:cancelFn,eventName:eventName,isFullScreen:isFullScreen}}})();_V_.PlaybackTech=_V_.Component.extend({init:function(player,options){},onClick:function(){if(this.player.options.controls){_V_.PlayToggle.prototype.onClick.call(this)}}});_V_.apiMethods="play,pause,paused,currentTime,setCurrentTime,duration,buffered,volume,setVolume,muted,setMuted,width,height,supportsFullScreen,enterFullScreen,src,load,currentSrc,preload,setPreload,autoplay,setAutoplay,loop,setLoop,error,networkState,readyState,seeking,initialTime,startOffsetTime,played,seekable,ended,videoTracks,audioTracks,videoWidth,videoHeight,textTracks,defaultPlaybackRate,playbackRate,mediaGroup,controller,controls,defaultMuted".split(",");_V_.each(_V_.apiMethods,function(methodName){_V_.PlaybackTech.prototype[methodName]=function(){throw new Error("The '"+methodName+"' method is not available on the playback technology's API")}});_V_.html5=_V_.PlaybackTech.extend({init:function(player,options,ready){this.player=player;this.el=this.createElement();this.ready(ready);this.addEvent("click",this.proxy(this.onClick));var source=options.source;if(source&&this.el.currentSrc==source.src){player.triggerEvent("loadstart")}else{if(source){this.el.src=source.src}}player.ready(function(){if(this.options.autoplay&&this.paused()){this.tag.poster=null;this.play()}});this.setupTriggers();this.triggerReady()},destroy:function(){this.player.tag=false;this.removeTriggers();this.el.parentNode.removeChild(this.el)},createElement:function(){var html5=_V_.html5,player=this.player,el=player.tag,newEl;if(!el||this.support.movingElementInDOM===false){if(el){player.el.removeChild(el)}newEl=_V_.createElement("video",{id:el.id||player.el.id+"_html5_api",className:el.className||"vjs-tech"});el=newEl;_V_.insertFirst(el,player.el)}_V_.each(["autoplay","preload","loop","muted"],function(attr){if(player.options[attr]!==null){el[attr]=player.options[attr]}},this);return el},setupTriggers:function(){_V_.each.call(this,_V_.html5.events,function(type){_V_.addEvent(this.el,type,_V_.proxy(this.player,this.eventHandler))})},removeTriggers:function(){_V_.each.call(this,_V_.html5.events,function(type){_V_.removeEvent(this.el,type,_V_.proxy(this.player,this.eventHandler))})},eventHandler:function(e){e.stopPropagation();this.triggerEvent(e)},play:function(){this.el.play()},pause:function(){this.el.pause()},paused:function(){return this.el.paused},currentTime:function(){return this.el.currentTime},setCurrentTime:function(seconds){try{this.el.currentTime=seconds}catch(e){_V_.log(e,"Video isn't ready. (VideoJS)")}},duration:function(){return this.el.duration||0},buffered:function(){return this.el.buffered},volume:function(){return this.el.volume},setVolume:function(percentAsDecimal){this.el.volume=percentAsDecimal},muted:function(){return this.el.muted},setMuted:function(muted){this.el.muted=muted},width:function(){return this.el.offsetWidth},height:function(){return this.el.offsetHeight},supportsFullScreen:function(){if(typeof this.el.webkitEnterFullScreen=="function"){if(!navigator.userAgent.match("Chrome")&&!navigator.userAgent.match("Mac OS X 10.5")){return true}}return false},enterFullScreen:function(){try{this.el.webkitEnterFullScreen()}catch(e){if(e.code==11){_V_.log("VideoJS: Video not ready.")}}},src:function(src){this.el.src=src},load:function(){this.el.load()},currentSrc:function(){return this.el.currentSrc},preload:function(){return this.el.preload},setPreload:function(val){this.el.preload=val},autoplay:function(){return this.el.autoplay},setAutoplay:function(val){this.el.autoplay=val},loop:function(){return this.el.loop},setLoop:function(val){this.el.loop=val},error:function(){return this.el.error},seeking:function(){return this.el.seeking},ended:function(){return this.el.ended},controls:function(){return this.player.options.controls},defaultMuted:function(){return this.el.defaultMuted}});_V_.html5.isSupported=function(){return !!document.createElement("video").canPlayType};_V_.html5.canPlaySource=function(srcObj){return !!document.createElement("video").canPlayType(srcObj.type)};_V_.html5.events="loadstart,suspend,abort,error,emptied,stalled,loadedmetadata,loadeddata,canplay,canplaythrough,playing,waiting,seeking,seeked,ended,durationchange,timeupdate,progress,play,pause,ratechange,volumechange".split(",");_V_.html5.prototype.support={fullscreen:(typeof _V_.testVid.webkitEnterFullScreen!==undefined)?(!_V_.ua.match("Chrome")&&!_V_.ua.match("Mac OS X 10.5")?true:false):false,movingElementInDOM:!_V_.isIOS()};if(_V_.isAndroid()){if(_V_.androidVersion()<3){document.createElement("video").constructor.prototype.canPlayType=function(type){return(type&&type.toLowerCase().indexOf("video/mp4")!=-1)?"maybe":""}}}_V_.flash=_V_.PlaybackTech.extend({init:function(player,options){this.player=player;var source=options.source,parentEl=options.parentEl,placeHolder=this.el=_V_.createElement("div",{id:parentEl.id+"_temp_flash"}),objId=player.el.id+"_flash_api",playerOptions=player.options,flashVars=_V_.merge({readyFunction:"_V_.flash.onReady",eventProxyFunction:"_V_.flash.onEvent",errorEventProxyFunction:"_V_.flash.onError",autoplay:playerOptions.autoplay,preload:playerOptions.preload,loop:playerOptions.loop,muted:playerOptions.muted},options.flashVars),params=_V_.merge({wmode:"opaque",bgcolor:"#000000"},options.params),attributes=_V_.merge({id:objId,name:objId,"class":"vjs-tech"},options.attributes);if(source){flashVars.src=encodeURIComponent(_V_.getAbsoluteURL(source.src))}_V_.insertFirst(placeHolder,parentEl);if(options.startTime){this.ready(function(){this.load();this.play();this.currentTime(options.startTime)})}if(options.iFrameMode==true&&!_V_.isFF){var iFrm=_V_.createElement("iframe",{id:objId+"_iframe",name:objId+"_iframe",className:"vjs-tech",scrolling:"no",marginWidth:0,marginHeight:0,frameBorder:0});flashVars.readyFunction="ready";flashVars.eventProxyFunction="events";flashVars.errorEventProxyFunction="errors";_V_.addEvent(iFrm,"load",_V_.proxy(this,function(){var iDoc,objTag,swfLoc,iWin=iFrm.contentWindow,varString="";iDoc=iFrm.contentDocument?iFrm.contentDocument:iFrm.contentWindow.document;iDoc.write(_V_.flash.getEmbedCode(options.swf,flashVars,params,attributes));iWin.player=this.player;iWin.ready=_V_.proxy(this.player,function(currSwf){var el=iDoc.getElementById(currSwf),player=this,tech=player.tech;tech.el=el;_V_.addEvent(el,"click",tech.proxy(tech.onClick));_V_.flash.checkReady(tech)});iWin.events=_V_.proxy(this.player,function(swfID,eventName,other){var player=this;if(player&&player.techName=="flash"){player.triggerEvent(eventName)}});iWin.errors=_V_.proxy(this.player,function(swfID,eventName){_V_.log("Flash Error",eventName)})}));placeHolder.parentNode.replaceChild(iFrm,placeHolder)}else{_V_.flash.embed(options.swf,placeHolder,flashVars,params,attributes)}},destroy:function(){this.el.parentNode.removeChild(this.el)},play:function(){this.el.vjs_play()},pause:function(){this.el.vjs_pause()},src:function(src){src=_V_.getAbsoluteURL(src);this.el.vjs_src(src);if(this.player.autoplay()){var tech=this;setTimeout(function(){tech.play()},0)}},load:function(){this.el.vjs_load()},poster:function(){this.el.vjs_getProperty("poster")},buffered:function(){return _V_.createTimeRange(0,this.el.vjs_getProperty("buffered"))},supportsFullScreen:function(){return false},enterFullScreen:function(){return false}});(function(){var api=_V_.flash.prototype,readWrite="preload,currentTime,defaultPlaybackRate,playbackRate,autoplay,loop,mediaGroup,controller,controls,volume,muted,defaultMuted".split(","),readOnly="error,currentSrc,networkState,readyState,seeking,initialTime,duration,startOffsetTime,paused,played,seekable,ended,videoTracks,audioTracks,videoWidth,videoHeight,textTracks".split(","),callOnly="load,play,pause".split(",");createSetter=function(attr){var attrUpper=attr.charAt(0).toUpperCase()+attr.slice(1);api["set"+attrUpper]=function(val){return this.el.vjs_setProperty(attr,val)}},createGetter=function(attr){api[attr]=function(){return this.el.vjs_getProperty(attr)}};_V_.each(readWrite,function(attr){createGetter(attr);createSetter(attr)});_V_.each(readOnly,function(attr){createGetter(attr)})})();_V_.flash.isSupported=function(){return _V_.flash.version()[0]>=10};_V_.flash.canPlaySource=function(srcObj){if(srcObj.type in _V_.flash.prototype.support.formats){return"maybe"}};_V_.flash.prototype.support={formats:{"video/flv":"FLV","video/x-flv":"FLV","video/mp4":"MP4","video/m4v":"MP4"},progressEvent:false,timeupdateEvent:false,fullscreenResize:false,parentResize:!(_V_.ua.match("Firefox"))};_V_.flash.onReady=function(currSwf){var el=_V_.el(currSwf);var player=el.player||el.parentNode.player,tech=player.tech;el.player=player;tech.el=el;tech.addEvent("click",tech.onClick);_V_.flash.checkReady(tech)};_V_.flash.checkReady=function(tech){if(tech.el.vjs_getProperty){tech.triggerReady()}else{setTimeout(function(){_V_.flash.checkReady(tech)},50)}};_V_.flash.onEvent=function(swfID,eventName){var player=_V_.el(swfID).player;player.triggerEvent(eventName)};_V_.flash.onError=function(swfID,err){var player=_V_.el(swfID).player;player.triggerEvent("error");_V_.log("Flash Error",err,swfID)};_V_.flash.version=function(){var version="0,0,0";try{version=new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version").replace(/\D+/g,",").match(/^,?(.+),?$/)[1]}catch(e){try{if(navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){version=(navigator.plugins["Shockwave Flash 2.0"]||navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g,",").match(/^,?(.+),?$/)[1]}}catch(e){}}return version.split(",")};_V_.flash.embed=function(swf,placeHolder,flashVars,params,attributes){var code=_V_.flash.getEmbedCode(swf,flashVars,params,attributes),obj=_V_.createElement("div",{innerHTML:code}).childNodes[0],par=placeHolder.parentNode;placeHolder.parentNode.replaceChild(obj,placeHolder);if(_V_.isIE()){var newObj=par.childNodes[0];setTimeout(function(){newObj.style.display="block"},1000)}return obj};_V_.flash.getEmbedCode=function(swf,flashVars,params,attributes){var objTag='<object type="application/x-shockwave-flash"',flashVarsString="",paramsString="";attrsString="";if(flashVars){_V_.eachProp(flashVars,function(key,val){flashVarsString+=(key+"="+val+"&amp;")})}params=_V_.merge({movie:swf,flashvars:flashVarsString,allowScriptAccess:"always",allowNetworking:"all"},params);_V_.eachProp(params,function(key,val){paramsString+='<param name="'+key+'" value="'+val+'" />'});attributes=_V_.merge({data:swf,width:"100%",height:"100%"},attributes);_V_.eachProp(attributes,function(key,val){attrsString+=(key+'="'+val+'" ')});return objTag+attrsString+">"+paramsString+"</object>"};_V_.Control=_V_.Component.extend({buildCSSClass:function(){return"vjs-control "+this._super()}});_V_.ControlBar=_V_.Component.extend({options:{loadEvent:"play",components:{playToggle:{},fullscreenToggle:{},currentTimeDisplay:{},timeDivider:{},durationDisplay:{},remainingTimeDisplay:{},progressControl:{},volumeControl:{},muteToggle:{}}},init:function(player,options){this._super(player,options);player.one("play",this.proxy(function(){this.fadeIn();this.player.addEvent("mouseover",this.proxy(this.fadeIn));this.player.addEvent("mouseout",this.proxy(this.fadeOut))}))},createElement:function(){return _V_.createElement("div",{className:"vjs-controls"})},fadeIn:function(){this._super();this.player.triggerEvent("controlsvisible")},fadeOut:function(){this._super();this.player.triggerEvent("controlshidden")},lockShowing:function(){this.el.style.opacity="1"}});_V_.Button=_V_.Control.extend({init:function(player,options){this._super(player,options);this.addEvent("click",this.onClick);this.addEvent("focus",this.onFocus);this.addEvent("blur",this.onBlur)},createElement:function(type,attrs){attrs=_V_.merge({className:this.buildCSSClass(),innerHTML:'<div><span class="vjs-control-text">'+(this.buttonText||"Need Text")+"</span></div>",role:"button",tabIndex:0},attrs);return this._super(type,attrs)},onClick:function(){},onFocus:function(){_V_.addEvent(document,"keyup",_V_.proxy(this,this.onKeyPress))},onKeyPress:function(event){if(event.which==32||event.which==13){event.preventDefault();this.onClick()}},onBlur:function(){_V_.removeEvent(document,"keyup",_V_.proxy(this,this.onKeyPress))}});_V_.PlayButton=_V_.Button.extend({buttonText:"Play",buildCSSClass:function(){return"vjs-play-button "+this._super()},onClick:function(){this.player.play()}});_V_.PauseButton=_V_.Button.extend({buttonText:"Pause",buildCSSClass:function(){return"vjs-pause-button "+this._super()},onClick:function(){this.player.pause()}});_V_.PlayToggle=_V_.Button.extend({buttonText:"Play",init:function(player,options){this._super(player,options);player.addEvent("play",_V_.proxy(this,this.onPlay));player.addEvent("pause",_V_.proxy(this,this.onPause))},buildCSSClass:function(){return"vjs-play-control "+this._super()},onClick:function(){if(this.player.paused()){this.player.play()}else{this.player.pause()}},onPlay:function(){_V_.removeClass(this.el,"vjs-paused");_V_.addClass(this.el,"vjs-playing")},onPause:function(){_V_.removeClass(this.el,"vjs-playing");_V_.addClass(this.el,"vjs-paused")}});_V_.FullscreenToggle=_V_.Button.extend({buttonText:"Fullscreen",buildCSSClass:function(){return"vjs-fullscreen-control "+this._super()},onClick:function(){if(!this.player.isFullScreen){this.player.requestFullScreen()}else{this.player.cancelFullScreen()}}});_V_.BigPlayButton=_V_.Button.extend({init:function(player,options){this._super(player,options);player.addEvent("play",_V_.proxy(this,this.hide));player.addEvent("ended",_V_.proxy(this,this.show))},createElement:function(){return this._super("div",{className:"vjs-big-play-button",innerHTML:"<span></span>"})},onClick:function(){if(this.player.currentTime()){this.player.currentTime(0)}this.player.play()}});_V_.LoadingSpinner=_V_.Component.extend({init:function(player,options){this._super(player,options);player.addEvent("canplay",_V_.proxy(this,this.hide));player.addEvent("canplaythrough",_V_.proxy(this,this.hide));player.addEvent("playing",_V_.proxy(this,this.hide));player.addEvent("seeking",_V_.proxy(this,this.show));player.addEvent("seeked",_V_.proxy(this,this.hide));player.addEvent("error",_V_.proxy(this,this.show));player.addEvent("waiting",_V_.proxy(this,this.show))},createElement:function(){var classNameSpinner,innerHtmlSpinner;if(typeof this.player.el.style.WebkitBorderRadius=="string"||typeof this.player.el.style.MozBorderRadius=="string"||typeof this.player.el.style.KhtmlBorderRadius=="string"||typeof this.player.el.style.borderRadius=="string"){classNameSpinner="vjs-loading-spinner";innerHtmlSpinner="<div class='ball1'></div><div class='ball2'></div><div class='ball3'></div><div class='ball4'></div><div class='ball5'></div><div class='ball6'></div><div class='ball7'></div><div class='ball8'></div>"}else{classNameSpinner="vjs-loading-spinner-fallback";innerHtmlSpinner=""}return this._super("div",{className:classNameSpinner,innerHTML:innerHtmlSpinner})}});_V_.CurrentTimeDisplay=_V_.Component.extend({init:function(player,options){this._super(player,options);player.addEvent("timeupdate",_V_.proxy(this,this.updateContent))},createElement:function(){var el=this._super("div",{className:"vjs-current-time vjs-time-controls vjs-control"});this.content=_V_.createElement("div",{className:"vjs-current-time-display",innerHTML:"0:00"});el.appendChild(_V_.createElement("div").appendChild(this.content));return el},updateContent:function(){var time=(this.player.scrubbing)?this.player.values.currentTime:this.player.currentTime();this.content.innerHTML=_V_.formatTime(time,this.player.duration())}});_V_.DurationDisplay=_V_.Component.extend({init:function(player,options){this._super(player,options);player.addEvent("timeupdate",_V_.proxy(this,this.updateContent))},createElement:function(){var el=this._super("div",{className:"vjs-duration vjs-time-controls vjs-control"});this.content=_V_.createElement("div",{className:"vjs-duration-display",innerHTML:"0:00"});el.appendChild(_V_.createElement("div").appendChild(this.content));return el},updateContent:function(){if(this.player.duration()){this.content.innerHTML=_V_.formatTime(this.player.duration())}}});_V_.TimeDivider=_V_.Component.extend({createElement:function(){return this._super("div",{className:"vjs-time-divider",innerHTML:"<div><span>/</span></div>"})}});_V_.RemainingTimeDisplay=_V_.Component.extend({init:function(player,options){this._super(player,options);player.addEvent("timeupdate",_V_.proxy(this,this.updateContent))},createElement:function(){var el=this._super("div",{className:"vjs-remaining-time vjs-time-controls vjs-control"});this.content=_V_.createElement("div",{className:"vjs-remaining-time-display",innerHTML:"-0:00"});el.appendChild(_V_.createElement("div").appendChild(this.content));return el},updateContent:function(){if(this.player.duration()){this.content.innerHTML="-"+_V_.formatTime(this.player.remainingTime())}}});_V_.Slider=_V_.Component.extend({init:function(player,options){this._super(player,options);player.addEvent(this.playerEvent,_V_.proxy(this,this.update));this.addEvent("mousedown",this.onMouseDown);this.addEvent("focus",this.onFocus);this.addEvent("blur",this.onBlur);this.player.addEvent("controlsvisible",this.proxy(this.update));this.update()},createElement:function(type,attrs){attrs=_V_.merge({role:"slider","aria-valuenow":0,"aria-valuemin":0,"aria-valuemax":100,tabIndex:0},attrs);return this._super(type,attrs)},onMouseDown:function(event){event.preventDefault();_V_.blockTextSelection();_V_.addEvent(document,"mousemove",_V_.proxy(this,this.onMouseMove));_V_.addEvent(document,"mouseup",_V_.proxy(this,this.onMouseUp));this.onMouseMove(event)},onMouseUp:function(event){_V_.unblockTextSelection();_V_.removeEvent(document,"mousemove",this.onMouseMove,false);_V_.removeEvent(document,"mouseup",this.onMouseUp,false);this.update()},update:function(){var barProgress,progress=this.getPercent();handle=this.handle,bar=this.bar;if(isNaN(progress)){progress=0}barProgress=progress;if(handle){var box=this.el,boxWidth=box.offsetWidth,handleWidth=handle.el.offsetWidth,handlePercent=(handleWidth)?handleWidth/boxWidth:0,boxAdjustedPercent=1-handlePercent;adjustedProgress=progress*boxAdjustedPercent,barProgress=adjustedProgress+(handlePercent/2);handle.el.style.left=_V_.round(adjustedProgress*100,2)+"%"}bar.el.style.width=_V_.round(barProgress*100,2)+"%"},calculateDistance:function(event){var box=this.el,boxX=_V_.findPosX(box),boxW=box.offsetWidth,handle=this.handle;if(handle){var handleW=handle.el.offsetWidth;boxX=boxX+(handleW/2);boxW=boxW-handleW}return Math.max(0,Math.min(1,(event.pageX-boxX)/boxW))},onFocus:function(event){_V_.addEvent(document,"keyup",_V_.proxy(this,this.onKeyPress))},onKeyPress:function(event){if(event.which==37){event.preventDefault();this.stepBack()}else{if(event.which==39){event.preventDefault();this.stepForward()}}},onBlur:function(event){_V_.removeEvent(document,"keyup",_V_.proxy(this,this.onKeyPress))}});_V_.ProgressControl=_V_.Component.extend({options:{components:{seekBar:{}}},createElement:function(){return this._super("div",{className:"vjs-progress-control vjs-control"})}});_V_.SeekBar=_V_.Slider.extend({options:{components:{loadProgressBar:{},bar:{componentClass:"PlayProgressBar"},handle:{componentClass:"SeekHandle"}}},playerEvent:"timeupdate",init:function(player,options){this._super(player,options)},createElement:function(){return this._super("div",{className:"vjs-progress-holder"})},getPercent:function(){return this.player.currentTime()/this.player.duration()},onMouseDown:function(event){this._super(event);this.player.scrubbing=true;this.videoWasPlaying=!this.player.paused();this.player.pause()},onMouseMove:function(event){var newTime=this.calculateDistance(event)*this.player.duration();if(newTime==this.player.duration()){newTime=newTime-0.1}this.player.currentTime(newTime)},onMouseUp:function(event){this._super(event);this.player.scrubbing=false;if(this.videoWasPlaying){this.player.play()}},stepForward:function(){this.player.currentTime(this.player.currentTime()+1)},stepBack:function(){this.player.currentTime(this.player.currentTime()-1)}});_V_.LoadProgressBar=_V_.Component.extend({init:function(player,options){this._super(player,options);player.addEvent("progress",_V_.proxy(this,this.update))},createElement:function(){return this._super("div",{className:"vjs-load-progress",innerHTML:'<span class="vjs-control-text">Loaded: 0%</span>'})},update:function(){if(this.el.style){this.el.style.width=_V_.round(this.player.bufferedPercent()*100,2)+"%"}}});_V_.PlayProgressBar=_V_.Component.extend({createElement:function(){return this._super("div",{className:"vjs-play-progress",innerHTML:'<span class="vjs-control-text">Progress: 0%</span>'})}});_V_.SeekHandle=_V_.Component.extend({createElement:function(){return this._super("div",{className:"vjs-seek-handle",innerHTML:'<span class="vjs-control-text">00:00</span>'})}});_V_.VolumeControl=_V_.Component.extend({options:{components:{volumeBar:{}}},createElement:function(){return this._super("div",{className:"vjs-volume-control vjs-control"})}});_V_.VolumeBar=_V_.Slider.extend({options:{components:{bar:{componentClass:"VolumeLevel"},handle:{componentClass:"VolumeHandle"}}},playerEvent:"volumechange",createElement:function(){return this._super("div",{className:"vjs-volume-bar"})},onMouseMove:function(event){this.player.volume(this.calculateDistance(event))},getPercent:function(){return this.player.volume()},stepForward:function(){this.player.volume(this.player.volume()+0.1)},stepBack:function(){this.player.volume(this.player.volume()-0.1)}});_V_.VolumeLevel=_V_.Component.extend({createElement:function(){return this._super("div",{className:"vjs-volume-level",innerHTML:'<span class="vjs-control-text"></span>'})}});_V_.VolumeHandle=_V_.Component.extend({createElement:function(){return this._super("div",{className:"vjs-volume-handle",innerHTML:'<span class="vjs-control-text"></span>'})}});_V_.MuteToggle=_V_.Button.extend({init:function(player,options){this._super(player,options);player.addEvent("volumechange",_V_.proxy(this,this.update))},createElement:function(){return this._super("div",{className:"vjs-mute-control vjs-control",innerHTML:'<div><span class="vjs-control-text">Mute</span></div>'})},onClick:function(event){this.player.muted(this.player.muted()?false:true)},update:function(event){var vol=this.player.volume(),level=3;if(vol==0||this.player.muted()){level=0}else{if(vol<0.33){level=1}else{if(vol<0.67){level=2}}}_V_.each.call(this,[0,1,2,3],function(i){_V_.removeClass(this.el,"vjs-vol-"+i)});_V_.addClass(this.el,"vjs-vol-"+level)}});_V_.PosterImage=_V_.Button.extend({init:function(player,options){this._super(player,options);if(!this.player.options.poster){this.hide()}player.addEvent("play",_V_.proxy(this,this.hide))},createElement:function(){return _V_.createElement("img",{className:"vjs-poster",src:this.player.options.poster,tabIndex:-1})},onClick:function(){this.player.play()}});_V_.Menu=_V_.Component.extend({init:function(player,options){this._super(player,options)},addItem:function(component){this.addComponent(component);component.addEvent("click",this.proxy(function(){this.unlockShowing()}))},createElement:function(){return this._super("ul",{className:"vjs-menu"})}});_V_.MenuItem=_V_.Button.extend({init:function(player,options){this._super(player,options);if(options.selected){this.addClass("vjs-selected")}},createElement:function(type,attrs){return this._super("li",_V_.merge({className:"vjs-menu-item",innerHTML:this.options.label},attrs))},onClick:function(){this.selected(true)},selected:function(selected){if(selected){this.addClass("vjs-selected")}else{this.removeClass("vjs-selected")}}});_V_.merge(_V_.Player.prototype,{addTextTracks:function(trackObjects){var tracks=this.textTracks=(this.textTracks)?this.textTracks:[],i=0,j=trackObjects.length,track,Kind;for(;i<j;i++){Kind=_V_.uc(trackObjects[i].kind||"subtitles");track=new _V_[Kind+"Track"](this,trackObjects[i]);tracks.push(track);if(track["default"]){this.ready(_V_.proxy(track,track.show))}}return this},showTextTrack:function(id,disableSameKind){var tracks=this.textTracks,i=0,j=tracks.length,track,showTrack,kind;for(;i<j;i++){track=tracks[i];if(track.id===id){track.show();showTrack=track}else{if(disableSameKind&&track.kind==disableSameKind&&track.mode>0){track.disable()}}}kind=(showTrack)?showTrack.kind:((disableSameKind)?disableSameKind:false);if(kind){this.triggerEvent(kind+"trackchange")}return this}});_V_.Track=_V_.Component.extend({init:function(player,options){this._super(player,options);_V_.merge(this,{id:options.id||("vjs_"+options.kind+"_"+options.language+"_"+_V_.guid++),src:options.src,"default":options["default"],title:options.title,language:options.srclang,label:options.label,cues:[],activeCues:[],readyState:0,mode:0})},createElement:function(){return this._super("div",{className:"vjs-"+this.kind+" vjs-text-track"})},show:function(){this.activate();this.mode=2;this._super()},hide:function(){this.activate();this.mode=1;this._super()},disable:function(){if(this.mode==2){this.hide()}this.deactivate();this.mode=0},activate:function(){if(this.readyState==0){this.load()}if(this.mode==0){this.player.addEvent("timeupdate",this.proxy(this.update,this.id));this.player.addEvent("ended",this.proxy(this.reset,this.id));if(this.kind=="captions"||this.kind=="subtitles"){this.player.textTrackDisplay.addComponent(this)}}},deactivate:function(){this.player.removeEvent("timeupdate",this.proxy(this.update,this.id));this.player.removeEvent("ended",this.proxy(this.reset,this.id));this.reset();this.player.textTrackDisplay.removeComponent(this)},load:function(){if(this.readyState==0){this.readyState=1;_V_.get(this.src,this.proxy(this.parseCues),this.proxy(this.onError))}},onError:function(err){this.error=err;this.readyState=3;this.triggerEvent("error")},parseCues:function(srcContent){var cue,time,text,lines=srcContent.split("\n"),line="",id;for(var i=1,j=lines.length;i<j;i++){line=_V_.trim(lines[i]);if(line){if(line.indexOf("-->")==-1){id=line;line=_V_.trim(lines[++i])}else{id=this.cues.length}cue={id:id,index:this.cues.length};time=line.split(" --> ");cue.startTime=this.parseCueTime(time[0]);cue.endTime=this.parseCueTime(time[1]);text=[];while(lines[++i]&&(line=_V_.trim(lines[i]))){text.push(line)}cue.text=text.join("<br/>");this.cues.push(cue)}}this.readyState=2;this.triggerEvent("loaded")},parseCueTime:function(timeText){var parts=timeText.split(":"),time=0,hours,minutes,other,seconds,ms,flags;if(parts.length==3){hours=parts[0];minutes=parts[1];other=parts[2]}else{hours=0;minutes=parts[0];other=parts[1]}other=other.split(/\s+/);seconds=other.splice(0,1)[0];seconds=seconds.split(/\.|,/);ms=parseFloat(seconds[1]);seconds=seconds[0];time+=parseFloat(hours)*3600;time+=parseFloat(minutes)*60;time+=parseFloat(seconds);if(ms){time+=ms/1000}return time},update:function(){if(this.cues.length>0){var time=this.player.currentTime();if(this.prevChange===undefined||time<this.prevChange||this.nextChange<=time){var cues=this.cues,newNextChange=this.player.duration(),newPrevChange=0,reverse=false,newCues=[],firstActiveIndex,lastActiveIndex,html="",cue,i,j;if(time>=this.nextChange||this.nextChange===undefined){i=(this.firstActiveIndex!==undefined)?this.firstActiveIndex:0}else{reverse=true;i=(this.lastActiveIndex!==undefined)?this.lastActiveIndex:cues.length-1}while(true){cue=cues[i];if(cue.endTime<=time){newPrevChange=Math.max(newPrevChange,cue.endTime);if(cue.active){cue.active=false}}else{if(time<cue.startTime){newNextChange=Math.min(newNextChange,cue.startTime);if(cue.active){cue.active=false}if(!reverse){break}}else{if(reverse){newCues.splice(0,0,cue);if(lastActiveIndex===undefined){lastActiveIndex=i}firstActiveIndex=i}else{newCues.push(cue);if(firstActiveIndex===undefined){firstActiveIndex=i}lastActiveIndex=i}newNextChange=Math.min(newNextChange,cue.endTime);newPrevChange=Math.max(newPrevChange,cue.startTime);cue.active=true}}if(reverse){if(i===0){break}else{i--}}else{if(i===cues.length-1){break}else{i++}}}this.activeCues=newCues;this.nextChange=newNextChange;this.prevChange=newPrevChange;this.firstActiveIndex=firstActiveIndex;this.lastActiveIndex=lastActiveIndex;this.updateDisplay();this.triggerEvent("cuechange")}}},updateDisplay:function(){var cues=this.activeCues,html="",i=0,j=cues.length;for(;i<j;i++){html+="<span class='vjs-tt-cue'>"+cues[i].text+"</span>"}this.el.innerHTML=html},reset:function(){this.nextChange=0;this.prevChange=this.player.duration();this.firstActiveIndex=0;this.lastActiveIndex=0}});_V_.CaptionsTrack=_V_.Track.extend({kind:"captions"});_V_.SubtitlesTrack=_V_.Track.extend({kind:"subtitles"});_V_.ChaptersTrack=_V_.Track.extend({kind:"chapters"});_V_.TextTrackDisplay=_V_.Component.extend({createElement:function(){return this._super("div",{className:"vjs-text-track-display"})}});_V_.TextTrackMenuItem=_V_.MenuItem.extend({init:function(player,options){var track=this.track=options.track;options.label=track.label;options.selected=track["default"];this._super(player,options);this.player.addEvent(track.kind+"trackchange",_V_.proxy(this,this.update))},onClick:function(){this._super();this.player.showTextTrack(this.track.id,this.track.kind)},update:function(){if(this.track.mode==2){this.selected(true)}else{this.selected(false)}}});_V_.OffTextTrackMenuItem=_V_.TextTrackMenuItem.extend({init:function(player,options){options.track={kind:options.kind,player:player,label:"Off"};this._super(player,options)},onClick:function(){this._super();this.player.showTextTrack(this.track.id,this.track.kind)},update:function(){var tracks=this.player.textTracks,i=0,j=tracks.length,track,off=true;for(;i<j;i++){track=tracks[i];if(track.kind==this.track.kind&&track.mode==2){off=false}}if(off){this.selected(true)}else{this.selected(false)}}});_V_.TextTrackButton=_V_.Button.extend({init:function(player,options){this._super(player,options);this.menu=this.createMenu();if(this.items.length===0){this.hide()}},createMenu:function(){var menu=new _V_.Menu(this.player);menu.el.appendChild(_V_.createElement("li",{className:"vjs-menu-title",innerHTML:_V_.uc(this.kind)}));menu.addItem(new _V_.OffTextTrackMenuItem(this.player,{kind:this.kind}));this.items=this.createItems();this.each(this.items,function(item){menu.addItem(item)});this.addComponent(menu);return menu},createItems:function(){var items=[];this.each(this.player.textTracks,function(track){if(track.kind===this.kind){items.push(new _V_.TextTrackMenuItem(this.player,{track:track}))}});return items},buildCSSClass:function(){return this.className+" vjs-menu-button "+this._super()},onFocus:function(){this.menu.lockShowing();_V_.one(this.menu.el.childNodes[this.menu.el.childNodes.length-1],"blur",this.proxy(function(){this.menu.unlockShowing()}))},onBlur:function(){},onClick:function(){this.one("mouseout",this.proxy(function(){this.menu.unlockShowing();this.el.blur()}))}});_V_.CaptionsButton=_V_.TextTrackButton.extend({kind:"captions",buttonText:"Captions",className:"vjs-captions-button"});_V_.SubtitlesButton=_V_.TextTrackButton.extend({kind:"subtitles",buttonText:"Subtitles",className:"vjs-subtitles-button"});_V_.ChaptersButton=_V_.TextTrackButton.extend({kind:"chapters",buttonText:"Chapters",className:"vjs-chapters-button",createItems:function(chaptersTrack){var items=[];this.each(this.player.textTracks,function(track){if(track.kind===this.kind){items.push(new _V_.TextTrackMenuItem(this.player,{track:track}))}});return items},createMenu:function(){var tracks=this.player.textTracks,i=0,j=tracks.length,track,chaptersTrack,items=this.items=[];for(;i<j;i++){track=tracks[i];if(track.kind==this.kind&&track["default"]){if(track.readyState<2){this.chaptersTrack=track;track.addEvent("loaded",this.proxy(this.createMenu));return}else{chaptersTrack=track;break}}}var menu=this.menu=new _V_.Menu(this.player);menu.el.appendChild(_V_.createElement("li",{className:"vjs-menu-title",innerHTML:_V_.uc(this.kind)}));if(chaptersTrack){var cues=chaptersTrack.cues,i=0,j=cues.length,cue,mi;for(;i<j;i++){cue=cues[i];mi=new _V_.ChaptersTrackMenuItem(this.player,{track:chaptersTrack,cue:cue});items.push(mi);menu.addComponent(mi)}}this.addComponent(menu);if(this.items.length>0){this.show()}return menu}});_V_.ChaptersTrackMenuItem=_V_.MenuItem.extend({init:function(player,options){var track=this.track=options.track,cue=this.cue=options.cue,currentTime=player.currentTime();options.label=cue.text;options.selected=(cue.startTime<=currentTime&&currentTime<cue.endTime);this._super(player,options);track.addEvent("cuechange",_V_.proxy(this,this.update))},onClick:function(){this._super();this.player.currentTime(this.cue.startTime);this.update(this.cue.startTime)},update:function(time){var cue=this.cue,currentTime=this.player.currentTime();if(cue.startTime<=currentTime&&currentTime<cue.endTime){this.selected(true)}else{this.selected(false)}}});_V_.merge(_V_.ControlBar.prototype.options.components,{subtitlesButton:{},captionsButton:{},chaptersButton:{}});_V_.autoSetup=function(){var options,vid,player,vids=document.getElementsByTagName("video");if(vids&&vids.length>0){for(var i=0,j=vids.length;i<j;i++){vid=vids[i];if(vid&&vid.getAttribute){if(vid.player===undefined){options=vid.getAttribute("data-setup");if(options!==null){options=JSON.parse(options||"{}");player=_V_(vid,options)}}}else{_V_.autoSetupTimeout(1);break}}}else{if(!_V_.windowLoaded){_V_.autoSetupTimeout(1)}}};_V_.autoSetupTimeout=function(wait){setTimeout(_V_.autoSetup,wait)};_V_.addEvent(window,"load",function(){_V_.windowLoaded=true});_V_.autoSetup();window.VideoJS=window._V_=VideoJS})(window); \ No newline at end of file
diff --git a/mediagoblin/_version.py b/mediagoblin/_version.py
index 94ab9f1a..2db399a9 100644
--- a/mediagoblin/_version.py
+++ b/mediagoblin/_version.py
@@ -23,4 +23,4 @@
# see http://www.python.org/dev/peps/pep-0386/
-__version__ = "0.3.2.dev"
+__version__ = "0.3.3.dev"
diff --git a/mediagoblin/admin/views.py b/mediagoblin/admin/views.py
index 9c14c55c..22ca74a3 100644
--- a/mediagoblin/admin/views.py
+++ b/mediagoblin/admin/views.py
@@ -14,10 +14,11 @@
# 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.db.util import DESCENDING
+from werkzeug.exceptions import Forbidden
+
+from mediagoblin.db.models import MediaEntry
from mediagoblin.decorators import require_active_login
-from mediagoblin.tools.response import (render_to_response, render_403,
- render_404)
+from mediagoblin.tools.response import render_to_response
@require_active_login
def admin_processing_panel(request):
@@ -26,17 +27,17 @@ def admin_processing_panel(request):
'''
# TODO: Why not a "require_admin_login" decorator throwing a 403 exception?
if not request.user.is_admin:
- return render_403(request)
+ raise Forbidden()
- processing_entries = request.db.MediaEntry.find(
- {'state': u'processing'}).sort('created', DESCENDING)
+ processing_entries = MediaEntry.query.filter_by(state = u'processing').\
+ order_by(MediaEntry.created.desc())
# Get media entries which have failed to process
- failed_entries = request.db.MediaEntry.find(
- {'state': u'failed'}).sort('created', DESCENDING)
+ failed_entries = MediaEntry.query.filter_by(state = u'failed').\
+ order_by(MediaEntry.created.desc())
- processed_entries = request.db.MediaEntry.find(
- {'state': u'processed'}).sort('created', DESCENDING).limit(10)
+ processed_entries = MediaEntry.query.filter_by(state = u'processed').\
+ order_by(MediaEntry.created.desc()).limit(10)
# Render to response
return render_to_response(
diff --git a/mediagoblin/app.py b/mediagoblin/app.py
index 876ded4e..10fbf4a3 100644
--- a/mediagoblin/app.py
+++ b/mediagoblin/app.py
@@ -17,14 +17,16 @@
import os
import logging
-from mediagoblin.routing import url_map, view_functions, add_route
+from mediagoblin.routing import get_url_map
+from mediagoblin.tools.routing import endpoint_to_controller
from werkzeug.wrappers import Request
from werkzeug.exceptions import HTTPException, NotFound
+from werkzeug.routing import RequestRedirect
from mediagoblin import meddleware, __version__
from mediagoblin.tools import common, translate, template
-from mediagoblin.tools.response import render_404
+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.mg_globals import setup_globals
@@ -77,7 +79,7 @@ class MediaGoblinApp(object):
setup_plugins()
# Set up the database
- self.connection, self.db = setup_database()
+ self.db = setup_database()
# Register themes
self.theme_registry, self.current_theme = register_themes(app_config)
@@ -93,11 +95,7 @@ class MediaGoblinApp(object):
self.public_store, self.queue_store = setup_storage()
# set up routing
- self.url_map = url_map
-
- for route in PluginManager().get_routes():
- _log.debug('adding plugin route: {0}'.format(route))
- add_route(*route)
+ self.url_map = get_url_map()
# set up staticdirector tool
self.staticdirector = get_staticdirector(app_config)
@@ -135,9 +133,8 @@ class MediaGoblinApp(object):
def call_backend(self, environ, start_response):
request = Request(environ)
- ## Compatibility webob -> werkzeug
+ # Compatibility with django, use request.args preferrably
request.GET = request.args
- request.accept = request.accept_mimetypes
## Routing / controller loading stuff
map_adapter = self.url_map.bind_to_environ(request.environ)
@@ -188,41 +185,46 @@ class MediaGoblinApp(object):
mg_request.setup_user_in_request(request)
try:
- endpoint, url_values = map_adapter.match()
+ found_rule, url_values = map_adapter.match(return_rule=True)
request.matchdict = url_values
- except NotFound as exc:
- return render_404(request)(environ, start_response)
+ except RequestRedirect as response:
+ # Deal with 301 responses eg due to missing final slash
+ return response(environ, start_response)
except HTTPException as exc:
- # Support legacy webob.exc responses
- return exc(environ, start_response)
-
- view_func = view_functions[endpoint]
-
- _log.debug('endpoint: {0} view_func: {1}'.format(
- endpoint,
- view_func))
+ # Stop and render exception
+ return render_http_exception(
+ request, exc,
+ exc.get_description(environ))(environ, start_response)
- # import the endpoint, or if it's already a callable, call that
- if isinstance(view_func, unicode) \
- or isinstance(view_func, str):
- controller = common.import_component(view_func)
- else:
- controller = view_func
+ controller = endpoint_to_controller(found_rule)
# pass the request through our meddleware classes
- for m in self.meddleware:
- response = m.process_request(request, controller)
- if response is not None:
- return response(environ, start_response)
+ try:
+ for m in self.meddleware:
+ response = m.process_request(request, controller)
+ if response is not None:
+ return response(environ, start_response)
+ except HTTPException as e:
+ return render_http_exception(
+ request, e,
+ e.get_description(environ))(environ, start_response)
request.start_response = start_response
- # get the response from the controller
- response = controller(request)
+ # get the Http response from the controller
+ try:
+ response = controller(request)
+ except HTTPException as e:
+ response = render_http_exception(
+ request, e, e.get_description(environ))
- # pass the response through the meddleware
- for m in self.meddleware[::-1]:
- m.process_response(request, response)
+ # pass the response through the meddlewares
+ try:
+ for m in self.meddleware[::-1]:
+ m.process_response(request, response)
+ except HTTPException as e:
+ response = render_http_exeption(
+ request, e, e.get_description(environ))
return response(environ, start_response)
diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py
index c5b046d2..8829995a 100644
--- a/mediagoblin/auth/lib.py
+++ b/mediagoblin/auth/lib.py
@@ -109,7 +109,7 @@ def send_verification_email(user, request):
'verification_url': EMAIL_VERIFICATION_TEMPLATE.format(
host=request.host,
uri=request.urlgen('mediagoblin.auth.verify_email'),
- userid=unicode(user._id),
+ userid=unicode(user.id),
verification_key=user.verification_key)})
# TODO: There is no error handling in place
@@ -144,7 +144,7 @@ def send_fp_verification_email(user, request):
'verification_url': EMAIL_FP_VERIFICATION_TEMPLATE.format(
host=request.host,
uri=request.urlgen('mediagoblin.auth.verify_forgot_password'),
- userid=unicode(user._id),
+ userid=unicode(user.id),
fp_verification_key=user.fp_verification_key)})
# TODO: There is no error handling in place
diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py
index 5b77c122..43354135 100644
--- a/mediagoblin/auth/views.py
+++ b/mediagoblin/auth/views.py
@@ -17,13 +17,10 @@
import uuid
import datetime
-from webob import exc
-
-from mediagoblin import messages
-from mediagoblin import mg_globals
+from mediagoblin import messages, mg_globals
+from mediagoblin.db.models import User
from mediagoblin.tools.response import render_to_response, redirect, render_404
from mediagoblin.tools.translate import pass_to_ugettext as _
-from mediagoblin.db.util import ObjectId, InvalidId
from mediagoblin.auth import lib as auth_lib
from mediagoblin.auth import forms as auth_forms
from mediagoblin.auth.lib import send_verification_email, \
@@ -63,10 +60,8 @@ def register(request):
em_user, em_dom = unicode(request.form['email']).split("@", 1)
em_dom = em_dom.lower()
email = em_user + "@" + em_dom
- users_with_username = request.db.User.find(
- {'username': username}).count()
- users_with_email = request.db.User.find(
- {'email': email}).count()
+ users_with_username = User.query.filter_by(username=username).count()
+ users_with_email = User.query.filter_by(email=email).count()
extra_validation_passes = True
@@ -81,16 +76,16 @@ def register(request):
if extra_validation_passes:
# Create the user
- user = request.db.User()
+ user = User()
user.username = username
user.email = email
user.pw_hash = auth_lib.bcrypt_gen_password_hash(
request.form['password'])
user.verification_key = unicode(uuid.uuid4())
- user.save(validate=True)
+ user.save()
# log the user in
- request.session['user_id'] = unicode(user._id)
+ request.session['user_id'] = unicode(user.id)
request.session.save()
# send verification email
@@ -120,16 +115,15 @@ def login(request):
login_failed = False
if request.method == 'POST' and login_form.validate():
- user = request.db.User.find_one(
- {'username': request.form['username'].lower()})
+ user = User.query.filter_by(username=request.form['username'].lower()).first()
if user and user.check_login(request.form['password']):
# set up login in session
- request.session['user_id'] = unicode(user._id)
+ request.session['user_id'] = unicode(user.id)
request.session.save()
if request.form.get('next'):
- return exc.HTTPFound(location=request.form['next'])
+ return redirect(request, location=request.form['next'])
else:
return redirect(request, "index")
@@ -166,8 +160,7 @@ def verify_email(request):
if not 'userid' in request.GET or not 'token' in request.GET:
return render_404(request)
- user = request.db.User.find_one(
- {'_id': ObjectId(unicode(request.GET['userid']))})
+ user = User.query.filter_by(id=request.args['userid']).first()
if user and user.verification_key == unicode(request.GET['token']):
user.status = u'active'
@@ -242,11 +235,9 @@ def forgot_password(request):
if request.method == 'POST' and fp_form.validate():
# '$or' not available till mongodb 1.5.3
- user = request.db.User.find_one(
- {'username': request.form['username']})
+ user = User.query.filter_by(username=request.form['username']).first()
if not user:
- user = request.db.User.find_one(
- {'email': request.form['username']})
+ user = User.query.filter_by(email=request.form['username']).first()
if user:
if user.email_verified and user.status == 'active':
@@ -305,11 +296,9 @@ def verify_forgot_password(request):
formdata_userid = formdata['vars']['userid']
formdata_vars = formdata['vars']
- # check if it's a valid Id
- try:
- user = request.db.User.find_one(
- {'_id': ObjectId(unicode(formdata_userid))})
- except InvalidId:
+ # check if it's a valid user id
+ user = User.query.filter_by(id=formdata_userid).first()
+ if not user:
return render_404(request)
# check if we have a real user and correct token
@@ -338,7 +327,7 @@ def verify_forgot_password(request):
'mediagoblin/auth/change_fp.html',
{'cp_form': cp_form})
- # in case there is a valid id but no user whit that id in the db
+ # 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)
diff --git a/mediagoblin/config_spec.ini b/mediagoblin/config_spec.ini
index 17df2819..bee67d46 100644
--- a/mediagoblin/config_spec.ini
+++ b/mediagoblin/config_spec.ini
@@ -9,9 +9,6 @@ source_link = string(default="https://gitorious.org/mediagoblin/mediagoblin")
media_types = string_list(default=list("mediagoblin.media_types.image"))
# database stuff
-db_host = string()
-db_name = string(default="mediagoblin")
-db_port = integer()
sql_engine = string(default="sqlite:///%(here)s/mediagoblin.db")
# Where temporary files used in processing and etc are kept
diff --git a/mediagoblin/db/__init__.py b/mediagoblin/db/__init__.py
index d149f62a..27ca4b06 100644
--- a/mediagoblin/db/__init__.py
+++ b/mediagoblin/db/__init__.py
@@ -18,18 +18,6 @@
Database Abstraction/Wrapper Layer
==================================
- **NOTE from Chris Webber:** I asked Elrond to explain why he put
- ASCENDING and DESCENDING in db/util.py when we could just import from
- pymongo. Read beow for why, but note that nobody is actually doing
- this and there's no proof that we'll ever support more than
- MongoDB... it would be a huge amount of work to do so.
-
- If you really want to prove that possible, jump on IRC and talk to
- us about making such a branch. In the meanwhile, it doesn't hurt to
- have things as they are... if it ever makes it hard for us to
- actually do things, we might revisit or remove this. But for more
- information, read below.
-
This submodule is for most of the db specific stuff.
There are two main ideas here:
diff --git a/mediagoblin/db/sql/base.py b/mediagoblin/db/base.py
index e10e7739..699a503a 100644
--- a/mediagoblin/db/sql/base.py
+++ b/mediagoblin/db/base.py
@@ -17,47 +17,19 @@
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session, sessionmaker, object_session
-from sqlalchemy.orm.query import Query
-from sqlalchemy.sql.expression import desc
-from mediagoblin.db.sql.fake import DESCENDING
-
-def _get_query_model(query):
- cols = query.column_descriptions
- assert len(cols) == 1, "These functions work only on simple queries"
- return cols[0]["type"]
-
-
-class GMGQuery(Query):
- def sort(self, key, direction):
- key_col = getattr(_get_query_model(self), key)
- if direction is DESCENDING:
- key_col = desc(key_col)
- return self.order_by(key_col)
-
- def skip(self, amount):
- return self.offset(amount)
-
-
-Session = scoped_session(sessionmaker(query_cls=GMGQuery))
-
-
-def _fix_query_dict(query_dict):
- if '_id' in query_dict:
- query_dict['id'] = query_dict.pop('_id')
+Session = scoped_session(sessionmaker())
class GMGTableBase(object):
query = Session.query_property()
@classmethod
- def find(cls, query_dict={}):
- _fix_query_dict(query_dict)
+ def find(cls, query_dict):
return cls.query.filter_by(**query_dict)
@classmethod
- def find_one(cls, query_dict={}):
- _fix_query_dict(query_dict)
+ def find_one(cls, query_dict):
return cls.query.filter_by(**query_dict).first()
@classmethod
@@ -71,8 +43,7 @@ class GMGTableBase(object):
# The key *has* to exist on sql.
return getattr(self, key)
- def save(self, validate=True):
- assert validate
+ def save(self):
sess = object_session(self)
if sess is None:
sess = Session()
diff --git a/mediagoblin/db/sql/extratypes.py b/mediagoblin/db/extratypes.py
index f2304af0..f2304af0 100644
--- a/mediagoblin/db/sql/extratypes.py
+++ b/mediagoblin/db/extratypes.py
diff --git a/mediagoblin/db/sql/util.py b/mediagoblin/db/migration_tools.py
index c6d8562e..e5380a3b 100644
--- a/mediagoblin/db/sql/util.py
+++ b/mediagoblin/db/migration_tools.py
@@ -14,12 +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 sys
-from mediagoblin.db.sql.base import Session
-from mediagoblin.db.sql.models import MediaEntry, Tag, MediaTag, Collection
-
from mediagoblin.tools.common import simple_printer
+from sqlalchemy import Table
class MigrationManager(object):
@@ -47,7 +43,7 @@ class MigrationManager(object):
self.printer = printer
# For convenience
- from mediagoblin.db.sql.models import MigrationData
+ from mediagoblin.db.models import MigrationData
self.migration_model = MigrationData
self.migration_table = MigrationData.__table__
@@ -217,9 +213,9 @@ class MigrationManager(object):
u' + Running migration %s, "%s"... ' % (
migration_number, migration_func.func_name))
migration_func(self.session)
+ self.set_current_migration(migration_number)
self.printer('done.\n')
- self.set_current_migration()
return u'migrated'
# Otherwise return None. Well it would do this anyway, but
@@ -261,67 +257,14 @@ def assure_migrations_table_setup(db):
"""
Make sure the migrations table is set up in the database.
"""
- from mediagoblin.db.sql.models import MigrationData
+ from mediagoblin.db.models import MigrationData
if not MigrationData.__table__.exists(db.bind):
MigrationData.metadata.create_all(
db.bind, tables=[MigrationData.__table__])
-##########################
-# Random utility functions
-##########################
-
-
-def atomic_update(table, query_dict, update_values):
- table.find(query_dict).update(update_values,
- synchronize_session=False)
- Session.commit()
-
-
-def check_media_slug_used(dummy_db, uploader_id, slug, ignore_m_id):
- filt = (MediaEntry.uploader == uploader_id) \
- & (MediaEntry.slug == slug)
- if ignore_m_id is not None:
- filt = filt & (MediaEntry.id != ignore_m_id)
- does_exist = Session.query(MediaEntry.id).filter(filt).first() is not None
- return does_exist
-
-
-def media_entries_for_tag_slug(dummy_db, tag_slug):
- return MediaEntry.query \
- .join(MediaEntry.tags_helper) \
- .join(MediaTag.tag_helper) \
- .filter(
- (MediaEntry.state == u'processed')
- & (Tag.slug == tag_slug))
-
-
-def clean_orphan_tags(commit=True):
- """Search for unused MediaTags and delete them"""
- q1 = Session.query(Tag).outerjoin(MediaTag).filter(MediaTag.id==None)
- for t in q1:
- Session.delete(t)
- # The "let the db do all the work" version:
- # q1 = Session.query(Tag.id).outerjoin(MediaTag).filter(MediaTag.id==None)
- # q2 = Session.query(Tag).filter(Tag.id.in_(q1))
- # q2.delete(synchronize_session = False)
- if commit:
- Session.commit()
-
-
-def check_collection_slug_used(dummy_db, creator_id, slug, ignore_c_id):
- filt = (Collection.creator == creator_id) \
- & (Collection.slug == slug)
- if ignore_c_id is not None:
- filt = filt & (Collection.id != ignore_c_id)
- does_exist = Session.query(Collection.id).filter(filt).first() is not None
- return does_exist
-
-
-if __name__ == '__main__':
- from mediagoblin.db.sql.open import setup_connection_and_db_from_config
-
- conn,db = setup_connection_and_db_from_config({'sql_engine':'sqlite:///mediagoblin.db'})
-
- clean_orphan_tags()
+def inspect_table(metadata, table_name):
+ """Simple helper to get a ref to an already existing table"""
+ return Table(table_name, metadata, autoload=True,
+ autoload_with=metadata.bind)
diff --git a/mediagoblin/db/sql/migrations.py b/mediagoblin/db/migrations.py
index bc68caa3..80ec5269 100644
--- a/mediagoblin/db/sql/migrations.py
+++ b/mediagoblin/db/migrations.py
@@ -18,11 +18,13 @@ import datetime
from sqlalchemy import (MetaData, Table, Column, Boolean, SmallInteger,
Integer, Unicode, UnicodeText, DateTime,
- ForeignKey, UniqueConstraint)
+ ForeignKey)
+from sqlalchemy.exc import ProgrammingError
from sqlalchemy.ext.declarative import declarative_base
+from migrate.changeset.constraint import UniqueConstraint
-from mediagoblin.db.sql.util import RegisterMigration
-from mediagoblin.db.sql.models import MediaEntry, Collection, User
+from mediagoblin.db.migration_tools import RegisterMigration, inspect_table
+from mediagoblin.db.models import MediaEntry, Collection, User
MIGRATIONS = {}
@@ -58,8 +60,7 @@ def add_wants_notification_column(db_conn):
def add_transcoding_progress(db_conn):
metadata = MetaData(bind=db_conn.bind)
- media_entry = Table('core__media_entries', metadata, autoload=True,
- autoload_with=db_conn.bind)
+ media_entry = inspect_table(metadata, 'core__media_entries')
col = Column('transcoding_progress', SmallInteger)
col.create(media_entry)
@@ -92,15 +93,20 @@ class CollectionItem_v0(declarative_base()):
## This should be activated, normally.
## But this would change the way the next migration used to work.
## So it's commented for now.
- # __table_args__ = (
- # UniqueConstraint('collection', 'media_entry'),
- # {})
+ __table_args__ = (
+ UniqueConstraint('collection', 'media_entry'),
+ {})
+
+collectionitem_unique_constraint_done = False
@RegisterMigration(4, MIGRATIONS)
def add_collection_tables(db_conn):
Collection_v0.__table__.create(db_conn.bind)
CollectionItem_v0.__table__.create(db_conn.bind)
+ global collectionitem_unique_constraint_done
+ collectionitem_unique_constraint_done = True
+
db_conn.commit()
@@ -108,8 +114,7 @@ def add_collection_tables(db_conn):
def add_mediaentry_collected(db_conn):
metadata = MetaData(bind=db_conn.bind)
- media_entry = Table('core__media_entries', metadata, autoload=True,
- autoload_with=db_conn.bind)
+ media_entry = inspect_table(metadata, 'core__media_entries')
col = Column('collected', Integer, default=0)
col.create(media_entry)
@@ -128,3 +133,54 @@ class ProcessingMetaData_v0(declarative_base()):
def create_processing_metadata_table(db):
ProcessingMetaData_v0.__table__.create(db.bind)
db.commit()
+
+
+# Okay, problem being:
+# Migration #4 forgot to add the uniqueconstraint for the
+# new tables. While creating the tables from scratch had
+# the constraint enabled.
+#
+# So we have four situations that should end up at the same
+# db layout:
+#
+# 1. Fresh install.
+# Well, easy. Just uses the tables in models.py
+# 2. Fresh install using a git version just before this migration
+# The tables are all there, the unique constraint is also there.
+# This migration should do nothing.
+# But as we can't detect the uniqueconstraint easily,
+# this migration just adds the constraint again.
+# And possibly fails very loud. But ignores the failure.
+# 3. old install, not using git, just releases.
+# This one will get the new tables in #4 (now with constraint!)
+# And this migration is just skipped silently.
+# 4. old install, always on latest git.
+# This one has the tables, but lacks the constraint.
+# So this migration adds the constraint.
+@RegisterMigration(7, MIGRATIONS)
+def fix_CollectionItem_v0_constraint(db_conn):
+ """Add the forgotten Constraint on CollectionItem"""
+
+ global collectionitem_unique_constraint_done
+ if collectionitem_unique_constraint_done:
+ # Reset it. Maybe the whole thing gets run again
+ # For a different db?
+ collectionitem_unique_constraint_done = False
+ return
+
+ metadata = MetaData(bind=db_conn.bind)
+
+ CollectionItem_table = inspect_table(metadata, 'core__collection_items')
+
+ constraint = UniqueConstraint('collection', 'media_entry',
+ name='core__collection_items_collection_media_entry_key',
+ table=CollectionItem_table)
+
+ try:
+ constraint.create()
+ except ProgrammingError:
+ # User probably has an install that was run since the
+ # collection tables were added, so we don't need to run this migration.
+ pass
+
+ db_conn.commit()
diff --git a/mediagoblin/db/mixin.py b/mediagoblin/db/mixin.py
index a8436c70..001b7826 100644
--- a/mediagoblin/db/mixin.py
+++ b/mediagoblin/db/mixin.py
@@ -27,9 +27,11 @@ These functions now live here and get "mixed in" into the
real objects.
"""
+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_manager
+from mediagoblin.media_types import get_media_managers, FileTypeNotSupported
from mediagoblin.tools import common, licenses
from mediagoblin.tools.text import cleaned_markdown_conversion
from mediagoblin.tools.url import slugify
@@ -56,8 +58,7 @@ class MediaEntryMixin(object):
self.slug = slugify(self.title)
- duplicate = check_media_slug_used(mg_globals.database,
- self.uploader, self.slug, self.id)
+ duplicate = check_media_slug_used(self.uploader, self.slug, self.id)
if duplicate:
if self.id is not None:
@@ -97,13 +98,14 @@ class MediaEntryMixin(object):
@property
def slug_or_id(self):
- return (self.slug or self._id)
+ return (self.slug or self.id)
+
def url_for_self(self, urlgen, **extra_args):
"""
Generate an appropriate url for ourselves
- Use a slug if we have one, else use our '_id'.
+ Use a slug if we have one, else use our 'id'.
"""
uploader = self.get_uploader
@@ -125,11 +127,26 @@ class MediaEntryMixin(object):
else:
# No thumbnail in media available. Get the media's
# MEDIA_MANAGER for the fallback icon and return static URL
- # Raise FileTypeNotSupported in case no such manager is enabled
- manager = get_media_manager(self.media_type)
+ # Raises FileTypeNotSupported in case no such manager is enabled
+ manager = self.media_manager
thumb_url = mg_globals.app.staticdirector(manager[u'default_thumb'])
return thumb_url
+ @cached_property
+ def media_manager(self):
+ """Returns the MEDIA_MANAGER of the media's media_type
+
+ 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
+ # Not found? Then raise an error
+ raise FileTypeNotSupported(
+ "MediaManager not in enabled types. Check media_types in config?")
+
def get_fail_exception(self):
"""
Get the exception that's appropriate for this error
@@ -190,13 +207,13 @@ class CollectionMixin(object):
@property
def slug_or_id(self):
- return (self.slug or self._id)
+ return (self.slug or self.id)
def url_for_self(self, urlgen, **extra_args):
"""
Generate an appropriate url for ourselves
- Use a slug if we have one, else use our '_id'.
+ Use a slug if we have one, else use our 'id'.
"""
creator = self.get_creator
diff --git a/mediagoblin/db/sql/models.py b/mediagoblin/db/models.py
index b48c1fbe..782bf869 100644
--- a/mediagoblin/db/sql/models.py
+++ b/mediagoblin/db/models.py
@@ -18,7 +18,7 @@
TODO: indexes on foreignkeys, where useful.
"""
-
+import logging
import datetime
import sys
@@ -31,10 +31,10 @@ from sqlalchemy.sql.expression import desc
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.util import memoized_property
-from mediagoblin.db.sql.extratypes import PathTupleWithSlashes, JSONEncoded
-from mediagoblin.db.sql.base import Base, DictReadAttrProxy
+from mediagoblin.db.extratypes import PathTupleWithSlashes, JSONEncoded
+from mediagoblin.db.base import Base, DictReadAttrProxy, Session
from mediagoblin.db.mixin import UserMixin, MediaEntryMixin, MediaCommentMixin, CollectionMixin, CollectionItemMixin
-from mediagoblin.db.sql.base import Session
+from mediagoblin.tools.files import delete_media_files
# It's actually kind of annoying how sqlalchemy-migrate does this, if
# I understand it right, but whatever. Anyway, don't remove this :P
@@ -43,17 +43,7 @@ from mediagoblin.db.sql.base import Session
# this import-based meddling...
from migrate import changeset
-
-class SimpleFieldAlias(object):
- """An alias for any field"""
- def __init__(self, fieldname):
- self.fieldname = fieldname
-
- def __get__(self, instance, cls):
- return getattr(instance, self.fieldname)
-
- def __set__(self, instance, val):
- setattr(instance, self.fieldname, val)
+_log = logging.getLogger(__name__)
class User(Base, UserMixin):
@@ -83,8 +73,6 @@ class User(Base, UserMixin):
## TODO
# plugin data would be in a separate model
- _id = SimpleFieldAlias("id")
-
def __repr__(self):
return '<{0} #{1} {2} {3} "{4}">'.format(
self.__class__.__name__,
@@ -93,6 +81,27 @@ class User(Base, UserMixin):
'admin' if self.is_admin else 'user',
self.username)
+ def delete(self, **kwargs):
+ """Deletes a User and all related entries/comments/files/..."""
+ # Delete this user's Collections and all contained CollectionItems
+ for collection in self.collections:
+ collection.delete(commit=False)
+
+ media_entries = MediaEntry.query.filter(MediaEntry.uploader == self.id)
+ for media in media_entries:
+ # TODO: Make sure that "MediaEntry.delete()" also deletes
+ # all related files/Comments
+ media.delete(del_orphan_tags=False, commit=False)
+
+ # Delete now unused tags
+ # TODO: import here due to cyclic imports!!! This cries for refactoring
+ from mediagoblin.db.util import clean_orphan_tags
+ clean_orphan_tags(commit=False)
+
+ # Delete user, pass through commit=False/True in kwargs
+ super(User, self).delete(**kwargs)
+ _log.info('Deleted user "{0}" account'.format(self.username))
+
class MediaEntry(Base, MediaEntryMixin):
"""
@@ -137,7 +146,6 @@ class MediaEntry(Base, MediaEntryMixin):
)
attachment_files_helper = relationship("MediaAttachmentFile",
- cascade="all, delete-orphan",
order_by="MediaAttachmentFile.created"
)
attachment_files = association_proxy("attachment_files_helper", "dict_view",
@@ -146,7 +154,7 @@ class MediaEntry(Base, MediaEntryMixin):
)
tags_helper = relationship("MediaTag",
- cascade="all, delete-orphan"
+ cascade="all, delete-orphan" # should be automatically deleted
)
tags = association_proxy("tags_helper", "dict_view",
creator=lambda v: MediaTag(name=v["name"], slug=v["slug"])
@@ -161,8 +169,6 @@ class MediaEntry(Base, MediaEntryMixin):
# media_data
# fail_error
- _id = SimpleFieldAlias("id")
-
def get_comments(self, ascending=False):
order_col = MediaComment.created
if not ascending:
@@ -233,6 +239,37 @@ class MediaEntry(Base, MediaEntryMixin):
id=self.id,
title=safe_title)
+ def delete(self, del_orphan_tags=True, **kwargs):
+ """Delete MediaEntry and all related files/attachments/comments
+
+ This will *not* automatically delete unused collections, which
+ can remain empty...
+
+ :param del_orphan_tags: True/false if we delete unused Tags too
+ :param commit: True/False if this should end the db transaction"""
+ # User's CollectionItems are automatically deleted via "cascade".
+ # Delete all the associated comments
+ for comment in self.get_comments():
+ comment.delete(commit=False)
+
+ # Delete all related files/attachments
+ try:
+ delete_media_files(self)
+ except OSError, error:
+ # Returns list of files we failed to delete
+ _log.error('No such files from the user "{1}" to delete: '
+ '{0}'.format(str(error), self.get_uploader))
+ _log.info('Deleted Media entry id "{0}"'.format(self.id))
+ # Related MediaTag's are automatically cleaned, but we might
+ # want to clean out unused Tag's too.
+ if del_orphan_tags:
+ # TODO: Import here due to cyclic imports!!!
+ # This cries for refactoring
+ from mediagoblin.db.util import clean_orphan_tags
+ clean_orphan_tags(commit=False)
+ # pass through commit=False/True in kwargs
+ super(MediaEntry, self).delete(**kwargs)
+
class FileKeynames(Base):
"""
@@ -359,10 +396,12 @@ class MediaComment(Base, MediaCommentMixin):
get_author = relationship(User)
- _id = SimpleFieldAlias("id")
-
class Collection(Base, CollectionMixin):
+ """An 'album' or 'set' of media by a user.
+
+ On deletion, contained CollectionItems get automatically reaped via
+ SQL cascade"""
__tablename__ = "core__collections"
id = Column(Integer, primary_key=True)
@@ -372,19 +411,19 @@ class Collection(Base, CollectionMixin):
index=True)
description = Column(UnicodeText)
creator = Column(Integer, ForeignKey(User.id), nullable=False)
+ # TODO: No of items in Collection. Badly named, can we migrate to num_items?
items = Column(Integer, default=0)
- get_creator = relationship(User)
+ get_creator = relationship(User, backref="collections")
def get_collection_items(self, ascending=False):
+ #TODO, is this still needed with self.collection_items being available?
order_col = CollectionItem.position
if not ascending:
order_col = desc(order_col)
return CollectionItem.query.filter_by(
collection=self.id).order_by(order_col)
- _id = SimpleFieldAlias("id")
-
class CollectionItem(Base, CollectionItemMixin):
__tablename__ = "core__collection_items"
@@ -396,12 +435,13 @@ class CollectionItem(Base, CollectionItemMixin):
note = Column(UnicodeText, nullable=True)
added = Column(DateTime, nullable=False, default=datetime.datetime.now)
position = Column(Integer)
- in_collection = relationship("Collection")
+ in_collection = relationship("Collection",
+ backref=backref(
+ "collection_items",
+ cascade="all, delete-orphan"))
get_media_entry = relationship(MediaEntry)
- _id = SimpleFieldAlias("id")
-
__table_args__ = (
UniqueConstraint('collection', 'media_entry'),
{})
diff --git a/mediagoblin/db/sql/models_v0.py b/mediagoblin/db/models_v0.py
index 06f87d28..ec51a1f5 100644
--- a/mediagoblin/db/sql/models_v0.py
+++ b/mediagoblin/db/models_v0.py
@@ -31,9 +31,8 @@ from sqlalchemy.orm.collections import attribute_mapped_collection
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.util import memoized_property
-from mediagoblin.db.sql.extratypes import PathTupleWithSlashes, JSONEncoded
-from mediagoblin.db.sql.base import GMGTableBase
-from mediagoblin.db.sql.base import Session
+from mediagoblin.db.extratypes import PathTupleWithSlashes, JSONEncoded
+from mediagoblin.db.base import GMGTableBase, Session
Base_v0 = declarative_base(cls=GMGTableBase)
diff --git a/mediagoblin/db/mongo/indexes.py b/mediagoblin/db/mongo/indexes.py
deleted file mode 100644
index a63c24ae..00000000
--- a/mediagoblin/db/mongo/indexes.py
+++ /dev/null
@@ -1,146 +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/>.
-
-"""
-Indexes for the local database.
-
-To add new indexes
-------------------
-
-Indexes are recorded in the following format:
-
-ACTIVE_INDEXES = {
- 'collection_name': {
- 'identifier': { # key identifier used for possibly deprecating later
- 'index': [index_foo_goes_here]}}
-
-... and anything else being parameters to the create_index function
-(including unique=True, etc)
-
-Current indexes must be registered in ACTIVE_INDEXES... deprecated
-indexes should be marked in DEPRECATED_INDEXES.
-
-Remember, ordering of compound indexes MATTERS. Read below for more.
-
-REQUIRED READING:
- - http://kylebanker.com/blog/2010/09/21/the-joy-of-mongodb-indexes/
-
- - http://www.mongodb.org/display/DOCS/Indexes
- - http://www.mongodb.org/display/DOCS/Indexing+Advice+and+FAQ
-
-
-To remove deprecated indexes
-----------------------------
-
-Removing deprecated indexes is the same, just move the index into the
-deprecated indexes mapping.
-
-DEPRECATED_INDEXES = {
- 'collection_name': {
- 'deprecated_index_identifier1': {
- 'index': [index_foo_goes_here]}}
-
-... etc.
-
-If an index has been deprecated that identifier should NEVER BE USED
-AGAIN. Eg, if you previously had 'awesomepants_unique', you shouldn't
-use 'awesomepants_unique' again, you should create a totally new name
-or at worst use 'awesomepants_unique2'.
-"""
-
-from pymongo import ASCENDING, DESCENDING
-
-
-################
-# Active indexes
-################
-ACTIVE_INDEXES = {}
-
-# MediaEntry indexes
-# ------------------
-
-MEDIAENTRY_INDEXES = {
- 'uploader_slug_unique': {
- # Matching an object to an uploader + slug.
- # MediaEntries are unique on these two combined, eg:
- # /u/${myuser}/m/${myslugname}/
- 'index': [('uploader', ASCENDING),
- ('slug', ASCENDING)],
- 'unique': True},
-
- 'created': {
- # A global index for all media entries created, in descending
- # order. This is used for the site's frontpage.
- 'index': [('created', DESCENDING)]},
-
- 'uploader_created': {
- # Indexing on uploaders and when media entries are created.
- # Used for showing a user gallery, etc.
- 'index': [('uploader', ASCENDING),
- ('created', DESCENDING)]},
-
- 'state_uploader_tags_created': {
- # Indexing on processed?, media uploader, associated tags, and
- # timestamp Used for showing media items matching a tag
- # search, most recent first.
- 'index': [('state', ASCENDING),
- ('uploader', ASCENDING),
- ('tags.slug', DESCENDING),
- ('created', DESCENDING)]},
-
- 'state_tags_created': {
- # Indexing on processed?, media tags, and timestamp (across all users)
- # This is used for a front page tag search.
- 'index': [('state', ASCENDING),
- ('tags.slug', DESCENDING),
- ('created', DESCENDING)]}}
-
-
-ACTIVE_INDEXES['media_entries'] = MEDIAENTRY_INDEXES
-
-
-# User indexes
-# ------------
-
-USER_INDEXES = {
- 'username_unique': {
- # Index usernames, and make sure they're unique.
- # ... I guess we might need to adjust this once we're federated :)
- 'index': 'username',
- 'unique': True},
- 'created': {
- # All most recently created users
- 'index': 'created'}}
-
-
-ACTIVE_INDEXES['users'] = USER_INDEXES
-
-
-# MediaComment indexes
-
-MEDIA_COMMENT_INDEXES = {
- 'mediaentry_created': {
- 'index': [('media_entry', ASCENDING),
- ('created', DESCENDING)]}}
-
-ACTIVE_INDEXES['media_comments'] = MEDIA_COMMENT_INDEXES
-
-
-####################
-# Deprecated indexes
-####################
-
-DEPRECATED_INDEXES = {}
diff --git a/mediagoblin/db/mongo/migrations.py b/mediagoblin/db/mongo/migrations.py
deleted file mode 100644
index 569dec88..00000000
--- a/mediagoblin/db/mongo/migrations.py
+++ /dev/null
@@ -1,208 +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/>.
-
-from mediagoblin.db.mongo.util import RegisterMigration
-from mediagoblin.tools.text import cleaned_markdown_conversion
-
-
-def add_table_field(db, table_name, field_name, default_value):
- """
- Add a new field to the table/collection named table_name.
- The field will have the name field_name and the value default_value
- """
- db[table_name].update(
- {field_name: {'$exists': False}},
- {'$set': {field_name: default_value}},
- multi=True)
-
-
-def drop_table_field(db, table_name, field_name):
- """
- Drop an old field from a table/collection
- """
- db[table_name].update(
- {field_name: {'$exists': True}},
- {'$unset': {field_name: 1}},
- multi=True)
-
-
-# Please see mediagoblin/tests/test_migrations.py for some examples of
-# basic migrations.
-
-
-@RegisterMigration(1)
-def user_add_bio_html(database):
- """
- Users now have richtext bios via Markdown, reflect appropriately.
- """
- collection = database['users']
-
- target = collection.find(
- {'bio_html': {'$exists': False}})
-
- for document in target:
- document['bio_html'] = cleaned_markdown_conversion(
- document['bio'])
- collection.save(document)
-
-
-@RegisterMigration(2)
-def mediaentry_mediafiles_main_to_original(database):
- """
- Rename "main" media file to "original".
- """
- collection = database['media_entries']
- target = collection.find(
- {'media_files.main': {'$exists': True}})
-
- for document in target:
- original = document['media_files'].pop('main')
- document['media_files']['original'] = original
-
- collection.save(document)
-
-
-@RegisterMigration(3)
-def mediaentry_remove_thumbnail_file(database):
- """
- Use media_files['thumb'] instead of media_entries['thumbnail_file']
- """
- database['media_entries'].update(
- {'thumbnail_file': {'$exists': True}},
- {'$unset': {'thumbnail_file': 1}},
- multi=True)
-
-
-@RegisterMigration(4)
-def mediaentry_add_queued_task_id(database):
- """
- Add the 'queued_task_id' field for entries that don't have it.
- """
- add_table_field(database, 'media_entries', 'queued_task_id', None)
-
-
-@RegisterMigration(5)
-def mediaentry_add_fail_error_and_metadata(database):
- """
- Add 'fail_error' and 'fail_metadata' fields to media entries
- """
- add_table_field(database, 'media_entries', 'fail_error', None)
- add_table_field(database, 'media_entries', 'fail_metadata', {})
-
-
-@RegisterMigration(6)
-def user_add_forgot_password_token_and_expires(database):
- """
- Add token and expiration fields to help recover forgotten passwords
- """
- add_table_field(database, 'users', 'fp_verification_key', None)
- add_table_field(database, 'users', 'fp_token_expire', None)
-
-
-@RegisterMigration(7)
-def media_type_image_to_multimedia_type_image(database):
- database['media_entries'].update(
- {'media_type': 'image'},
- {'$set': {'media_type': 'mediagoblin.media_types.image'}},
- multi=True)
-
-
-@RegisterMigration(8)
-def mediaentry_add_license(database):
- """
- Add the 'license' field for entries that don't have it.
- """
- add_table_field(database, 'media_entries', 'license', None)
-
-
-@RegisterMigration(9)
-def remove_calculated_html(database):
- """
- Drop pre-rendered html again and calculate things
- on the fly (and cache):
- - User.bio_html
- - MediaEntry.description_html
- - MediaComment.content_html
- """
- drop_table_field(database, 'users', 'bio_html')
- drop_table_field(database, 'media_entries', 'description_html')
- drop_table_field(database, 'media_comments', 'content_html')
-
-
-@RegisterMigration(10)
-def convert_video_media_data(database):
- """
- Move media_data["video"] directly into media_data
- """
- collection = database['media_entries']
- target = collection.find(
- {'media_data.video': {'$exists': True}})
-
- for document in target:
- assert len(document['media_data']) == 1
- document['media_data'] = document['media_data']['video']
- collection.save(document)
-
-
-@RegisterMigration(11)
-def convert_gps_media_data(database):
- """
- Move media_data["gps"]["*"] to media_data["gps_*"].
- In preparation for media_data.gps_*
- """
- collection = database['media_entries']
- target = collection.find(
- {'media_data.gps': {'$exists': True}})
-
- for document in target:
- for key, value in document['media_data']['gps'].iteritems():
- document['media_data']['gps_' + key] = value
- del document['media_data']['gps']
- collection.save(document)
-
-
-@RegisterMigration(12)
-def convert_exif_media_data(database):
- """
- Move media_data["exif"]["clean"] to media_data["exif_all"].
- Drop media_data["exif"]["useful"]
- In preparation for media_data.exif_all
- """
- collection = database['media_entries']
- target = collection.find(
- {'media_data.exif.clean': {'$exists': True}})
-
- for document in target:
- media_data = document['media_data']
-
- exif_all = media_data['exif'].pop('clean')
- if len(exif_all):
- media_data['exif_all'] = exif_all
-
- del media_data['exif']['useful']
-
- assert len(media_data['exif']) == 0
- del media_data['exif']
-
- collection.save(document)
-
-
-@RegisterMigration(13)
-def user_add_wants_comment_notification(database):
- """
- Add wants_comment_notification to user model
- """
- add_table_field(database, 'users', 'wants_comment_notification', True)
diff --git a/mediagoblin/db/mongo/models.py b/mediagoblin/db/mongo/models.py
deleted file mode 100644
index 3f1363d5..00000000
--- a/mediagoblin/db/mongo/models.py
+++ /dev/null
@@ -1,310 +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 datetime
-
-from mongokit import Document
-
-from mediagoblin.db.mongo import migrations
-from mediagoblin.db.mongo.util import ASCENDING, DESCENDING, ObjectId
-from mediagoblin.tools.pagination import Pagination
-from mediagoblin.db.mixin import UserMixin, MediaEntryMixin, MediaCommentMixin
-
-
-class MongoPK(object):
- """An alias for the _id primary key"""
- def __get__(self, instance, cls):
- return instance['_id']
- def __set__(self, instance, val):
- instance['_id'] = val
- def __delete__(self, instance):
- del instance['_id']
-
-
-###################
-# Custom validators
-###################
-
-########
-# Models
-########
-
-
-class User(Document, UserMixin):
- """
- A user of MediaGoblin.
-
- Structure:
- - username: The username of this user, should be unique to this instance.
- - email: Email address of this user
- - created: When the user was created
- - plugin_data: a mapping of extra plugin information for this User.
- Nothing uses this yet as we don't have plugins, but someday we
- might... :)
- - pw_hash: Hashed version of user's password.
- - email_verified: Whether or not the user has verified their email or not.
- Most parts of the site are disabled for users who haven't yet.
- - status: whether or not the user is active, etc. Currently only has two
- values, 'needs_email_verification' or 'active'. (In the future, maybe
- we'll change this to a boolean with a key of 'active' and have a
- separate field for a reason the user's been disabled if that's
- appropriate... email_verified is already separate, after all.)
- - wants_comment_notification: The user has selected that they want to be
- notified when comments are posted on their media.
- - verification_key: If the user is awaiting email verification, the user
- will have to provide this key (which will be encoded in the presented
- URL) in order to confirm their email as active.
- - is_admin: Whether or not this user is an administrator or not.
- - url: this user's personal webpage/website, if appropriate.
- - bio: biography of this user (plaintext, in markdown)
- """
- __collection__ = 'users'
- use_dot_notation = True
-
- structure = {
- 'username': unicode,
- 'email': unicode,
- 'created': datetime.datetime,
- 'plugin_data': dict, # plugins can dump stuff here.
- 'pw_hash': unicode,
- 'email_verified': bool,
- 'status': unicode,
- 'wants_comment_notification': bool,
- 'verification_key': unicode,
- 'is_admin': bool,
- 'url': unicode,
- 'bio': unicode, # May contain markdown
- 'fp_verification_key': unicode, # forgotten password verification key
- 'fp_token_expire': datetime.datetime,
- }
-
- required_fields = ['username', 'created', 'pw_hash', 'email']
-
- default_values = {
- 'created': datetime.datetime.utcnow,
- 'email_verified': False,
- 'wants_comment_notification': True,
- 'status': u'needs_email_verification',
- 'is_admin': False}
-
- id = MongoPK()
-
-
-class MediaEntry(Document, MediaEntryMixin):
- """
- Record of a piece of media.
-
- Structure:
- - uploader: A reference to a User who uploaded this.
-
- - title: Title of this work
-
- - slug: A normalized "slug" which can be used as part of a URL to retrieve
- this work, such as 'my-works-name-in-slug-form' may be viewable by
- 'http://mg.example.org/u/username/m/my-works-name-in-slug-form/'
- Note that since URLs are constructed this way, slugs must be unique
- per-uploader. (An index is provided to enforce that but code should be
- written on the python side to ensure this as well.)
-
- - created: Date and time of when this piece of work was uploaded.
-
- - description: Uploader-set description of this work. This can be marked
- up with MarkDown for slight fanciness (links, boldness, italics,
- paragraphs...)
-
- - media_type: What type of media is this? Currently we only support
- 'image' ;)
-
- - media_data: Extra information that's media-format-dependent.
- For example, images might contain some EXIF data that's not appropriate
- to other formats. You might store it like:
-
- mediaentry.media_data['exif'] = {
- 'manufacturer': 'CASIO',
- 'model': 'QV-4000',
- 'exposure_time': .659}
-
- Alternately for video you might store:
-
- # play length in seconds
- mediaentry.media_data['play_length'] = 340
-
- ... so what's appropriate here really depends on the media type.
-
- - plugin_data: a mapping of extra plugin information for this User.
- Nothing uses this yet as we don't have plugins, but someday we
- might... :)
-
- - tags: A list of tags. Each tag is stored as a dictionary that has a key
- for the actual name and the normalized name-as-slug, so ultimately this
- looks like:
- [{'name': 'Gully Gardens',
- 'slug': 'gully-gardens'},
- {'name': 'Castle Adventure Time?!",
- 'slug': 'castle-adventure-time'}]
-
- - state: What's the state of this file? Active, inactive, disabled, etc...
- But really for now there are only two states:
- "unprocessed": uploaded but needs to go through processing for display
- "processed": processed and able to be displayed
-
- - license: URI for media's license.
-
- - queued_media_file: storage interface style filepath describing a file
- queued for processing. This is stored in the mg_globals.queue_store
- storage system.
-
- - queued_task_id: celery task id. Use this to fetch the task state.
-
- - media_files: Files relevant to this that have actually been processed
- and are available for various types of display. Stored like:
- {'thumb': ['dir1', 'dir2', 'pic.png'}
-
- - attachment_files: A list of "attachment" files, ones that aren't
- critical to this piece of media but may be usefully relevant to people
- viewing the work. (currently unused.)
-
- - fail_error: path to the exception raised
- - fail_metadata:
- """
- __collection__ = 'media_entries'
- use_dot_notation = True
-
- structure = {
- 'uploader': ObjectId,
- 'title': unicode,
- 'slug': unicode,
- 'created': datetime.datetime,
- 'description': unicode, # May contain markdown/up
- 'media_type': unicode,
- 'media_data': dict, # extra data relevant to this media_type
- 'plugin_data': dict, # plugins can dump stuff here.
- 'tags': [dict],
- 'state': unicode,
- 'license': unicode,
-
- # For now let's assume there can only be one main file queued
- # at a time
- 'queued_media_file': [unicode],
- 'queued_task_id': unicode,
-
- # A dictionary of logical names to filepaths
- 'media_files': dict,
-
- # The following should be lists of lists, in appropriate file
- # record form
- 'attachment_files': list,
-
- # If things go badly in processing things, we'll store that
- # data here
- 'fail_error': unicode,
- 'fail_metadata': dict}
-
- required_fields = [
- 'uploader', 'created', 'media_type', 'slug']
-
- default_values = {
- 'created': datetime.datetime.utcnow,
- 'state': u'unprocessed'}
-
- id = MongoPK()
-
- def media_data_init(self, **kwargs):
- self.media_data.update(kwargs)
-
- def get_comments(self, ascending=False):
- if ascending:
- order = ASCENDING
- else:
- order = DESCENDING
-
- return self.db.MediaComment.find({
- 'media_entry': self._id}).sort('created', order)
-
- def url_to_prev(self, urlgen):
- """
- Provide a url to the previous entry from this user, if there is one
- """
- cursor = self.db.MediaEntry.find({'_id': {"$gt": self._id},
- 'uploader': self.uploader,
- 'state': 'processed'}).sort(
- '_id', ASCENDING).limit(1)
- for media in cursor:
- return media.url_for_self(urlgen)
-
- def url_to_next(self, urlgen):
- """
- Provide a url to the next entry from this user, if there is one
- """
- cursor = self.db.MediaEntry.find({'_id': {"$lt": self._id},
- 'uploader': self.uploader,
- 'state': 'processed'}).sort(
- '_id', DESCENDING).limit(1)
-
- for media in cursor:
- return media.url_for_self(urlgen)
-
- @property
- def get_uploader(self):
- return self.db.User.find_one({'_id': self.uploader})
-
-
-class MediaComment(Document, MediaCommentMixin):
- """
- A comment on a MediaEntry.
-
- Structure:
- - media_entry: The media entry this comment is attached to
- - author: user who posted this comment
- - created: when the comment was created
- - content: plaintext (but markdown'able) version of the comment's content.
- """
-
- __collection__ = 'media_comments'
- use_dot_notation = True
-
- structure = {
- 'media_entry': ObjectId,
- 'author': ObjectId,
- 'created': datetime.datetime,
- 'content': unicode,
- }
-
- required_fields = [
- 'media_entry', 'author', 'created', 'content']
-
- default_values = {
- 'created': datetime.datetime.utcnow}
-
- def media_entry(self):
- return self.db.MediaEntry.find_one({'_id': self['media_entry']})
-
- @property
- def get_author(self):
- return self.db.User.find_one({'_id': self['author']})
-
-
-REGISTER_MODELS = [
- MediaEntry,
- User,
- MediaComment]
-
-
-def register_models(connection):
- """
- Register all models in REGISTER_MODELS with this connection.
- """
- connection.register(REGISTER_MODELS)
diff --git a/mediagoblin/db/mongo/open.py b/mediagoblin/db/mongo/open.py
deleted file mode 100644
index c4f37b42..00000000
--- a/mediagoblin/db/mongo/open.py
+++ /dev/null
@@ -1,82 +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 pymongo
-import mongokit
-from paste.deploy.converters import asint
-from mediagoblin.db.mongo import models
-from mediagoblin.db.mongo.util import MigrationManager
-
-
-def load_models(app_config):
- pass
-
-
-def connect_database_from_config(app_config, use_pymongo=False):
- """
- Connect to the main database, take config from app_config
-
- Optionally use pymongo instead of mongokit for the connection.
- """
- port = app_config.get('db_port')
- if port:
- port = asint(port)
-
- if use_pymongo:
- connection = pymongo.Connection(
- app_config.get('db_host'), port)
- else:
- connection = mongokit.Connection(
- app_config.get('db_host'), port)
- return connection
-
-
-def setup_connection_and_db_from_config(app_config, use_pymongo=False):
- """
- Setup connection and database from config.
-
- Optionally use pymongo instead of mongokit.
- """
- connection = connect_database_from_config(app_config, use_pymongo)
- database_path = app_config['db_name']
- db = connection[database_path]
-
- if not use_pymongo:
- models.register_models(connection)
-
- return (connection, db)
-
-
-def check_db_migrations_current(db):
- # This MUST be imported so as to set up the appropriate migrations!
- from mediagoblin.db.mongo import migrations
-
- # Init the migration number if necessary
- migration_manager = MigrationManager(db)
- migration_manager.install_migration_version_if_missing()
-
- # Tiny hack to warn user if our migration is out of date
- if not migration_manager.database_at_latest_migration():
- db_migration_num = migration_manager.database_current_migration()
- latest_migration_num = migration_manager.latest_migration()
- if db_migration_num < latest_migration_num:
- print (
- "*WARNING:* Your migrations are out of date, "
- "maybe run ./bin/gmg migrate?")
- elif db_migration_num > latest_migration_num:
- print (
- "*WARNING:* Your migrations are out of date... "
- "in fact they appear to be from the future?!")
diff --git a/mediagoblin/db/mongo/util.py b/mediagoblin/db/mongo/util.py
deleted file mode 100644
index f61ae6be..00000000
--- a/mediagoblin/db/mongo/util.py
+++ /dev/null
@@ -1,318 +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/>.
-
-"""
-Utilities for database operations.
-
-Some note on migration and indexing tools:
-
-We store information about what the state of the database is in the
-'mediagoblin' document of the 'app_metadata' collection. Keys in that
-document relevant to here:
-
- - 'migration_number': The integer representing the current state of
- the migrations
-"""
-
-import copy
-
-# Imports that other modules might use
-from pymongo import ASCENDING, DESCENDING
-from pymongo.errors import InvalidId
-from mongokit import ObjectId
-
-from mediagoblin.db.mongo.indexes import ACTIVE_INDEXES, DEPRECATED_INDEXES
-
-
-################
-# Indexing tools
-################
-
-
-def add_new_indexes(database, active_indexes=ACTIVE_INDEXES):
- """
- Add any new indexes to the database.
-
- Args:
- - database: pymongo or mongokit database instance.
- - active_indexes: indexes to possibly add in the pattern of:
- {'collection_name': {
- 'identifier': {
- 'index': [index_foo_goes_here],
- 'unique': True}}
- where 'index' is the index to add and all other options are
- arguments for collection.create_index.
-
- Returns:
- A list of indexes added in form ('collection', 'index_name')
- """
- indexes_added = []
-
- for collection_name, indexes in active_indexes.iteritems():
- collection = database[collection_name]
- collection_indexes = collection.index_information().keys()
-
- for index_name, index_data in indexes.iteritems():
- if not index_name in collection_indexes:
- # Get a copy actually so we don't modify the actual
- # structure
- index_data = copy.copy(index_data)
- index = index_data.pop('index')
- collection.create_index(
- index, name=index_name, **index_data)
-
- indexes_added.append((collection_name, index_name))
-
- return indexes_added
-
-
-def remove_deprecated_indexes(database, deprecated_indexes=DEPRECATED_INDEXES):
- """
- Remove any deprecated indexes from the database.
-
- Args:
- - database: pymongo or mongokit database instance.
- - deprecated_indexes: the indexes to deprecate in the pattern of:
- {'collection_name': {
- 'identifier': {
- 'index': [index_foo_goes_here],
- 'unique': True}}
-
- (... although we really only need the 'identifier' here, as the
- rest of the information isn't used in this case. But it's kept
- around so we can remember what it was)
-
- Returns:
- A list of indexes removed in form ('collection', 'index_name')
- """
- indexes_removed = []
-
- for collection_name, indexes in deprecated_indexes.iteritems():
- collection = database[collection_name]
- collection_indexes = collection.index_information().keys()
-
- for index_name, index_data in indexes.iteritems():
- if index_name in collection_indexes:
- collection.drop_index(index_name)
-
- indexes_removed.append((collection_name, index_name))
-
- return indexes_removed
-
-
-#################
-# Migration tools
-#################
-
-# The default migration registry...
-#
-# Don't set this yourself! RegisterMigration will automatically fill
-# this with stuff via decorating methods in migrations.py
-
-class MissingCurrentMigration(Exception):
- pass
-
-
-MIGRATIONS = {}
-
-
-class RegisterMigration(object):
- """
- Tool for registering migrations
-
- Call like:
-
- @RegisterMigration(33)
- def update_dwarves(database):
- [...]
-
- This will register your migration with the default migration
- registry. Alternately, to specify a very specific
- migration_registry, you can pass in that as the second argument.
-
- Note, the number of your migration should NEVER be 0 or less than
- 0. 0 is the default "no migrations" state!
- """
- def __init__(self, migration_number, migration_registry=MIGRATIONS):
- assert migration_number > 0, "Migration number must be > 0!"
- assert migration_number not in migration_registry, \
- "Duplicate migration numbers detected! That's not allowed!"
-
- self.migration_number = migration_number
- self.migration_registry = migration_registry
-
- def __call__(self, migration):
- self.migration_registry[self.migration_number] = migration
- return migration
-
-
-class MigrationManager(object):
- """
- Migration handling tool.
-
- Takes information about a database, lets you update the database
- to the latest migrations, etc.
- """
- def __init__(self, database, migration_registry=MIGRATIONS):
- """
- Args:
- - database: database we're going to migrate
- - migration_registry: where we should find all migrations to
- run
- """
- self.database = database
- self.migration_registry = migration_registry
- self._sorted_migrations = None
-
- def _ensure_current_migration_record(self):
- """
- If there isn't a database[u'app_metadata'] mediagoblin entry
- with the 'current_migration', throw an error.
- """
- if self.database_current_migration() is None:
- raise MissingCurrentMigration(
- "Tried to call function which requires "
- "'current_migration' set in database")
-
- @property
- def sorted_migrations(self):
- """
- Sort migrations if necessary and store in self._sorted_migrations
- """
- if not self._sorted_migrations:
- self._sorted_migrations = sorted(
- self.migration_registry.items(),
- # sort on the key... the migration number
- key=lambda migration_tuple: migration_tuple[0])
-
- return self._sorted_migrations
-
- def latest_migration(self):
- """
- Return a migration number for the latest migration, or 0 if
- there are no migrations.
- """
- if self.sorted_migrations:
- return self.sorted_migrations[-1][0]
- else:
- # If no migrations have been set, we start at 0.
- return 0
-
- def set_current_migration(self, migration_number):
- """
- Set the migration in the database to migration_number
- """
- # Add the mediagoblin migration if necessary
- self.database[u'app_metadata'].update(
- {u'_id': u'mediagoblin'},
- {u'$set': {u'current_migration': migration_number}},
- upsert=True)
-
- def install_migration_version_if_missing(self):
- """
- Sets the migration to the latest version if no migration
- version at all is set.
- """
- mgoblin_metadata = self.database[u'app_metadata'].find_one(
- {u'_id': u'mediagoblin'})
- if not mgoblin_metadata:
- latest_migration = self.latest_migration()
- self.set_current_migration(latest_migration)
-
- def database_current_migration(self):
- """
- Return the current migration in the database.
- """
- mgoblin_metadata = self.database[u'app_metadata'].find_one(
- {u'_id': u'mediagoblin'})
- if not mgoblin_metadata:
- return None
- else:
- return mgoblin_metadata[u'current_migration']
-
- def database_at_latest_migration(self):
- """
- See if the database is at the latest migration.
- Returns a boolean.
- """
- current_migration = self.database_current_migration()
- return current_migration == self.latest_migration()
-
- def migrations_to_run(self):
- """
- Get a list of migrations to run still, if any.
-
- Note that calling this will set your migration version to the
- latest version if it isn't installed to anything yet!
- """
- self._ensure_current_migration_record()
-
- db_current_migration = self.database_current_migration()
-
- return [
- (migration_number, migration_func)
- for migration_number, migration_func in self.sorted_migrations
- if migration_number > db_current_migration]
-
- def migrate_new(self, pre_callback=None, post_callback=None):
- """
- Run all migrations.
-
- Includes two optional args:
- - pre_callback: if called, this is a callback on something to
- run pre-migration. Takes (migration_number, migration_func)
- as arguments
- - pre_callback: if called, this is a callback on something to
- run post-migration. Takes (migration_number, migration_func)
- as arguments
- """
- # If we aren't set to any version number, presume we're at the
- # latest (which means we'll do nothing here...)
- self.install_migration_version_if_missing()
-
- for migration_number, migration_func in self.migrations_to_run():
- if pre_callback:
- pre_callback(migration_number, migration_func)
- migration_func(self.database)
- self.set_current_migration(migration_number)
- if post_callback:
- post_callback(migration_number, migration_func)
-
-
-##########################
-# Random utility functions
-##########################
-
-
-def atomic_update(table, query_dict, update_values):
- table.collection.update(
- query_dict,
- {"$set": update_values})
-
-
-def check_media_slug_used(db, uploader_id, slug, ignore_m_id):
- query_dict = {'uploader': uploader_id, 'slug': slug}
- if ignore_m_id is not None:
- query_dict['_id'] = {'$ne': ignore_m_id}
- existing_user_slug_entries = db.MediaEntry.find(
- query_dict).count()
- return existing_user_slug_entries
-
-
-def media_entries_for_tag_slug(db, tag_slug):
- return db.MediaEntry.find(
- {u'state': u'processed',
- u'tags.slug': tag_slug})
diff --git a/mediagoblin/db/open.py b/mediagoblin/db/open.py
index f4c38511..d976acd8 100644
--- a/mediagoblin/db/open.py
+++ b/mediagoblin/db/open.py
@@ -14,16 +14,65 @@
# 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/>.
-try:
- from mediagoblin.db.sql_switch import use_sql
-except ImportError:
- use_sql = False
-
-if use_sql:
- from mediagoblin.db.sql.open import \
- setup_connection_and_db_from_config, check_db_migrations_current, \
- load_models
-else:
- from mediagoblin.db.mongo.open import \
- setup_connection_and_db_from_config, check_db_migrations_current, \
- load_models
+
+from sqlalchemy import create_engine
+import logging
+
+from mediagoblin.db.base import Base, Session
+from mediagoblin import mg_globals
+
+_log = logging.getLogger(__name__)
+
+
+class DatabaseMaster(object):
+ def __init__(self, engine):
+ self.engine = engine
+
+ for k, v in Base._decl_class_registry.iteritems():
+ setattr(self, k, v)
+
+ def commit(self):
+ Session.commit()
+
+ def save(self, obj):
+ Session.add(obj)
+ Session.flush()
+
+ def check_session_clean(self):
+ for dummy in Session():
+ _log.warn("STRANGE: There are elements in the sql session. "
+ "Please report this and help us track this down.")
+ break
+
+ def reset_after_request(self):
+ Session.rollback()
+ Session.remove()
+
+
+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:
+ __import__(plugin + ".models")
+ except ImportError as exc:
+ _log.debug("Could not load {0}.models: {1}".format(
+ plugin,
+ exc))
+
+
+def setup_connection_and_db_from_config(app_config):
+ engine = create_engine(app_config['sql_engine'])
+ # logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)
+ Session.configure(bind=engine)
+
+ return DatabaseMaster(engine)
+
+
+def check_db_migrations_current(db):
+ pass
diff --git a/mediagoblin/db/sql/convert.py b/mediagoblin/db/sql/convert.py
deleted file mode 100644
index ac64cf8d..00000000
--- a/mediagoblin/db/sql/convert.py
+++ /dev/null
@@ -1,282 +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/>.
-
-from copy import copy
-from itertools import chain, imap
-
-from mediagoblin.init import setup_global_and_app_config
-
-from mediagoblin.db.sql.base import Session
-from mediagoblin.db.sql.models_v0 import Base_v0
-from mediagoblin.db.sql.models_v0 import (User, MediaEntry, MediaComment,
- Tag, MediaTag, MediaFile, MediaAttachmentFile, MigrationData,
- ImageData, VideoData, AsciiData, AudioData)
-from mediagoblin.db.sql.open import setup_connection_and_db_from_config as \
- sql_connect
-from mediagoblin.db.mongo.open import setup_connection_and_db_from_config as \
- mongo_connect
-
-
-obj_id_table = dict()
-
-
-def add_obj_ids(entry, new_entry):
- global obj_id_table
- print "\t%r -> SQL id %r" % (entry._id, new_entry.id)
- obj_id_table[entry._id] = new_entry.id
-
-
-def copy_attrs(entry, new_entry, attr_list):
- for a in attr_list:
- val = entry[a]
- setattr(new_entry, a, val)
-
-
-def copy_reference_attr(entry, new_entry, ref_attr):
- val = entry[ref_attr]
- val = obj_id_table[val]
- setattr(new_entry, ref_attr, val)
-
-
-def convert_users(mk_db):
- session = Session()
-
- for entry in mk_db.User.find().sort('created'):
- print entry.username
-
- new_entry = User()
- copy_attrs(entry, new_entry,
- ('username', 'email', 'created', 'pw_hash', 'email_verified',
- 'status', 'verification_key', 'is_admin', 'url',
- 'bio',
- 'fp_verification_key', 'fp_token_expire',))
- # new_entry.fp_verification_expire = entry.fp_token_expire
-
- session.add(new_entry)
- session.flush()
- add_obj_ids(entry, new_entry)
-
- session.commit()
- session.close()
-
-
-def convert_media_entries(mk_db):
- session = Session()
-
- for entry in mk_db.MediaEntry.find().sort('created'):
- print repr(entry.title)
-
- new_entry = MediaEntry()
- copy_attrs(entry, new_entry,
- ('title', 'slug', 'created',
- 'description',
- 'media_type', 'state', 'license',
- 'fail_error', 'fail_metadata',
- 'queued_task_id',))
- copy_reference_attr(entry, new_entry, "uploader")
-
- session.add(new_entry)
- session.flush()
- add_obj_ids(entry, new_entry)
-
- for key, value in entry.media_files.iteritems():
- new_file = MediaFile(name=key, file_path=value)
- new_file.media_entry = new_entry.id
- Session.add(new_file)
-
- for attachment in entry.attachment_files:
- new_attach = MediaAttachmentFile(
- name=attachment["name"],
- filepath=attachment["filepath"],
- created=attachment["created"]
- )
- new_attach.media_entry = new_entry.id
- Session.add(new_attach)
-
- session.commit()
- session.close()
-
-
-def convert_image(mk_db):
- session = Session()
-
- for media in mk_db.MediaEntry.find(
- {'media_type': 'mediagoblin.media_types.image'}).sort('created'):
- media_data = copy(media.media_data)
-
- if len(media_data):
- media_data_row = ImageData(**media_data)
- media_data_row.media_entry = obj_id_table[media['_id']]
- session.add(media_data_row)
-
- session.commit()
- session.close()
-
-
-def convert_video(mk_db):
- session = Session()
-
- for media in mk_db.MediaEntry.find(
- {'media_type': 'mediagoblin.media_types.video'}).sort('created'):
- media_data_row = VideoData(**media.media_data)
- media_data_row.media_entry = obj_id_table[media['_id']]
- session.add(media_data_row)
-
- session.commit()
- session.close()
-
-
-def convert_media_tags(mk_db):
- session = Session()
- session.autoflush = False
-
- for media in mk_db.MediaEntry.find().sort('created'):
- print repr(media.title)
-
- for otag in media.tags:
- print " ", repr((otag["slug"], otag["name"]))
-
- nslug = session.query(Tag).filter_by(slug=otag["slug"]).first()
- print " ", repr(nslug)
- if nslug is None:
- nslug = Tag(slug=otag["slug"])
- session.add(nslug)
- session.flush()
- print " ", repr(nslug), nslug.id
-
- ntag = MediaTag()
- ntag.tag = nslug.id
- ntag.name = otag["name"]
- ntag.media_entry = obj_id_table[media._id]
- session.add(ntag)
-
- session.commit()
- session.close()
-
-
-def convert_media_comments(mk_db):
- session = Session()
-
- for entry in mk_db.MediaComment.find().sort('created'):
- print repr(entry.content)
-
- new_entry = MediaComment()
- copy_attrs(entry, new_entry,
- ('created',
- 'content',))
-
- try:
- copy_reference_attr(entry, new_entry, "media_entry")
- copy_reference_attr(entry, new_entry, "author")
- except KeyError as e:
- print('KeyError in convert_media_comments(): {0}'.format(e))
- else:
- session.add(new_entry)
- session.flush()
- add_obj_ids(entry, new_entry)
-
- session.commit()
- session.close()
-
-
-media_types_tables = (
- ("mediagoblin.media_types.image", (ImageData,)),
- ("mediagoblin.media_types.video", (VideoData,)),
- ("mediagoblin.media_types.ascii", (AsciiData,)),
- ("mediagoblin.media_types.audio", (AudioData,)),
- )
-
-
-def convert_add_migration_versions(dummy_sql_db):
- session = Session()
-
- for name in chain(("__main__",),
- imap(lambda e: e[0], media_types_tables)):
- print "\tAdding %s" % (name,)
- m = MigrationData(name=unicode(name), version=0)
- session.add(m)
-
- session.commit()
- session.close()
-
-
-def cleanup_sql_tables(sql_db):
- for mt, table_list in media_types_tables:
- session = Session()
-
- count = session.query(MediaEntry.media_type). \
- filter_by(media_type=unicode(mt)).count()
- print " %s: %d entries" % (mt, count)
-
- if count == 0:
- print "\tAnalyzing tables"
- for tab in table_list:
- cnt2 = session.query(tab).count()
- print "\t %s: %d entries" % (tab.__tablename__, cnt2)
- assert cnt2 == 0
-
- print "\tRemoving migration info"
- mi = session.query(MigrationData).filter_by(name=unicode(mt)).one()
- session.delete(mi)
- session.commit()
- session.close()
-
- print "\tDropping tables"
- tables = [model.__table__ for model in table_list]
- Base_v0.metadata.drop_all(sql_db.engine, tables=tables)
-
- session.close()
-
-
-def print_header(title):
- print "\n=== %s ===" % (title,)
-
-
-convert_call_list = (
- ("Converting Users", convert_users),
- ("Converting Media Entries", convert_media_entries),
- ("Converting Media Data for Images", convert_image),
- ("Cnnverting Media Data for Videos", convert_video),
- ("Converting Tags for Media", convert_media_tags),
- ("Converting Media Comments", convert_media_comments),
- )
-
-sql_call_list = (
- ("Filling Migration Tables", convert_add_migration_versions),
- ("Analyzing/Cleaning SQL Data", cleanup_sql_tables),
- )
-
-def run_conversion(config_name):
- global_config, app_config = setup_global_and_app_config(config_name)
-
- sql_conn, sql_db = sql_connect(app_config)
- mk_conn, mk_db = mongo_connect(app_config)
-
- Base_v0.metadata.create_all(sql_db.engine)
-
- for title, func in convert_call_list:
- print_header(title)
- func(mk_db)
- Session.remove()
-
- for title, func in sql_call_list:
- print_header(title)
- func(sql_db)
- Session.remove()
-
-
-if __name__ == '__main__':
- run_conversion("mediagoblin.ini")
diff --git a/mediagoblin/db/sql/open.py b/mediagoblin/db/sql/open.py
deleted file mode 100644
index 9db21c56..00000000
--- a/mediagoblin/db/sql/open.py
+++ /dev/null
@@ -1,78 +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/>.
-
-
-from sqlalchemy import create_engine
-import logging
-
-from mediagoblin.db.sql.base import Base, Session
-from mediagoblin import mg_globals
-
-_log = logging.getLogger(__name__)
-
-
-class DatabaseMaster(object):
- def __init__(self, engine):
- self.engine = engine
-
- for k, v in Base._decl_class_registry.iteritems():
- setattr(self, k, v)
-
- def commit(self):
- Session.commit()
-
- def save(self, obj):
- Session.add(obj)
- Session.flush()
-
- def check_session_clean(self):
- for dummy in Session():
- _log.warn("STRANGE: There are elements in the sql session. "
- "Please report this and help us track this down.")
- break
-
- def reset_after_request(self):
- Session.rollback()
- Session.remove()
-
-
-def load_models(app_config):
- import mediagoblin.db.sql.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:
- __import__(plugin + ".models")
- except ImportError as exc:
- _log.debug("Could not load {0}.models: {1}".format(
- plugin,
- exc))
-
-
-def setup_connection_and_db_from_config(app_config):
- engine = create_engine(app_config['sql_engine'])
- # logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)
- Session.configure(bind=engine)
-
- return "dummy conn", DatabaseMaster(engine)
-
-
-def check_db_migrations_current(db):
- pass
diff --git a/mediagoblin/db/sql_switch.py b/mediagoblin/db/sql_switch.py
deleted file mode 100644
index 571adbdb..00000000
--- a/mediagoblin/db/sql_switch.py
+++ /dev/null
@@ -1 +0,0 @@
-use_sql = True
diff --git a/mediagoblin/db/util.py b/mediagoblin/db/util.py
index a8c8c92b..529ef8b9 100644
--- a/mediagoblin/db/util.py
+++ b/mediagoblin/db/util.py
@@ -14,16 +14,63 @@
# 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/>.
-try:
- from mediagoblin.db.sql_switch import use_sql
-except ImportError:
- use_sql = False
-
-if use_sql:
- from mediagoblin.db.sql.fake import ObjectId, InvalidId, DESCENDING
- from mediagoblin.db.sql.util import atomic_update, check_media_slug_used, \
- media_entries_for_tag_slug, check_collection_slug_used
-else:
- from mediagoblin.db.mongo.util import \
- ObjectId, InvalidId, DESCENDING, atomic_update, \
- check_media_slug_used, media_entries_for_tag_slug
+from mediagoblin.db.base import Session
+from mediagoblin.db.models import MediaEntry, Tag, MediaTag, Collection
+
+
+##########################
+# Random utility functions
+##########################
+
+
+def atomic_update(table, query_dict, update_values):
+ table.find(query_dict).update(update_values,
+ synchronize_session=False)
+ Session.commit()
+
+
+def check_media_slug_used(uploader_id, slug, ignore_m_id):
+ query = MediaEntry.query.filter_by(uploader=uploader_id, slug=slug)
+ if ignore_m_id is not None:
+ query = query.filter(MediaEntry.id != ignore_m_id)
+ does_exist = query.first() is not None
+ return does_exist
+
+
+def media_entries_for_tag_slug(dummy_db, tag_slug):
+ return MediaEntry.query \
+ .join(MediaEntry.tags_helper) \
+ .join(MediaTag.tag_helper) \
+ .filter(
+ (MediaEntry.state == u'processed')
+ & (Tag.slug == tag_slug))
+
+
+def clean_orphan_tags(commit=True):
+ """Search for unused MediaTags and delete them"""
+ q1 = Session.query(Tag).outerjoin(MediaTag).filter(MediaTag.id==None)
+ for t in q1:
+ Session.delete(t)
+ # The "let the db do all the work" version:
+ # q1 = Session.query(Tag.id).outerjoin(MediaTag).filter(MediaTag.id==None)
+ # q2 = Session.query(Tag).filter(Tag.id.in_(q1))
+ # q2.delete(synchronize_session = False)
+ if commit:
+ Session.commit()
+
+
+def check_collection_slug_used(dummy_db, creator_id, slug, ignore_c_id):
+ filt = (Collection.creator == creator_id) \
+ & (Collection.slug == slug)
+ if ignore_c_id is not None:
+ filt = filt & (Collection.id != ignore_c_id)
+ does_exist = Session.query(Collection.id).filter(filt).first() is not None
+ return does_exist
+
+
+if __name__ == '__main__':
+ from mediagoblin.db.open import setup_connection_and_db_from_config
+
+ db = setup_connection_and_db_from_config({'sql_engine':'sqlite:///mediagoblin.db'})
+
+ clean_orphan_tags()
diff --git a/mediagoblin/decorators.py b/mediagoblin/decorators.py
index 9be9d4cc..804fab7e 100644
--- a/mediagoblin/decorators.py
+++ b/mediagoblin/decorators.py
@@ -17,11 +17,11 @@
from functools import wraps
from urlparse import urljoin
-from urllib import urlencode
+from werkzeug.exceptions import Forbidden, NotFound
+from werkzeug.urls import url_quote
-from webob import exc
-
-from mediagoblin.db.util import ObjectId, InvalidId
+from mediagoblin import mg_globals as mgg
+from mediagoblin.db.models import MediaEntry, User
from mediagoblin.tools.response import redirect, render_404
@@ -42,16 +42,27 @@ def require_active_login(controller):
qualified=True),
request.url)
- return exc.HTTPFound(
- location='?'.join([
- request.urlgen('mediagoblin.auth.login'),
- urlencode({
- 'next': next_url})]))
+ return redirect(request, 'mediagoblin.auth.login',
+ next=url_quote(next_url))
return controller(request, *args, **kwargs)
return new_controller_func
+def active_user_from_url(controller):
+ """Retrieve User() from <user> URL pattern and pass in as url_user=...
+
+ Returns a 404 if no such active user has been found"""
+ @wraps(controller)
+ def wrapper(request, *args, **kwargs):
+ user = User.query.filter_by(username=request.matchdict['user']).first()
+ if user is None:
+ return render_404(request)
+
+ return controller(request, *args, url_user=user, **kwargs)
+
+ return wrapper
+
def user_may_delete_media(controller):
"""
@@ -59,11 +70,10 @@ def user_may_delete_media(controller):
"""
@wraps(controller)
def wrapper(request, *args, **kwargs):
- uploader_id = request.db.MediaEntry.find_one(
- {'_id': ObjectId(request.matchdict['media'])}).uploader
+ uploader_id = kwargs['media'].uploader
if not (request.user.is_admin or
- request.user._id == uploader_id):
- return exc.HTTPForbidden()
+ request.user.id == uploader_id):
+ raise Forbidden()
return controller(request, *args, **kwargs)
@@ -79,8 +89,8 @@ def user_may_alter_collection(controller):
creator_id = request.db.User.find_one(
{'username': request.matchdict['user']}).id
if not (request.user.is_admin or
- request.user._id == creator_id):
- return exc.HTTPForbidden()
+ request.user.id == creator_id):
+ raise Forbidden()
return controller(request, *args, **kwargs)
@@ -111,29 +121,29 @@ def get_user_media_entry(controller):
"""
@wraps(controller)
def wrapper(request, *args, **kwargs):
- user = request.db.User.find_one(
- {'username': request.matchdict['user']})
-
+ user = User.query.filter_by(username=request.matchdict['user']).first()
if not user:
- return render_404(request)
- media = request.db.MediaEntry.find_one(
- {'slug': request.matchdict['media'],
- 'state': u'processed',
- 'uploader': user._id})
+ raise NotFound()
+
+ media = MediaEntry.query.filter_by(
+ slug = request.matchdict['media'],
+ state = u'processed',
+ uploader = user.id).first()
- # no media via slug? Grab it via ObjectId
if not media:
+ # no media via slug? Grab it via object id
try:
- media = request.db.MediaEntry.find_one(
- {'_id': ObjectId(request.matchdict['media']),
- 'state': u'processed',
- 'uploader': user._id})
- except InvalidId:
- return render_404(request)
+ media = MediaEntry.query.filter_by(
+ id = int(request.matchdict['media']),
+ state = u'processed',
+ uploader = user.id).first()
+ except ValueError:
+ # media "id" was no int
+ raise NotFound()
- # Still no media? Okay, 404.
- if not media:
- return render_404(request)
+ if not media:
+ # no media by that id? Okay, 404.
+ raise NotFound()
return controller(request, media=media, *args, **kwargs)
@@ -154,7 +164,7 @@ def get_user_collection(controller):
collection = request.db.Collection.find_one(
{'slug': request.matchdict['collection'],
- 'creator': user._id})
+ 'creator': user.id})
# Still no collection? Okay, 404.
if not collection:
@@ -179,10 +189,10 @@ def get_user_collection_item(controller):
collection = request.db.Collection.find_one(
{'slug': request.matchdict['collection'],
- 'creator': user._id})
+ 'creator': user.id})
collection_item = request.db.CollectionItem.find_one(
- {'_id': request.matchdict['collection_item'] })
+ {'id': request.matchdict['collection_item'] })
# Still no collection item? Okay, 404.
if not collection_item:
@@ -199,17 +209,28 @@ def get_media_entry_by_id(controller):
"""
@wraps(controller)
def wrapper(request, *args, **kwargs):
- try:
- media = request.db.MediaEntry.find_one(
- {'_id': ObjectId(request.matchdict['media']),
- 'state': u'processed'})
- except InvalidId:
- return render_404(request)
-
+ media = MediaEntry.query.filter_by(
+ id=request.matchdict['media_id'],
+ state=u'processed').first()
# Still no media? Okay, 404.
if not media:
return render_404(request)
+ given_username = request.matchdict.get('user')
+ if given_username and (given_username != media.get_uploader.username):
+ return render_404(request)
+
return controller(request, media=media, *args, **kwargs)
return wrapper
+
+
+def get_workbench(func):
+ """Decorator, passing in a workbench as kwarg which is cleaned up afterwards"""
+
+ @wraps(func)
+ def new_func(*args, **kwargs):
+ with mgg.workbench_manager.create() as workbench:
+ return func(*args, workbench=workbench, **kwargs)
+
+ return new_func
diff --git a/mediagoblin/edit/lib.py b/mediagoblin/edit/lib.py
index b4715134..aab537a0 100644
--- a/mediagoblin/edit/lib.py
+++ b/mediagoblin/edit/lib.py
@@ -17,7 +17,7 @@
def may_edit_media(request, media):
"""Check, if the request's user may edit the media details"""
- if media.uploader == request.user._id:
+ if media.uploader == request.user.id:
return True
if request.user.is_admin:
return True
diff --git a/mediagoblin/edit/routing.py b/mediagoblin/edit/routing.py
index 28b73d1e..035a766f 100644
--- a/mediagoblin/edit/routing.py
+++ b/mediagoblin/edit/routing.py
@@ -14,9 +14,13 @@
# 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.routing import add_route
+from mediagoblin.tools.routing import add_route
-add_route('mediagoblin.edit.profile', '/edit/profile/',
+add_route('mediagoblin.edit.profile', '/u/<string:user>/edit/',
'mediagoblin.edit.views:edit_profile')
+add_route('mediagoblin.edit.legacy_edit_profile', '/edit/profile/',
+ 'mediagoblin.edit.views:legacy_edit_profile')
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')
diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py
index 2d42ff0b..c656c63f 100644
--- a/mediagoblin/edit/views.py
+++ b/mediagoblin/edit/views.py
@@ -14,10 +14,10 @@
# 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 webob import exc
from cgi import FieldStorage
from datetime import datetime
+from werkzeug.exceptions import Forbidden
from werkzeug.utils import secure_filename
from mediagoblin import messages
@@ -26,8 +26,9 @@ from mediagoblin import mg_globals
from mediagoblin.auth import lib as auth_lib
from mediagoblin.edit import forms
from mediagoblin.edit.lib import may_edit_media
-from mediagoblin.decorators import require_active_login, get_user_media_entry, \
- user_may_alter_collection, get_user_collection
+from mediagoblin.decorators import (require_active_login, active_user_from_url,
+ get_media_entry_by_id,
+ get_user_media_entry, user_may_alter_collection, get_user_collection)
from mediagoblin.tools.response import render_to_response, redirect
from mediagoblin.tools.translate import pass_to_ugettext as _
from mediagoblin.tools.text import (
@@ -37,11 +38,11 @@ from mediagoblin.db.util import check_media_slug_used, check_collection_slug_use
import mimetypes
-@get_user_media_entry
+@get_media_entry_by_id
@require_active_login
def edit_media(request, media):
if not may_edit_media(request, media):
- return exc.HTTPForbidden()
+ raise Forbidden("User may not edit this media")
defaults = dict(
title=media.title,
@@ -57,8 +58,8 @@ def edit_media(request, media):
if request.method == 'POST' and form.validate():
# Make sure there isn't already a MediaEntry with such a slug
# and userid.
- slug_used = check_media_slug_used(request.db, media.uploader,
- request.form['slug'], media.id)
+ slug_used = check_media_slug_used(media.uploader, request.form['slug'],
+ media.id)
if slug_used:
form.slug.errors.append(
@@ -75,11 +76,11 @@ def edit_media(request, media):
media.save()
- return exc.HTTPFound(
- location=media.url_for_self(request.urlgen))
+ return redirect(request,
+ location=media.url_for_self(request.urlgen))
if request.user.is_admin \
- and media.uploader != request.user._id \
+ and media.uploader != request.user.id \
and request.method != 'POST':
messages.add_message(
request, messages.WARNING,
@@ -130,7 +131,7 @@ def edit_attachments(request, media):
attachment_public_filepath \
= mg_globals.public_store.get_unique_filepath(
- ['media_entries', unicode(media._id), 'attachment',
+ ['media_entries', unicode(media.id), 'attachment',
public_filename])
attachment_public_file = mg_globals.public_store.get_file(
@@ -153,34 +154,42 @@ def edit_attachments(request, media):
messages.add_message(
request, messages.SUCCESS,
- "You added the attachment %s!" \
+ _("You added the attachment %s!") \
% (request.form['attachment_name']
or request.files['attachment_file'].filename))
- return exc.HTTPFound(
- location=media.url_for_self(request.urlgen))
+ return redirect(request,
+ location=media.url_for_self(request.urlgen))
return render_to_response(
request,
'mediagoblin/edit/attachments.html',
{'media': media,
'form': form})
else:
- return exc.HTTPForbidden()
+ raise Forbidden("Attachments are disabled")
+
+@require_active_login
+def legacy_edit_profile(request):
+ """redirect the old /edit/profile/?username=USER to /u/USER/edit/"""
+ username = request.GET.get('username') or request.user.username
+ return redirect(request, 'mediagoblin.edit.profile', user=username)
@require_active_login
-def edit_profile(request):
- # admins may edit any user profile given a username in the querystring
- edit_username = request.GET.get('username')
- if request.user.is_admin and request.user.username != edit_username:
- user = request.db.User.find_one({'username': edit_username})
+@active_user_from_url
+def edit_profile(request, url_user=None):
+ # admins may edit any user profile
+ if request.user.username != url_user.username:
+ if not request.user.is_admin:
+ raise Forbidden(_("You can only edit your own profile."))
+
# No need to warn again if admin just submitted an edited profile
if request.method != 'POST':
messages.add_message(
request, messages.WARNING,
_("You are editing a user's profile. Proceed with caution."))
- else:
- user = request.user
+
+ user = url_user
form = forms.EditProfileForm(request.form,
url=user.get('url'),
@@ -258,6 +267,37 @@ def edit_account(request):
@require_active_login
+def delete_account(request):
+ """Delete a user completely"""
+ user = request.user
+ if request.method == 'POST':
+ if request.form.get(u'confirmed'):
+ # Form submitted and confirmed. Actually delete the user account
+ # Log out user and delete cookies etc.
+ # TODO: Should we be using MG.auth.views.py:logout for this?
+ request.session.delete()
+
+ # Delete user account and all related media files etc....
+ request.user.delete()
+
+ # We should send a message that the user has been deleted
+ # successfully. But we just deleted the session, so we
+ # can't...
+ return redirect(request, 'index')
+
+ else: # Did not check the confirmation box...
+ messages.add_message(
+ request, messages.WARNING,
+ _('You need to confirm the deletion of your account.'))
+
+ # No POST submission or not confirmed, just show page
+ return render_to_response(
+ request,
+ 'mediagoblin/edit/delete_account.html',
+ {'user': user})
+
+
+@require_active_login
@user_may_alter_collection
@get_user_collection
def edit_collection(request, collection):
@@ -278,7 +318,7 @@ def edit_collection(request, collection):
# Make sure there isn't already a Collection with this title
existing_collection = request.db.Collection.find_one({
- 'creator': request.user._id,
+ 'creator': request.user.id,
'title':request.form['title']})
if existing_collection and existing_collection.id != collection.id:
@@ -301,7 +341,7 @@ def edit_collection(request, collection):
collection=collection.slug)
if request.user.is_admin \
- and collection.creator != request.user._id \
+ and collection.creator != request.user.id \
and request.method != 'POST':
messages.add_message(
request, messages.WARNING,
diff --git a/mediagoblin/gmg_commands/__init__.py b/mediagoblin/gmg_commands/__init__.py
index e965dd57..6aed4f6c 100644
--- a/mediagoblin/gmg_commands/__init__.py
+++ b/mediagoblin/gmg_commands/__init__.py
@@ -25,11 +25,6 @@ SUBCOMMAND_MAP = {
'setup': 'mediagoblin.gmg_commands.shell:shell_parser_setup',
'func': 'mediagoblin.gmg_commands.shell:shell',
'help': 'Run a shell with some tools pre-setup'},
- 'migrate': {
- 'setup': 'mediagoblin.gmg_commands.migrate:migrate_parser_setup',
- 'func': 'mediagoblin.gmg_commands.migrate:migrate',
- 'help': ('Migrate your Mongo database. '
- '[DEPRECATED!] use convert_mongo_to_sql and dbupdate.')},
'adduser': {
'setup': 'mediagoblin.gmg_commands.users:adduser_parser_setup',
'func': 'mediagoblin.gmg_commands.users:adduser',
@@ -37,19 +32,15 @@ SUBCOMMAND_MAP = {
'makeadmin': {
'setup': 'mediagoblin.gmg_commands.users:makeadmin_parser_setup',
'func': 'mediagoblin.gmg_commands.users:makeadmin',
- 'help': 'Changes a user\'s password'},
+ 'help': 'Makes user an admin'},
'changepw': {
'setup': 'mediagoblin.gmg_commands.users:changepw_parser_setup',
'func': 'mediagoblin.gmg_commands.users:changepw',
- 'help': 'Makes admin an user'},
+ 'help': 'Changes a user\'s password'},
'dbupdate': {
'setup': 'mediagoblin.gmg_commands.dbupdate:dbupdate_parse_setup',
'func': 'mediagoblin.gmg_commands.dbupdate:dbupdate',
'help': 'Set up or update the SQL database'},
- 'convert_mongo_to_sql': {
- 'setup': 'mediagoblin.gmg_commands.mongosql:mongosql_parser_setup',
- 'func': 'mediagoblin.gmg_commands.mongosql:mongosql',
- 'help': 'Convert Mongo DB data to SQL DB data'},
'theme': {
'setup': 'mediagoblin.gmg_commands.theme:theme_parser_setup',
'func': 'mediagoblin.gmg_commands.theme:theme',
diff --git a/mediagoblin/gmg_commands/dbupdate.py b/mediagoblin/gmg_commands/dbupdate.py
index 67fdd69c..65b3f922 100644
--- a/mediagoblin/gmg_commands/dbupdate.py
+++ b/mediagoblin/gmg_commands/dbupdate.py
@@ -18,8 +18,8 @@ import logging
from sqlalchemy.orm import sessionmaker
-from mediagoblin.db.sql.open import setup_connection_and_db_from_config
-from mediagoblin.db.sql.util import MigrationManager
+from mediagoblin.db.open import setup_connection_and_db_from_config
+from mediagoblin.db.migration_tools import MigrationManager
from mediagoblin.init import setup_global_and_app_config
from mediagoblin.tools.common import import_component
@@ -52,8 +52,8 @@ def gather_database_data(media_types, plugins):
managed_dbdata = []
# Add main first
- from mediagoblin.db.sql.models import MODELS as MAIN_MODELS
- from mediagoblin.db.sql.migrations import MIGRATIONS as MAIN_MIGRATIONS
+ from mediagoblin.db.models import MODELS as MAIN_MODELS
+ from mediagoblin.db.migrations import MIGRATIONS as MAIN_MIGRATIONS
managed_dbdata.append(
DatabaseData(
@@ -114,7 +114,7 @@ def run_dbupdate(app_config, global_config):
global_config.get('plugins', {}).keys())
# Set up the database
- connection, db = setup_connection_and_db_from_config(app_config)
+ db = setup_connection_and_db_from_config(app_config)
Session = sessionmaker(bind=db.engine)
diff --git a/mediagoblin/gmg_commands/import_export.py b/mediagoblin/gmg_commands/import_export.py
index 72ebd8a8..d51a1e3e 100644
--- a/mediagoblin/gmg_commands/import_export.py
+++ b/mediagoblin/gmg_commands/import_export.py
@@ -105,7 +105,7 @@ def env_import(args):
setup_storage()
global_config, app_config = setup_global_and_app_config(args.conf_file)
- connection, db = setup_connection_and_db_from_config(
+ db = setup_connection_and_db_from_config(
app_config)
tf = tarfile.open(
@@ -243,8 +243,7 @@ def env_export(args):
setup_storage()
- connection, db = setup_connection_and_db_from_config(
- app_config)
+ db = setup_connection_and_db_from_config(app_config)
_export_database(db, args)
diff --git a/mediagoblin/gmg_commands/migrate.py b/mediagoblin/gmg_commands/migrate.py
deleted file mode 100644
index b915a528..00000000
--- a/mediagoblin/gmg_commands/migrate.py
+++ /dev/null
@@ -1,75 +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 sys
-
-from mediagoblin.init import setup_global_and_app_config
-
-
-def migrate_parser_setup(subparser):
- pass
-
-
-def _print_started_migration(migration_number, migration_func):
- sys.stdout.write(
- "Running migration %s, '%s'... " % (
- migration_number, migration_func.func_name))
- sys.stdout.flush()
-
-
-def _print_finished_migration(migration_number, migration_func):
- sys.stdout.write("done.\n")
- sys.stdout.flush()
-
-
-def migrate(args):
- run_migrate(args.conf_file)
-
-
-def run_migrate(conf_file):
- # This MUST be imported so as to set up the appropriate migrations!
- from mediagoblin.db.mongo import migrations
-
- from mediagoblin.db.mongo import util as db_util
- from mediagoblin.db.mongo.open import setup_connection_and_db_from_config
-
- global_config, app_config = setup_global_and_app_config(conf_file)
-
- connection, db = setup_connection_and_db_from_config(
- app_config, use_pymongo=True)
- migration_manager = db_util.MigrationManager(db)
-
- # Clear old indexes
- print "== Clearing old indexes... =="
- removed_indexes = db_util.remove_deprecated_indexes(db)
-
- for collection, index_name in removed_indexes:
- print "Removed index '%s' in collection '%s'" % (
- index_name, collection)
-
- # Migrate
- print "\n== Applying migrations... =="
- migration_manager.migrate_new(
- pre_callback=_print_started_migration,
- post_callback=_print_finished_migration)
-
- # Add new indexes
- print "\n== Adding new indexes... =="
- new_indexes = db_util.add_new_indexes(db)
-
- for collection, index_name in new_indexes:
- print "Added index '%s' to collection '%s'" % (
- index_name, collection)
diff --git a/mediagoblin/gmg_commands/shell.py b/mediagoblin/gmg_commands/shell.py
index ec1ab535..4998acd7 100644
--- a/mediagoblin/gmg_commands/shell.py
+++ b/mediagoblin/gmg_commands/shell.py
@@ -47,24 +47,21 @@ def py_shell(**user_namespace):
def ipython_shell(**user_namespace):
"""
- Run a shell for the user using ipython.
+ Run a shell for the user using ipython. Return False if there is no IPython
"""
try:
from IPython import embed
except:
- print "IPython not available... exiting!"
- return
-
+ return False
+
embed(
banner1=SHELL_BANNER,
user_ns=user_namespace)
-
+ return True
def shell(args):
"""
- Setup a shell for the user
- either a normal Python shell
- or an IPython one
+ Setup a shell for the user either a normal Python shell or an IPython one
"""
user_namespace = {
'mg_globals': mg_globals,
@@ -74,4 +71,6 @@ def shell(args):
if args.ipython:
ipython_shell(**user_namespace)
else:
- py_shell(**user_namespace)
+ # Try ipython_shell first and fall back if not available
+ if not ipython_shell(**user_namespace):
+ py_shell(**user_namespace)
diff --git a/mediagoblin/gmg_commands/users.py b/mediagoblin/gmg_commands/users.py
index 70e591c9..024c8498 100644
--- a/mediagoblin/gmg_commands/users.py
+++ b/mediagoblin/gmg_commands/users.py
@@ -55,7 +55,7 @@ def adduser(args):
entry.pw_hash = auth_lib.bcrypt_gen_password_hash(args.password)
entry.status = u'active'
entry.email_verified = True
- entry.save(validate=True)
+ entry.save()
print "User created (and email marked as verified)"
diff --git a/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.mo
index eaec0daa..d8d02ded 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 cf090994..6bdfacc6 100644
--- a/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.po
@@ -10,8 +10,8 @@ msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2012-09-24 14:01-0500\n"
-"PO-Revision-Date: 2012-09-24 18:57+0000\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 15:14+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
@@ -94,7 +94,7 @@ msgstr ""
msgid "You can now log in using your new password."
msgstr ""
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:83
+#: 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:40
msgid "Title"
@@ -105,7 +105,7 @@ msgid "Description of this work"
msgstr "وص٠هذا العمل."
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:87 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:44
msgid ""
"You can use\n"
@@ -121,11 +121,11 @@ msgstr "الوسوم"
msgid "Separate tags by commas."
msgstr ""
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:91
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "المسار"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:92
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "لا يمكن ترك المسار ÙØ§Ø±ØºÙ‹Ø§"
@@ -164,20 +164,20 @@ msgstr ""
msgid "New password"
msgstr ""
-#: mediagoblin/edit/forms.py:72
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr ""
-#: mediagoblin/edit/forms.py:84
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:43
msgid "Description of this collection"
msgstr ""
-#: mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
@@ -191,33 +191,38 @@ msgstr "يوجد مل٠آخر بهذا المسار لدى هذى المستخØ
msgid "You are editing another user's media. Proceed with caution."
msgstr "أنت تحرّر وسائط مستخدم آخر. كن حذرًا أثناء العملية."
-#: mediagoblin/edit/views.py:182
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr ""
+
+#: mediagoblin/edit/views.py:181
msgid "You are editing a user's profile. Proceed with caution."
msgstr "أنت تحرّر مل٠مستخدم آخر. كن حذرًا أثناء العملية."
-#: mediagoblin/edit/views.py:198
+#: mediagoblin/edit/views.py:197
msgid "Profile changes saved"
msgstr ""
-#: mediagoblin/edit/views.py:227 mediagoblin/edit/views.py:247
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
msgid "Account settings saved"
msgstr ""
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:251
msgid "Wrong password"
msgstr ""
-#: mediagoblin/edit/views.py:288 mediagoblin/submit/views.py:211
-#: mediagoblin/user_pages/views.py:215
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr ""
-#: mediagoblin/edit/views.py:292
+#: mediagoblin/edit/views.py:291
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:309
+#: mediagoblin/edit/views.py:308
msgid "You are editing another user's collection. Proceed with caution."
msgstr ""
@@ -234,7 +239,7 @@ msgid "However, old link directory symlink found; removed.\n"
msgstr ""
#: mediagoblin/media_types/__init__.py:60
-#: mediagoblin/media_types/__init__.py:120
+#: mediagoblin/media_types/__init__.py:101
msgid "Sorry, I don't support that file type :("
msgstr ""
@@ -304,7 +309,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:60
msgid "The client {0} has been registered!"
msgstr ""
@@ -329,62 +334,43 @@ msgstr "يا سلام! Ù†ÙØ´Ø±ÙŽØª!"
msgid "Collection \"%s\" added!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/404.html:24
-msgid "Image of 404 goblin stressing out"
-msgstr "صورة قزم مرتبك"
-
-#: mediagoblin/templates/mediagoblin/404.html:25
-msgid "Oops!"
-msgstr "ويحي!"
-
-#: mediagoblin/templates/mediagoblin/404.html:26
-msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr "يبدو أنه لا توجد ØµÙØ­Ø© ÙÙŠ العنوان. عذرًا!"
-
-#: mediagoblin/templates/mediagoblin/404.html:28
-msgid ""
-"If you're sure the address is correct, maybe the page you're looking for has"
-" been moved or deleted."
-msgstr "إن كنت متأكدًا من صحة العنوان ÙØ±Ø¨Ù…ا تكون Ø§Ù„ØµÙØ­Ø© التي تريدها Ù†Ùقلت أو Ø­ÙØ°Ùت."
-
-#: mediagoblin/templates/mediagoblin/base.html:50
+#: mediagoblin/templates/mediagoblin/base.html:48
msgid "MediaGoblin logo"
msgstr "شعار ميدياغوبلن"
-#: mediagoblin/templates/mediagoblin/base.html:60
-msgid "Verify your email!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:66
-msgid "+ Add media"
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:67
-msgid "+ Add collection"
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:69
-msgid "View your profile"
-msgstr ""
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
+msgstr "أض٠وسائط"
-#: mediagoblin/templates/mediagoblin/base.html:70
-msgid "Log out"
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:75
+#: 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:89
+#: mediagoblin/templates/mediagoblin/base.html:87
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project."
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:92
+#: mediagoblin/templates/mediagoblin/base.html:90
#, python-format
msgid ""
"Released under the <a "
@@ -392,31 +378,56 @@ msgid ""
"href=\"%(source_link)s\">Source code</a> available."
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:24
+#: mediagoblin/templates/mediagoblin/error.html:24
+msgid "Image of goblin stressing out"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:25
+msgid "Actions"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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/root.html:51
msgid "Explore"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:26
+#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Hi there, welcome to this MediaGoblin site!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/root.html:55
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:29
+#: mediagoblin/templates/mediagoblin/root.html:56
msgid ""
"To add your own media, place comments, and more, you can log in with your "
"MediaGoblin account."
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:31
+#: mediagoblin/templates/mediagoblin/root.html:58
msgid "Don't have one yet? It's easy!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:32
+#: mediagoblin/templates/mediagoblin/root.html:59
#, python-format
msgid ""
"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
@@ -424,17 +435,10 @@ msgid ""
" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:40
+#: mediagoblin/templates/mediagoblin/root.html:67
msgid "Most recent media"
msgstr "أحدث الوسائط"
-#: 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/admin/panel.html:29
msgid ""
"Here you can track the state of media being processed on this instance."
@@ -543,30 +547,43 @@ msgstr "أهلًا يا %(username)sØŒ\n\nØ§ÙØªØ­ الرابط التالي\nÙ
msgid "Editing attachments for %(media_title)s"
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/attachments.html:43
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
+msgid "Attachments"
+msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:53
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
msgid "Cancel"
msgstr "ألغÙ"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:43
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
msgid "Save changes"
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:41
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
#, python-format
msgid "Changing %(username)s's account settings"
msgstr ""
@@ -592,13 +609,12 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:23
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
msgid "Download"
msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:27
msgid "Original"
msgstr ""
@@ -625,6 +641,56 @@ msgstr ""
msgid "WebM file (Vorbis codec)"
msgstr ""
+#: 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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr ""
+
+#: 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 ""
+
+#: 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:40
msgid ""
"Sorry, this video will not work because \n"
@@ -649,7 +715,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
#: mediagoblin/templates/mediagoblin/submit/start.html:34
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:83
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
msgid "Add"
msgstr ""
@@ -678,14 +744,6 @@ msgstr ""
msgid "Delete"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection.html:59
-#, python-format
-msgid ""
-"<p>\n"
-" %(collection_description)s\n"
-" </p>"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
@@ -693,7 +751,7 @@ msgid "Really delete %(title)s?"
msgstr "أتود حقًا حذ٠%(title)s?"
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr ""
@@ -702,7 +760,7 @@ msgstr ""
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
msgid "Remove"
msgstr ""
@@ -728,12 +786,6 @@ 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:67
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
-#, python-format
-msgid "Image for %(media_title)s"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
msgid "Add a comment"
msgstr ""
@@ -760,13 +812,8 @@ msgid ""
" <p>%(date)s</p>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
-msgid "Attachments"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
-msgid "Add attachment"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
@@ -774,11 +821,11 @@ msgstr ""
msgid "Add %(title)s to collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
msgid "+"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
msgid "Add a new collection"
msgstr ""
@@ -849,41 +896,25 @@ msgstr "Ø­Ø±Ù‘ÙØ± المل٠الشخصي"
msgid "This user hasn't filled in their profile (yet)."
msgstr "لم يعبئ هذا العضو بيانات ملÙÙ‡ بعد."
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:125
-msgid "Change account settings"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:138
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
#, python-format
msgid "View all of %(username)s's media"
msgstr "Ø£Ø¸Ù‡ÙØ± كل وسائط %(username)s"
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
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:157
-msgid "Add media"
-msgstr "أض٠وسائط"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:163
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:87
-#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:72
+#: 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:39
-#, python-format
-msgid ""
-"<br />\n"
-" <a href=\"%(entry_url)s\">%(note)s</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:47
-#, python-format
-msgid "<br /><a href=\"%(remove_url)s\" class=\"remove\">(remove)</a>"
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
msgstr ""
#: mediagoblin/templates/mediagoblin/utils/collections.html:20
@@ -903,7 +934,7 @@ msgstr ""
msgid "Location"
msgstr ""
-#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:38
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
#, python-format
msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
msgstr ""
@@ -942,6 +973,32 @@ msgstr ""
msgid "Could not read the image file."
msgstr ""
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr "ويحي!"
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr ""
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr ""
+
+#: mediagoblin/tools/response.py:47
+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:55
+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/user_pages/forms.py:28
msgid "I am sure I want to delete this"
msgstr "أنا متأكد من رغبتي بحذ٠هذا العمل"
@@ -962,74 +1019,74 @@ msgstr ""
msgid "commented on your post"
msgstr ""
-#: mediagoblin/user_pages/views.py:161
+#: mediagoblin/user_pages/views.py:156
msgid "Oops, your comment was empty."
msgstr ""
-#: mediagoblin/user_pages/views.py:167
+#: mediagoblin/user_pages/views.py:162
msgid "Your comment has been posted!"
msgstr ""
-#: mediagoblin/user_pages/views.py:235
+#: mediagoblin/user_pages/views.py:230
msgid "You have to select or add a collection"
msgstr ""
-#: mediagoblin/user_pages/views.py:243
+#: mediagoblin/user_pages/views.py:238
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:258
+#: mediagoblin/user_pages/views.py:253
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:266
+#: mediagoblin/user_pages/views.py:261
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:297
+#: mediagoblin/user_pages/views.py:292
msgid ""
"Some of the files with this entry seem to be missing. Deleting anyway."
msgstr ""
-#: mediagoblin/user_pages/views.py:302
+#: mediagoblin/user_pages/views.py:297
msgid "You deleted the media."
msgstr ""
-#: mediagoblin/user_pages/views.py:309
+#: mediagoblin/user_pages/views.py:304
msgid "The media was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:317
+#: mediagoblin/user_pages/views.py:312
msgid "You are about to delete another user's media. Proceed with caution."
msgstr "أنت على وشك حذ٠وسائط مستخدم آخر. كن حذرًا أثناء العملية."
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr ""
-#: mediagoblin/user_pages/views.py:383
+#: 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:393
+#: mediagoblin/user_pages/views.py:384
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:426
+#: mediagoblin/user_pages/views.py:417
#, python-format
msgid "You deleted the collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:433
+#: mediagoblin/user_pages/views.py:424
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:443
+#: mediagoblin/user_pages/views.py:434
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr ""
diff --git a/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.mo
index 89fde97f..ae6216cf 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 ee4a0aca..79f26e8f 100644
--- a/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.po
@@ -5,12 +5,13 @@
# Translators:
# Al fred <devaleitzer@aim.com>, 2011.
# <devaleitzer@aim.com>, 2011.
+# <skarbat@gmail.com>, 2012.
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2012-09-24 14:01-0500\n"
-"PO-Revision-Date: 2012-09-24 18:57+0000\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 15:14+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
@@ -34,11 +35,11 @@ msgstr "Adreça electrònica"
#: mediagoblin/auth/forms.py:51
msgid "Username or email"
-msgstr ""
+msgstr "Nom d'usuari o correu"
#: mediagoblin/auth/forms.py:58
msgid "Incorrect input"
-msgstr ""
+msgstr "Entrada incorrecte"
#: mediagoblin/auth/views.py:55
msgid "Sorry, registration is disabled on this instance."
@@ -50,7 +51,7 @@ msgstr "Lamentablement aquest usuari ja existeix."
#: mediagoblin/auth/views.py:79
msgid "Sorry, a user with that email address already exists."
-msgstr ""
+msgstr "Perdó, ja existeix un usuari amb aquesta adreça de correu."
#: mediagoblin/auth/views.py:182
msgid ""
@@ -64,11 +65,11 @@ msgstr "La clau de verificació o la identificació de l'usuari no són correcte
#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
-msgstr ""
+msgstr "Has d'estar conectat per saber a qui hem d'enviar el correu!"
#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
-msgstr ""
+msgstr "Ja has verificat la teva adreça de correu!"
#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
@@ -77,23 +78,23 @@ msgstr "Torna'm a enviar el correu de verificació"
#: mediagoblin/auth/views.py:263
msgid ""
"An email has been sent with instructions on how to change your password."
-msgstr ""
+msgstr "S'ha enviat un correu amb instruccions de com cambiar la teva contrasenya"
#: mediagoblin/auth/views.py:273
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
-msgstr ""
+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:285
msgid "Couldn't find someone with that username or email."
-msgstr ""
+msgstr "No es troba ningu amb aquest nom d'usuari o correu electrònic."
#: mediagoblin/auth/views.py:333
msgid "You can now log in using your new password."
-msgstr ""
+msgstr "Ara et pots conectar amb la teva nova contrasenya."
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:83
+#: 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:40
msgid "Title"
@@ -101,16 +102,16 @@ msgstr "Títol"
#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31
msgid "Description of this work"
-msgstr ""
+msgstr "Descripció d'aquest treball."
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:87 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:44
msgid ""
"You can use\n"
" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n"
" Markdown</a> for formatting."
-msgstr ""
+msgstr "Pots utilitzar⎠<a href=\"http://daringfireball.net/projects/markdown/basics\">⎠Markdown</a> per donar-li format"
#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36
msgid "Tags"
@@ -118,26 +119,26 @@ msgstr "Etiquetes"
#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38
msgid "Separate tags by commas."
-msgstr ""
+msgstr "Separa els tags amb comes."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:91
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
-msgstr ""
+msgstr "Llimac"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:92
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
-msgstr ""
+msgstr "El llimac no pot ésser buit"
#: mediagoblin/edit/forms.py:40
msgid ""
"The title part of this media's address. You usually don't need to change "
"this."
-msgstr ""
+msgstr "El títol de l'adreça d'aquest mitjà. Normalment no necessites modificar això."
#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41
#: mediagoblin/templates/mediagoblin/utils/license.html:20
msgid "License"
-msgstr ""
+msgstr "Llicència"
#: mediagoblin/edit/forms.py:50
msgid "Bio"
@@ -149,80 +150,85 @@ msgstr "Lloc web"
#: mediagoblin/edit/forms.py:58
msgid "This address contains errors"
-msgstr ""
+msgstr "Aquesta adreça conté errors"
#: mediagoblin/edit/forms.py:63
msgid "Old password"
-msgstr ""
+msgstr "Contrasenya antiga"
#: mediagoblin/edit/forms.py:64
msgid "Enter your old password to prove you own this account."
-msgstr ""
+msgstr "Introdueix la teva contrasenya antiga per comprovar que aquest compte és teu."
#: mediagoblin/edit/forms.py:67
msgid "New password"
-msgstr ""
+msgstr "Nova contrasenya"
-#: mediagoblin/edit/forms.py:72
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
-msgstr ""
+msgstr "Envia'm correu quan d'altres comentin al meu mitjà"
-#: mediagoblin/edit/forms.py:84
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
-msgstr ""
+msgstr "El títol no pot ser buit"
-#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:43
msgid "Description of this collection"
-msgstr ""
+msgstr "Descripció d'aquesta col.lecció"
-#: mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
-msgstr ""
+msgstr "La part del títol de l'adreça d'aquesta col.lecció. Normalment no cal que canviis això."
#: mediagoblin/edit/views.py:65
msgid "An entry with that slug already exists for this user."
-msgstr ""
+msgstr "Ja existeix una entrada amb aquest llimac per aquest usuari"
#: mediagoblin/edit/views.py:86
msgid "You are editing another user's media. Proceed with caution."
msgstr "Esteu editant fitxers d'un altre usuari. Aneu amb compte."
-#: mediagoblin/edit/views.py:182
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr ""
+
+#: mediagoblin/edit/views.py:181
msgid "You are editing a user's profile. Proceed with caution."
msgstr "Esteu editant el perfil d'un usuari. Aneu amb compte"
-#: mediagoblin/edit/views.py:198
+#: mediagoblin/edit/views.py:197
msgid "Profile changes saved"
-msgstr ""
+msgstr "Els canvis al perfil s'han guardat"
-#: mediagoblin/edit/views.py:227 mediagoblin/edit/views.py:247
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
msgid "Account settings saved"
-msgstr ""
+msgstr "Els detalls del compte s'han guardat"
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:251
msgid "Wrong password"
-msgstr ""
+msgstr "Contrasenya errònia"
-#: mediagoblin/edit/views.py:288 mediagoblin/submit/views.py:211
-#: mediagoblin/user_pages/views.py:215
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
#, python-format
msgid "You already have a collection called \"%s\"!"
-msgstr ""
+msgstr "Ja tens una col.lecció anomenada \"%s\"!"
-#: mediagoblin/edit/views.py:292
+#: mediagoblin/edit/views.py:291
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:309
+#: mediagoblin/edit/views.py:308
msgid "You are editing another user's collection. Proceed with caution."
-msgstr ""
+msgstr "Estas editant la col.lecció d'un altre usuari. Prossegueix amb cautela."
#: mediagoblin/gmg_commands/theme.py:58
msgid "Cannot link theme... no theme set\n"
-msgstr ""
+msgstr "No es pot enllaçar el tema... no hi ha tema establert\n"
#: mediagoblin/gmg_commands/theme.py:71
msgid "No asset directory for this theme\n"
@@ -230,54 +236,54 @@ msgstr ""
#: mediagoblin/gmg_commands/theme.py:74
msgid "However, old link directory symlink found; removed.\n"
-msgstr ""
+msgstr "Tot i així, l'enllaç antic al directori s'ha trobat; eliminat.\n"
#: mediagoblin/media_types/__init__.py:60
-#: mediagoblin/media_types/__init__.py:120
+#: mediagoblin/media_types/__init__.py:101
msgid "Sorry, I don't support that file type :("
-msgstr ""
+msgstr "Ho sento, no puc manegar aquest tipus d'arxiu :("
#: mediagoblin/media_types/video/processing.py:35
msgid "Video transcoding failed"
-msgstr ""
+msgstr "La transformació del vídeo ha fallat"
#: mediagoblin/plugins/oauth/forms.py:26
msgid "Client ID"
-msgstr ""
+msgstr "ID del client"
#: mediagoblin/plugins/oauth/forms.py:28
msgid "Next URL"
-msgstr ""
+msgstr "Següent URL"
#: mediagoblin/plugins/oauth/forms.py:30
msgid "Allow"
-msgstr ""
+msgstr "Permetre"
#: mediagoblin/plugins/oauth/forms.py:31
msgid "Deny"
-msgstr ""
+msgstr "Denegar"
#: mediagoblin/plugins/oauth/forms.py:35
msgid "Name"
-msgstr ""
+msgstr "Nom"
#: mediagoblin/plugins/oauth/forms.py:36
msgid "The name of the OAuth client"
-msgstr ""
+msgstr "El nom del client OAuth"
#: mediagoblin/plugins/oauth/forms.py:37
msgid "Description"
-msgstr ""
+msgstr "Descripció"
#: mediagoblin/plugins/oauth/forms.py:39
msgid ""
"This will be visible to users allowing your\n"
" application to authenticate as them."
-msgstr ""
+msgstr "Això serà visiable a usuaris que permetin que la teva aplicació\n s'autentifiqui com a ells."
#: mediagoblin/plugins/oauth/forms.py:41
msgid "Type"
-msgstr ""
+msgstr "Tipus"
#: mediagoblin/plugins/oauth/forms.py:46
msgid ""
@@ -287,25 +293,25 @@ 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>Confidencial</strong> - El client pot\n fer peticions a la instància GNU MediaGoblin que no pot ésser\n interceptada per l'agent d'usuari (el client a la part servidor).<br />\n <strong>Public</strong> - El client no pot fer peticions \n confidencials a la instància GNU MediaGoblin (la part \n client JavaScript)."
#: mediagoblin/plugins/oauth/forms.py:53
msgid "Redirect URI"
-msgstr ""
+msgstr "Redireccionar URI "
#: mediagoblin/plugins/oauth/forms.py:55
msgid ""
"The redirect URI for the applications, this field\n"
" is <strong>required</strong> for public clients."
-msgstr ""
+msgstr "La URI de redirecció per les aplicacions, aquest camp\n és <strong>requeriment</strong> per els clients públics."
#: mediagoblin/plugins/oauth/forms.py:67
msgid "This field is required for public clients"
-msgstr ""
+msgstr "Aquest camp és requeriment per a clients públics"
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:60
msgid "The client {0} has been registered!"
-msgstr ""
+msgstr "El client {0} ha sigut enregistrat!"
#: mediagoblin/processing/__init__.py:138
msgid "Invalid file given for media type."
@@ -326,118 +332,117 @@ msgstr "Visca! S'ha enviat!"
#: mediagoblin/submit/views.py:215
#, python-format
msgid "Collection \"%s\" added!"
-msgstr ""
+msgstr "S'ha afegit la col.leccio \"%s\"!"
-#: mediagoblin/templates/mediagoblin/404.html:24
-msgid "Image of 404 goblin stressing out"
-msgstr "Imatge de la pantalla 404, el goblin no sap què fer..."
-
-#: mediagoblin/templates/mediagoblin/404.html:25
-msgid "Oops!"
-msgstr "Ups!"
-
-#: mediagoblin/templates/mediagoblin/404.html:26
-msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr "Sembla que no hi ha cap pàgina en aquesta adreça. Ho sentim."
-
-#: mediagoblin/templates/mediagoblin/404.html:28
-msgid ""
-"If you're sure the address is correct, maybe the page you're looking for has"
-" been moved or deleted."
-msgstr "Si esteu convençut que l'adreça és correcta, pot ser que la pàgina que cerqueu s'hagi canviat d'ubicació o s'hagi eliminat."
-
-#: mediagoblin/templates/mediagoblin/base.html:50
+#: mediagoblin/templates/mediagoblin/base.html:48
msgid "MediaGoblin logo"
msgstr "Logo de mediagoblin"
-#: mediagoblin/templates/mediagoblin/base.html:60
-msgid "Verify your email!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:66
-msgid "+ Add media"
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:67
-msgid "+ Add collection"
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:69
-msgid "View your profile"
-msgstr ""
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
+msgstr "Tots els fitxers"
-#: mediagoblin/templates/mediagoblin/base.html:70
-msgid "Log out"
-msgstr ""
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
+msgstr "Verifica el teu correu electrònic"
-#: mediagoblin/templates/mediagoblin/base.html:75
+#: 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:89
+#: mediagoblin/templates/mediagoblin/base.html:87
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project."
-msgstr ""
+msgstr "Alimentat per <a href=\"http://mediagoblin.org\">MediaGoblin</a>, un projecte <a href=\"http://gnu.org/\">GNU</a>."
-#: mediagoblin/templates/mediagoblin/base.html:92
+#: mediagoblin/templates/mediagoblin/base.html:90
#, 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:24
-msgid "Explore"
+#: mediagoblin/templates/mediagoblin/root.html:25
+msgid "Actions"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:26
-msgid "Hi there, welcome to this MediaGoblin site!"
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr "Modificar els ajustaments del compte"
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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 "Quadre de processament de fitxers"
+
+#: mediagoblin/templates/mediagoblin/root.html:51
+msgid "Explore"
+msgstr "Explorar"
+
+#: mediagoblin/templates/mediagoblin/root.html:53
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "Hola, una benvinguda al MediaGoblin!"
+
+#: mediagoblin/templates/mediagoblin/root.html:55
msgid ""
"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
"extraordinarily great piece of media hosting software."
-msgstr ""
+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:29
+#: mediagoblin/templates/mediagoblin/root.html:56
msgid ""
"To add your own media, place comments, and more, you can log in with your "
"MediaGoblin account."
-msgstr ""
+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:31
+#: mediagoblin/templates/mediagoblin/root.html:58
msgid "Don't have one yet? It's easy!"
-msgstr ""
+msgstr "No en tens una encara? Es fàcil!"
-#: mediagoblin/templates/mediagoblin/root.html:32
+#: mediagoblin/templates/mediagoblin/root.html:59
#, 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 ""
+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:40
+#: mediagoblin/templates/mediagoblin/root.html:67
msgid "Most recent media"
-msgstr ""
-
-#: 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 "Quadre de processament de fitxers"
+msgstr "Mitjans més recents"
#: mediagoblin/templates/mediagoblin/admin/panel.html:29
msgid ""
"Here you can track the state of media being processed on this instance."
-msgstr ""
+msgstr "Aqui pots seguir l'estat del mitjà que s'està processant a aquesta instància."
#: mediagoblin/templates/mediagoblin/admin/panel.html:32
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32
@@ -447,7 +452,7 @@ msgstr "S'està processant el fitxer"
#: mediagoblin/templates/mediagoblin/admin/panel.html:58
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56
msgid "No media in-processing"
-msgstr ""
+msgstr "No s'està processant cap mitjà"
#: mediagoblin/templates/mediagoblin/admin/panel.html:61
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59
@@ -457,34 +462,34 @@ msgstr "No s'han pogut penjar els següents fitxers:"
#: mediagoblin/templates/mediagoblin/admin/panel.html:90
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86
msgid "No failed entries!"
-msgstr ""
+msgstr "Sense entrades fallades!"
#: mediagoblin/templates/mediagoblin/admin/panel.html:92
msgid "Last 10 successful uploads"
-msgstr ""
+msgstr "Les últimes 10 pujades correctes"
#: mediagoblin/templates/mediagoblin/admin/panel.html:112
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107
msgid "No processed entries, yet!"
-msgstr ""
+msgstr "Encara no hi ha entrades processades!"
#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28
#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36
msgid "Set your new password"
-msgstr ""
+msgstr "Estableix la teva nova contrasenya"
#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39
msgid "Set password"
-msgstr ""
+msgstr "Establir contrasenya"
#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23
#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31
msgid "Recover password"
-msgstr ""
+msgstr "Recuperar contrasenya"
#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34
msgid "Send instructions"
-msgstr ""
+msgstr "Enviar instruccions"
#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19
#, python-format
@@ -498,7 +503,7 @@ msgid ""
"\n"
"If you think this is an error, just ignore this email and continue being\n"
"a happy goblin!"
-msgstr ""
+msgstr "Hola %(username)s,⎠⎠per cambiar la teva contrasenya de GNU MediaGoblin, obre la següent URL al ⎠teu navegador:⎠⎠%(verification_url)s⎠⎠Si creus que hi ha un error, ignora el correu i continua essent⎠un goblin feliç!"
#: mediagoblin/templates/mediagoblin/auth/login.html:39
msgid "Logging in failed!"
@@ -514,7 +519,7 @@ msgstr "Creeu-ne un aquí!"
#: mediagoblin/templates/mediagoblin/auth/login.html:51
msgid "Forgot your password?"
-msgstr ""
+msgstr "Has oblidat la teva contrasenya?"
#: mediagoblin/templates/mediagoblin/auth/register.html:28
#: mediagoblin/templates/mediagoblin/auth/register.html:36
@@ -540,46 +545,59 @@ msgstr "Hi %(username)s,\n\nto activate your GNU MediaGoblin account, open the f
#: mediagoblin/templates/mediagoblin/edit/attachments.html:35
#, python-format
msgid "Editing attachments for %(media_title)s"
+msgstr "Editant afegits per a %(media_title)s"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:43
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
+msgid "Attachments"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit.html:23
-#: mediagoblin/templates/mediagoblin/edit/edit.html:35
-#, python-format
-msgid "Editing %(media_title)s"
-msgstr "Edició %(media_title)s "
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:53
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
msgid "Cancel"
msgstr "Cancel·la"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:43
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
msgid "Save changes"
msgstr "Desa els canvis"
+#: mediagoblin/templates/mediagoblin/edit/edit.html:23
+#: mediagoblin/templates/mediagoblin/edit/edit.html:35
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "Edició %(media_title)s "
+
#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:41
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
#, python-format
msgid "Changing %(username)s's account settings"
-msgstr ""
+msgstr "Modificant els detalls del compte de %(username)s"
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29
#, python-format
msgid "Editing %(collection_title)s"
-msgstr ""
+msgstr "Editant %(collection_title)s"
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:23
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
#, python-format
msgid "Editing %(username)s's profile"
-msgstr ""
+msgstr "Editant perfil de %(username)s"
#: mediagoblin/templates/mediagoblin/listings/collection.html:30
#: mediagoblin/templates/mediagoblin/listings/collection.html:35
@@ -587,41 +605,90 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/listings/tag.html:35
#, python-format
msgid "Media tagged with: %(tag_name)s"
-msgstr ""
+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/image.html:23
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
msgid "Download"
-msgstr ""
+msgstr "Descarregar"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:27
msgid "Original"
-msgstr ""
+msgstr "Original"
#: 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 "Ho sento, aquest audiothis àudio no funcionarà perque \n »el teu navegador web no contempla suport d'àudio \n »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 ""
+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/video.html:56
msgid "Original file"
-msgstr ""
+msgstr "Arxiu original"
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:63
msgid "WebM file (Vorbis codec)"
+msgstr "Arxiu WebM (Vorbis codec)"
+
+#: 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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr "Imatge per %(media_title)s"
+
+#: 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 ""
+
+#: 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:40
@@ -629,93 +696,85 @@ msgid ""
"Sorry, this video will not work because \n"
"\t your web browser does not support HTML5 \n"
"\t video."
-msgstr ""
+msgstr "Ho sento, aquest video no funcionarà perquè \n » el teu navegador web no té suport per videos \n » HTML5."
#: mediagoblin/templates/mediagoblin/media_displays/video.html:43
msgid ""
"You can get a modern web browser that \n"
"\t can play this video at <a href=\"http://getfirefox.com\">\n"
"\t http://getfirefox.com</a>!"
-msgstr ""
+msgstr "Pots obtenir un navegador web modern que \n » podrà reproduir aquest vídeo, a <a href=\"http://getfirefox.com\">\n » http://getfirefox.com</a>!"
#: mediagoblin/templates/mediagoblin/media_displays/video.html:59
msgid "WebM file (640p; VP8/Vorbis)"
-msgstr ""
+msgstr "Arxiu WebM (640p; VP8/Vorbis)"
#: mediagoblin/templates/mediagoblin/submit/collection.html:26
msgid "Add a collection"
-msgstr ""
+msgstr "Afegir a la col.lecció"
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
#: mediagoblin/templates/mediagoblin/submit/start.html:34
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:83
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
msgid "Add"
-msgstr ""
+msgstr "Afegir"
#: mediagoblin/templates/mediagoblin/submit/start.html:23
#: mediagoblin/templates/mediagoblin/submit/start.html:30
msgid "Add your media"
-msgstr ""
+msgstr "Afegeix el teu mitjà"
#: mediagoblin/templates/mediagoblin/user_pages/collection.html:30
#, python-format
msgid "%(collection_title)s (%(username)s's collection)"
-msgstr ""
+msgstr "%(collection_title)s (la col.lecció de %(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 ""
+msgstr "%(collection_title)s per a <a href=\"%(user_url)s\">%(username)s</a>"
#: mediagoblin/templates/mediagoblin/user_pages/collection.html:52
#: mediagoblin/templates/mediagoblin/user_pages/media.html:87
msgid "Edit"
-msgstr ""
+msgstr "Editar"
#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56
#: mediagoblin/templates/mediagoblin/user_pages/media.html:91
msgid "Delete"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/collection.html:59
-#, python-format
-msgid ""
-"<p>\n"
-" %(collection_description)s\n"
-" </p>"
-msgstr ""
+msgstr "Esborrar"
#: 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 ""
+msgstr "Realment vols esborrar %(title)s?"
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
-msgstr ""
+msgstr "Esborrar permanentment"
#: 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 "Relment eliminar %(media_title)s de %(collection_title)s?"
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
msgid "Remove"
-msgstr ""
+msgstr "Eliminar"
#: 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 "Hola %(username)s,\n%(comment_author)s ha comentat el teu post (%(comment_url)s) a %(instance_name)s\n"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30
#, python-format
msgid "%(username)s's media"
-msgstr ""
+msgstr "Mitjà de %(username)s"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:37
#, python-format
@@ -725,76 +784,65 @@ msgstr "<a href=\"%(user_url)s\">%(username)s</a>'s media"
#: mediagoblin/templates/mediagoblin/user_pages/media.html:46
#, python-format
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:67
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
-#, python-format
-msgid "Image for %(media_title)s"
-msgstr ""
+msgstr "■Navegant mitjà per a <a href=\"%(user_url)s\">%(username)s</a>"
#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
msgid "Add a comment"
-msgstr ""
+msgstr "Afegeix un comentari"
#: mediagoblin/templates/mediagoblin/user_pages/media.html:109
msgid ""
"You can use <a "
"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for"
" formatting."
-msgstr ""
+msgstr "Pots usar <a href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> per donar format."
#: mediagoblin/templates/mediagoblin/user_pages/media.html:113
msgid "Add this comment"
-msgstr ""
+msgstr "Afegir aquest comentari"
#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
msgid "at"
-msgstr ""
+msgstr "a"
#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
#, python-format
msgid ""
"<h3>Added on</h3>\n"
" <p>%(date)s</p>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
-msgid "Attachments"
-msgstr ""
+msgstr "<h3>Afegit el</h3>\n <p>%(date)s</p>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
-msgid "Add attachment"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
#, python-format
msgid "Add %(title)s to collection"
-msgstr ""
+msgstr "Afegir %(title)s a la col.lecció"
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
msgid "+"
-msgstr ""
+msgstr "+"
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
msgid "Add a new collection"
-msgstr ""
+msgstr "Afegir una nova col.lecció"
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:29
msgid ""
"You can track the state of media being processed for your gallery here."
-msgstr ""
+msgstr "Aqui pots seguir l'estat del mitjà que s'està processant per la teva galeria"
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:89
msgid "Your last 10 successful uploads"
-msgstr ""
+msgstr "Les teves 10 últimes pujades correctes"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:31
#: mediagoblin/templates/mediagoblin/user_pages/user.html:89
#, python-format
msgid "%(username)s's profile"
-msgstr ""
+msgstr "Perfil de %(username)s"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:43
msgid "Sorry, no such user found."
@@ -837,7 +885,7 @@ msgstr "Si siu aqeust usuari però heu perdut el correu de verificació, podeu <
#: mediagoblin/templates/mediagoblin/user_pages/user.html:96
msgid "Here's a spot to tell others about yourself."
-msgstr ""
+msgstr "Aqui hi ha un espai per explicar de tu als demés"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:101
#: mediagoblin/templates/mediagoblin/user_pages/user.html:118
@@ -848,47 +896,31 @@ msgstr "Edita el perfil"
msgid "This user hasn't filled in their profile (yet)."
msgstr "Aquest usuari encara no ha escrit res al seu perfil."
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:125
-msgid "Change account settings"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:138
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
#, python-format
msgid "View all of %(username)s's media"
msgstr "View all of %(username)s's media"
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
msgid ""
"This is where your media will appear, but you don't seem to have added "
"anything yet."
-msgstr ""
+msgstr "Aqui és on apareixerà el teu mitjà, però sembla que encara no hi has afegit res."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:157
-msgid "Add media"
-msgstr "Tots els fitxers"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:163
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:87
-#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:72
+#: 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 ""
+msgstr "Sembla que no hi ha cap mitjà aqui encara..."
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:39
-#, python-format
-msgid ""
-"<br />\n"
-" <a href=\"%(entry_url)s\">%(note)s</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:47
-#, python-format
-msgid "<br /><a href=\"%(remove_url)s\" class=\"remove\">(remove)</a>"
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
msgstr ""
#: mediagoblin/templates/mediagoblin/utils/collections.html:20
#, python-format
msgid "In collections (%(collected)s)"
-msgstr ""
+msgstr "A les col.leccions (%(collected)s)"
#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
msgid "feed icon"
@@ -900,38 +932,38 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:25
msgid "Location"
-msgstr ""
+msgstr "Ubicació"
-#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:38
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
#, python-format
msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
-msgstr ""
+msgstr "Veure a <a href=\"%(osm_url)s\">OpenStreetMap</a>"
#: mediagoblin/templates/mediagoblin/utils/license.html:25
msgid "All rights reserved"
-msgstr ""
+msgstr "Tots els drets reservats"
#: mediagoblin/templates/mediagoblin/utils/pagination.html:39
msgid "↠Newer"
-msgstr ""
+msgstr "↠Més nou"
#: mediagoblin/templates/mediagoblin/utils/pagination.html:45
msgid "Older →"
-msgstr ""
+msgstr "Més antic →"
#: mediagoblin/templates/mediagoblin/utils/pagination.html:48
msgid "Go to page:"
-msgstr ""
+msgstr "Anar a la pàgina:"
#: mediagoblin/templates/mediagoblin/utils/prev_next.html:28
#: mediagoblin/templates/mediagoblin/utils/prev_next.html:33
msgid "newer"
-msgstr ""
+msgstr "més nou"
#: mediagoblin/templates/mediagoblin/utils/prev_next.html:39
#: mediagoblin/templates/mediagoblin/utils/prev_next.html:44
msgid "older"
-msgstr ""
+msgstr "més antic"
#: mediagoblin/templates/mediagoblin/utils/tags.html:20
msgid "Tagged with"
@@ -939,96 +971,122 @@ msgstr ""
#: mediagoblin/tools/exif.py:78
msgid "Could not read the image file."
+msgstr "No s'ha pogut llegir l'arxiu d'imatge"
+
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr "Ups!"
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr ""
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr ""
+
+#: mediagoblin/tools/response.py:47
+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:55
+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/user_pages/forms.py:28
msgid "I am sure I want to delete this"
-msgstr ""
+msgstr "Estic segur que vull esborrar això"
#: mediagoblin/user_pages/forms.py:32
msgid "I am sure I want to remove this item from the collection"
-msgstr ""
+msgstr "Estic segur que vull esborrar aquest element de la col.lecció"
#: mediagoblin/user_pages/forms.py:35
msgid "-- Select --"
-msgstr ""
+msgstr "-- Sel.leccionar --"
#: mediagoblin/user_pages/forms.py:37
msgid "Include a note"
-msgstr ""
+msgstr "Incluir una nota"
#: mediagoblin/user_pages/lib.py:56
msgid "commented on your post"
-msgstr ""
+msgstr "comentat al teu post"
-#: mediagoblin/user_pages/views.py:161
+#: mediagoblin/user_pages/views.py:156
msgid "Oops, your comment was empty."
-msgstr ""
+msgstr "Uups, el teu comentari era buit."
-#: mediagoblin/user_pages/views.py:167
+#: mediagoblin/user_pages/views.py:162
msgid "Your comment has been posted!"
-msgstr ""
+msgstr "El teu comentari s'ha publicat!"
-#: mediagoblin/user_pages/views.py:235
+#: mediagoblin/user_pages/views.py:230
msgid "You have to select or add a collection"
-msgstr ""
+msgstr "Has de sel.leccionar o afegir una col.lecció"
-#: mediagoblin/user_pages/views.py:243
+#: mediagoblin/user_pages/views.py:238
#, python-format
msgid "\"%s\" already in collection \"%s\""
-msgstr ""
+msgstr "\"%s\" ja és a la col.lecció \"%s\""
-#: mediagoblin/user_pages/views.py:258
+#: mediagoblin/user_pages/views.py:253
#, python-format
msgid "\"%s\" added to collection \"%s\""
-msgstr ""
+msgstr "\"%s\" afegir a la col.lecció \"%s\""
-#: mediagoblin/user_pages/views.py:266
+#: mediagoblin/user_pages/views.py:261
msgid "Please check your entries and try again."
-msgstr ""
+msgstr "Si et plau, comprova les teves entrades i intenta-ho de nou."
-#: mediagoblin/user_pages/views.py:297
+#: mediagoblin/user_pages/views.py:292
msgid ""
"Some of the files with this entry seem to be missing. Deleting anyway."
-msgstr ""
+msgstr "Sembla que falten alguns arxius amb aquesta entrada. Tot i així s'eliminen."
-#: mediagoblin/user_pages/views.py:302
+#: mediagoblin/user_pages/views.py:297
msgid "You deleted the media."
-msgstr ""
+msgstr "Has esborrat el mitjà"
-#: mediagoblin/user_pages/views.py:309
+#: mediagoblin/user_pages/views.py:304
msgid "The media was not deleted because you didn't check that you were sure."
-msgstr ""
+msgstr "El mitjà no s'ha esborrat perque no has marcat que n'estiguessis segur."
-#: mediagoblin/user_pages/views.py:317
+#: mediagoblin/user_pages/views.py:312
msgid "You are about to delete another user's media. Proceed with caution."
-msgstr ""
+msgstr "Ets a punt d'esborrar el mitjà d'un altre usuari. Prossegueix amb cautela."
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
-msgstr ""
+msgstr "Has esborrat l'element de la col.lecció"
-#: mediagoblin/user_pages/views.py:383
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
-msgstr ""
+msgstr "L'element no s'ha eliminat perque no has marcat que n'estiguessis segur."
-#: mediagoblin/user_pages/views.py:393
+#: mediagoblin/user_pages/views.py:384
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
-msgstr ""
+msgstr "Ets a punt d'esborrar un element de la col.lecció d'un altre usuari. Prossegueix amb cautela."
-#: mediagoblin/user_pages/views.py:426
+#: mediagoblin/user_pages/views.py:417
#, python-format
msgid "You deleted the collection \"%s\""
-msgstr ""
+msgstr "Has esborrat la col.lecció \"%s\""
-#: mediagoblin/user_pages/views.py:433
+#: mediagoblin/user_pages/views.py:424
msgid ""
"The collection was not deleted because you didn't check that you were sure."
-msgstr ""
+msgstr "La col.lecció no s'ha esborrat perquè no has marcat que n'estiguessis segur."
-#: mediagoblin/user_pages/views.py:443
+#: mediagoblin/user_pages/views.py:434
msgid ""
"You are about to delete another user's collection. Proceed with caution."
-msgstr ""
+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 23685f41..9d9955ce 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 0426e9ed..c0677f43 100644
--- a/mediagoblin/i18n/da/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/da/LC_MESSAGES/mediagoblin.po
@@ -5,12 +5,13 @@
# 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.
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2012-09-24 14:01-0500\n"
-"PO-Revision-Date: 2012-09-24 18:57+0000\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 15:14+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
@@ -34,41 +35,41 @@ msgstr "Email adresse"
#: mediagoblin/auth/forms.py:51
msgid "Username or email"
-msgstr ""
+msgstr "Brugernavn eller email"
#: mediagoblin/auth/forms.py:58
msgid "Incorrect input"
-msgstr ""
+msgstr "Forkert input"
#: mediagoblin/auth/views.py:55
msgid "Sorry, registration is disabled on this instance."
-msgstr ""
+msgstr "Desværre, registrering er ikke muligt på denne instans"
#: mediagoblin/auth/views.py:75
msgid "Sorry, a user with that name already exists."
-msgstr ""
+msgstr "Desværre, det brugernavn er allerede brugt"
#: mediagoblin/auth/views.py:79
msgid "Sorry, a user with that email address already exists."
-msgstr ""
+msgstr "Desværre, en bruger er allerede oprettet for den email"
#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
-msgstr ""
+msgstr "Din email adresse er blevet bekræftet. Du kan nu logge på, ændre din profil, og indsende billeder!"
#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
-msgstr ""
+msgstr "Bekræftelsesnøglen eller brugerid er forkert"
#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
-msgstr ""
+msgstr "Du er nødt til at være logget ind, så vi ved hvem vi skal emaile!"
#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
-msgstr ""
+msgstr "Du har allerede bekræftet din email adresse!"
#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
@@ -77,23 +78,23 @@ msgstr "Email til godkendelse sendt igen."
#: mediagoblin/auth/views.py:263
msgid ""
"An email has been sent with instructions on how to change your password."
-msgstr ""
+msgstr "En email er blevet sendt med instruktioner til at ændre dit kodeord."
#: mediagoblin/auth/views.py:273
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
-msgstr ""
+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:285
msgid "Couldn't find someone with that username or email."
-msgstr ""
+msgstr "Vi kunne ikke dit brugernavn eller email."
#: mediagoblin/auth/views.py:333
msgid "You can now log in using your new password."
-msgstr ""
+msgstr "Du kan nu logge ind med dit nye kodeord."
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:83
+#: 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:40
msgid "Title"
@@ -101,30 +102,30 @@ msgstr "Titel"
#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31
msgid "Description of this work"
-msgstr ""
+msgstr "Beskrivelse af arbejdet"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:87 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:44
msgid ""
"You can use\n"
" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n"
" Markdown</a> for formatting."
-msgstr ""
+msgstr "Du kan bruge\n <a href=\"http://daringfireball.net/projects/markdown/basics\">\n Markdown</a> til formattering."
#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36
msgid "Tags"
-msgstr ""
+msgstr "Tags"
#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38
msgid "Separate tags by commas."
-msgstr ""
+msgstr "Separer tags med kommaer."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:91
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr ""
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:92
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr ""
@@ -132,16 +133,16 @@ msgstr ""
msgid ""
"The title part of this media's address. You usually don't need to change "
"this."
-msgstr ""
+msgstr "Titeldelen af dette medie's adresse. Du behøver normalt ikke ændre dette."
#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41
#: mediagoblin/templates/mediagoblin/utils/license.html:20
msgid "License"
-msgstr ""
+msgstr "Licens"
#: mediagoblin/edit/forms.py:50
msgid "Bio"
-msgstr ""
+msgstr "Bio"
#: mediagoblin/edit/forms.py:56
msgid "Website"
@@ -149,38 +150,38 @@ msgstr "Websted"
#: mediagoblin/edit/forms.py:58
msgid "This address contains errors"
-msgstr ""
+msgstr "Denne adresse indeholder fejl"
#: mediagoblin/edit/forms.py:63
msgid "Old password"
-msgstr ""
+msgstr "Gammelt kodeord"
#: mediagoblin/edit/forms.py:64
msgid "Enter your old password to prove you own this account."
-msgstr ""
+msgstr "Skriv dit gamle kodeord for at bevise det er din konto."
#: mediagoblin/edit/forms.py:67
msgid "New password"
-msgstr ""
+msgstr "Ny kodeord"
-#: mediagoblin/edit/forms.py:72
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
-msgstr ""
+msgstr "Email mig når andre kommenterer på mine medier"
-#: mediagoblin/edit/forms.py:84
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
-msgstr ""
+msgstr "Titlen kan ikke være tom"
-#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:43
msgid "Description of this collection"
-msgstr ""
+msgstr "Beskrivelse af denne samling"
-#: mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
-msgstr ""
+msgstr "Titeldelen af denne samlings's adresse. Du behøver normalt ikke ændre dette."
#: mediagoblin/edit/views.py:65
msgid "An entry with that slug already exists for this user."
@@ -188,41 +189,46 @@ msgstr ""
#: mediagoblin/edit/views.py:86
msgid "You are editing another user's media. Proceed with caution."
+msgstr "Du er ved at ændre en anden brugers' medier. Pas på."
+
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
msgstr ""
-#: mediagoblin/edit/views.py:182
+#: mediagoblin/edit/views.py:181
msgid "You are editing a user's profile. Proceed with caution."
-msgstr ""
+msgstr "Du er ved at ændre en bruger's profil. Pas på."
-#: mediagoblin/edit/views.py:198
+#: mediagoblin/edit/views.py:197
msgid "Profile changes saved"
-msgstr ""
+msgstr "Profilændringer gemt"
-#: mediagoblin/edit/views.py:227 mediagoblin/edit/views.py:247
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
msgid "Account settings saved"
-msgstr ""
+msgstr "Kontoindstillinger gemt"
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:251
msgid "Wrong password"
-msgstr ""
+msgstr "Forkert kodeord"
-#: mediagoblin/edit/views.py:288 mediagoblin/submit/views.py:211
-#: mediagoblin/user_pages/views.py:215
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
#, python-format
msgid "You already have a collection called \"%s\"!"
-msgstr ""
+msgstr "Du har allerede en samling ved navn \"%s\"!"
-#: mediagoblin/edit/views.py:292
+#: mediagoblin/edit/views.py:291
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:309
+#: mediagoblin/edit/views.py:308
msgid "You are editing another user's collection. Proceed with caution."
-msgstr ""
+msgstr "Du er ved at ændre en anden bruger's samling. Pas på."
#: mediagoblin/gmg_commands/theme.py:58
msgid "Cannot link theme... no theme set\n"
-msgstr ""
+msgstr "Kan ikke linke til tema... intet tema sat\n"
#: mediagoblin/gmg_commands/theme.py:71
msgid "No asset directory for this theme\n"
@@ -233,9 +239,9 @@ msgid "However, old link directory symlink found; removed.\n"
msgstr ""
#: mediagoblin/media_types/__init__.py:60
-#: mediagoblin/media_types/__init__.py:120
+#: mediagoblin/media_types/__init__.py:101
msgid "Sorry, I don't support that file type :("
-msgstr ""
+msgstr "Desværre, jeg understøtter ikke den filtype :("
#: mediagoblin/media_types/video/processing.py:35
msgid "Video transcoding failed"
@@ -247,27 +253,27 @@ msgstr ""
#: mediagoblin/plugins/oauth/forms.py:28
msgid "Next URL"
-msgstr ""
+msgstr "Næste URL"
#: mediagoblin/plugins/oauth/forms.py:30
msgid "Allow"
-msgstr ""
+msgstr "Tillad"
#: mediagoblin/plugins/oauth/forms.py:31
msgid "Deny"
-msgstr ""
+msgstr "Forbyd"
#: mediagoblin/plugins/oauth/forms.py:35
msgid "Name"
-msgstr ""
+msgstr "Navn"
#: mediagoblin/plugins/oauth/forms.py:36
msgid "The name of the OAuth client"
-msgstr ""
+msgstr "Navnet af OAuth klienten"
#: mediagoblin/plugins/oauth/forms.py:37
msgid "Description"
-msgstr ""
+msgstr "Beskrivelse"
#: mediagoblin/plugins/oauth/forms.py:39
msgid ""
@@ -277,7 +283,7 @@ msgstr ""
#: mediagoblin/plugins/oauth/forms.py:41
msgid "Type"
-msgstr ""
+msgstr "Type"
#: mediagoblin/plugins/oauth/forms.py:46
msgid ""
@@ -301,15 +307,15 @@ msgstr ""
#: mediagoblin/plugins/oauth/forms.py:67
msgid "This field is required for public clients"
-msgstr ""
+msgstr "Dette felt er nødvendigt for offentlige klienter"
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:60
msgid "The client {0} has been registered!"
-msgstr ""
+msgstr "Klienten {0} er blevet registreret!"
#: mediagoblin/processing/__init__.py:138
msgid "Invalid file given for media type."
-msgstr ""
+msgstr "Forkert fil for medietypen."
#: mediagoblin/submit/forms.py:26
msgid "File"
@@ -317,73 +323,54 @@ msgstr "Fil"
#: mediagoblin/submit/views.py:57
msgid "You must provide a file."
-msgstr ""
+msgstr "Du må give mig en fil"
#: mediagoblin/submit/views.py:164
msgid "Woohoo! Submitted!"
-msgstr ""
+msgstr "Juhuu! Delt!"
#: mediagoblin/submit/views.py:215
#, python-format
msgid "Collection \"%s\" added!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/404.html:24
-msgid "Image of 404 goblin stressing out"
-msgstr "Billede af stresset 404 goblin"
-
-#: mediagoblin/templates/mediagoblin/404.html:25
-msgid "Oops!"
-msgstr "Hovsa!"
-
-#: mediagoblin/templates/mediagoblin/404.html:26
-msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/404.html:28
-msgid ""
-"If you're sure the address is correct, maybe the page you're looking for has"
-" been moved or deleted."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:50
+#: mediagoblin/templates/mediagoblin/base.html:48
msgid "MediaGoblin logo"
msgstr "MediaGoblin logo"
-#: mediagoblin/templates/mediagoblin/base.html:60
-msgid "Verify your email!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:66
-msgid "+ Add media"
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:67
-msgid "+ Add collection"
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:69
-msgid "View your profile"
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:70
-msgid "Log out"
-msgstr ""
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
+msgstr "Bekræft din email!"
-#: mediagoblin/templates/mediagoblin/base.html:75
+#: 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:89
+#: mediagoblin/templates/mediagoblin/base.html:87
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project."
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:92
+#: mediagoblin/templates/mediagoblin/base.html:90
#, python-format
msgid ""
"Released under the <a "
@@ -391,31 +378,56 @@ msgid ""
"href=\"%(source_link)s\">Source code</a> available."
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:24
-msgid "Explore"
+#: mediagoblin/templates/mediagoblin/error.html:24
+msgid "Image of goblin stressing out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:26
-msgid "Hi there, welcome to this MediaGoblin site!"
+#: mediagoblin/templates/mediagoblin/root.html:25
+msgid "Actions"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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/root.html:51
+msgid "Explore"
+msgstr "Udforsk"
+
+#: mediagoblin/templates/mediagoblin/root.html:53
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "Hey, velkommen til denne MediaGoblin side!"
+
+#: mediagoblin/templates/mediagoblin/root.html:55
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:29
+#: mediagoblin/templates/mediagoblin/root.html:56
msgid ""
"To add your own media, place comments, and more, you can log in with your "
"MediaGoblin account."
-msgstr ""
+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:31
+#: mediagoblin/templates/mediagoblin/root.html:58
msgid "Don't have one yet? It's easy!"
-msgstr ""
+msgstr "Har du ikke en endnu? Det er let!"
-#: mediagoblin/templates/mediagoblin/root.html:32
+#: mediagoblin/templates/mediagoblin/root.html:59
#, python-format
msgid ""
"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
@@ -423,17 +435,10 @@ msgid ""
" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:40
+#: mediagoblin/templates/mediagoblin/root.html:67
msgid "Most recent media"
msgstr ""
-#: 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/admin/panel.html:29
msgid ""
"Here you can track the state of media being processed on this instance."
@@ -542,30 +547,43 @@ msgstr ""
msgid "Editing attachments for %(media_title)s"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit.html:23
-#: mediagoblin/templates/mediagoblin/edit/edit.html:35
-#, python-format
-msgid "Editing %(media_title)s"
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:43
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
+msgid "Attachments"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:53
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
msgid "Cancel"
msgstr "Afbryd"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:43
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
msgid "Save changes"
msgstr "Gem ændringer"
+#: mediagoblin/templates/mediagoblin/edit/edit.html:23
+#: mediagoblin/templates/mediagoblin/edit/edit.html:35
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:41
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
#, python-format
msgid "Changing %(username)s's account settings"
msgstr ""
@@ -591,13 +609,12 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:23
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
msgid "Download"
msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:27
msgid "Original"
msgstr ""
@@ -624,6 +641,56 @@ msgstr ""
msgid "WebM file (Vorbis codec)"
msgstr ""
+#: 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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr ""
+
+#: 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 ""
+
+#: 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:40
msgid ""
"Sorry, this video will not work because \n"
@@ -648,7 +715,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
#: mediagoblin/templates/mediagoblin/submit/start.html:34
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:83
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
msgid "Add"
msgstr ""
@@ -677,14 +744,6 @@ msgstr ""
msgid "Delete"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection.html:59
-#, python-format
-msgid ""
-"<p>\n"
-" %(collection_description)s\n"
-" </p>"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
@@ -692,7 +751,7 @@ msgid "Really delete %(title)s?"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr ""
@@ -701,7 +760,7 @@ msgstr ""
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
msgid "Remove"
msgstr ""
@@ -727,12 +786,6 @@ msgstr ""
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:67
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
-#, python-format
-msgid "Image for %(media_title)s"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
msgid "Add a comment"
msgstr ""
@@ -759,13 +812,8 @@ msgid ""
" <p>%(date)s</p>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
-msgid "Attachments"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
-msgid "Add attachment"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
@@ -773,11 +821,11 @@ msgstr ""
msgid "Add %(title)s to collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
msgid "+"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
msgid "Add a new collection"
msgstr ""
@@ -848,41 +896,25 @@ msgstr "Ret profil"
msgid "This user hasn't filled in their profile (yet)."
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:125
-msgid "Change account settings"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:138
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
#, python-format
msgid "View all of %(username)s's media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
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:157
-msgid "Add media"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:163
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:87
-#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:72
+#: 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:39
-#, python-format
-msgid ""
-"<br />\n"
-" <a href=\"%(entry_url)s\">%(note)s</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:47
-#, python-format
-msgid "<br /><a href=\"%(remove_url)s\" class=\"remove\">(remove)</a>"
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
msgstr ""
#: mediagoblin/templates/mediagoblin/utils/collections.html:20
@@ -902,7 +934,7 @@ msgstr ""
msgid "Location"
msgstr ""
-#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:38
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
#, python-format
msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
msgstr ""
@@ -941,6 +973,32 @@ msgstr ""
msgid "Could not read the image file."
msgstr ""
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr "Hovsa!"
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr ""
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr ""
+
+#: mediagoblin/tools/response.py:47
+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:55
+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/user_pages/forms.py:28
msgid "I am sure I want to delete this"
msgstr ""
@@ -961,74 +1019,74 @@ msgstr ""
msgid "commented on your post"
msgstr ""
-#: mediagoblin/user_pages/views.py:161
+#: mediagoblin/user_pages/views.py:156
msgid "Oops, your comment was empty."
msgstr ""
-#: mediagoblin/user_pages/views.py:167
+#: mediagoblin/user_pages/views.py:162
msgid "Your comment has been posted!"
msgstr ""
-#: mediagoblin/user_pages/views.py:235
+#: mediagoblin/user_pages/views.py:230
msgid "You have to select or add a collection"
msgstr ""
-#: mediagoblin/user_pages/views.py:243
+#: mediagoblin/user_pages/views.py:238
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:258
+#: mediagoblin/user_pages/views.py:253
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:266
+#: mediagoblin/user_pages/views.py:261
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:297
+#: mediagoblin/user_pages/views.py:292
msgid ""
"Some of the files with this entry seem to be missing. Deleting anyway."
msgstr ""
-#: mediagoblin/user_pages/views.py:302
+#: mediagoblin/user_pages/views.py:297
msgid "You deleted the media."
msgstr ""
-#: mediagoblin/user_pages/views.py:309
+#: mediagoblin/user_pages/views.py:304
msgid "The media was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:317
+#: mediagoblin/user_pages/views.py:312
msgid "You are about to delete another user's media. Proceed with caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr ""
-#: mediagoblin/user_pages/views.py:383
+#: 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:393
+#: mediagoblin/user_pages/views.py:384
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:426
+#: mediagoblin/user_pages/views.py:417
#, python-format
msgid "You deleted the collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:433
+#: mediagoblin/user_pages/views.py:424
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:443
+#: mediagoblin/user_pages/views.py:434
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 015a480c..6374be42 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 6a1605c3..d3a56821 100644
--- a/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.po
@@ -5,7 +5,7 @@
# 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>, 2011-2012.
# <jakob.kramer@gmx.de>, 2011, 2012.
# Jakob Kramer <jakob.kramer@gmx.de>, 2012.
# Jan-Christoph Borchardt <JanCBorchardt@fsfe.org>, 2011.
@@ -13,13 +13,15 @@
# <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.
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2012-09-24 14:01-0500\n"
-"PO-Revision-Date: 2012-09-24 18:57+0000\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 15:14+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: German (http://www.transifex.com/projects/p/mediagoblin/language/de/)\n"
"MIME-Version: 1.0\n"
@@ -51,7 +53,7 @@ msgstr "Fehlerhafte Eingabe"
#: mediagoblin/auth/views.py:55
msgid "Sorry, registration is disabled on this instance."
-msgstr "Das Registrieren ist auf dieser Instanz leider deaktiviert."
+msgstr "Benutzerregistrierung ist auf diesem Server leider deaktiviert."
#: mediagoblin/auth/views.py:75
msgid "Sorry, a user with that name already exists."
@@ -65,11 +67,11 @@ msgstr "Leider gibt es bereits einen Benutzer mit dieser E-Mail-Adresse."
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
-msgstr "Deine E-Mail-Adresse wurde bestätigt. Du kannst dich nun anmelden, dein Profil bearbeiten und Bilder hochladen!"
+msgstr "Dein GNU MediaGoblin Konto wurde hiermit aktiviert. Du kannst dich jetzt anmelden, dein Profil bearbeiten und Medien hochladen."
#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
-msgstr "Der Bestätigungsschlüssel oder die Nutzernummer ist falsch."
+msgstr "Der Aktivierungsschlüssel oder die Nutzerkennung ist falsch."
#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
@@ -77,22 +79,22 @@ msgstr "Du musst angemeldet sein, damit wir wissen, wer die Email bekommt."
#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
-msgstr "Deine E-Mail-Adresse wurde bereits bestätigt."
+msgstr "Deine E-Mail-Adresse wurde bereits aktiviert."
#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
-msgstr "Bestätigungs-E-Mail wurde erneut versandt."
+msgstr "Aktivierungsmail wurde erneut versandt."
#: mediagoblin/auth/views.py:263
msgid ""
"An email has been sent with instructions on how to change your password."
-msgstr "Es wurde eine Email mit Anweisungen für die Änderung des Passwortes an dich gesendet."
+msgstr "Es wurde eine E-Mail mit der Anleitung zur Änderung des Passwortes an Dich gesendet."
#: mediagoblin/auth/views.py:273
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 bestätigt wurde."
+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:285
msgid "Couldn't find someone with that username or email."
@@ -102,7 +104,7 @@ msgstr "Es konnte niemand mit diesem Nutzernamen oder Email gefunden werden."
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:83
+#: 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:40
msgid "Title"
@@ -113,7 +115,7 @@ msgid "Description of this work"
msgstr "Beschreibung des Werkes"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:87 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:44
msgid ""
"You can use\n"
@@ -129,11 +131,11 @@ msgstr "Schlagwörter"
msgid "Separate tags by commas."
msgstr "Kommaseparierte Schlagwörter"
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:91
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "Kurztitel"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:92
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "Bitte gib einen Kurztitel ein"
@@ -172,24 +174,24 @@ msgstr "Gib dein altes Passwort ein, um zu bestätigen, dass du dieses Konto bes
msgid "New password"
msgstr "Neues Passwort"
-#: mediagoblin/edit/forms.py:72
+#: 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:84
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
-msgstr ""
+msgstr "Der Titel kann nicht leer sein"
-#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:43
msgid "Description of this collection"
-msgstr ""
+msgstr "Beschreibung dieser Sammlung"
-#: mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
-msgstr ""
+msgstr "Der Titelteil dieser Sammlungsadresse. Du musst ihn normalerweise nicht ändern."
#: mediagoblin/edit/views.py:65
msgid "An entry with that slug already exists for this user."
@@ -197,37 +199,42 @@ msgstr "Diesen Kurztitel hast du bereits vergeben."
#: mediagoblin/edit/views.py:86
msgid "You are editing another user's media. Proceed with caution."
-msgstr "Du bearbeitest die Medien eines Anderen. Sei bitte vorsichtig."
+msgstr "Du bearbeitest die Medien eines anderen Nutzers. Sei bitte vorsichtig."
-#: mediagoblin/edit/views.py:182
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr "Sie haben den Anhang %s hinzugefügt!"
+
+#: mediagoblin/edit/views.py:181
msgid "You are editing a user's profile. Proceed with caution."
-msgstr "Du bearbeitest das Profil eines Anderen. Sei bitte vorsichtig."
+msgstr "Du bearbeitest das Profil eines anderen Nutzers. Sei bitte vorsichtig."
-#: mediagoblin/edit/views.py:198
+#: mediagoblin/edit/views.py:197
msgid "Profile changes saved"
msgstr "Das Profil wurde aktualisiert"
-#: mediagoblin/edit/views.py:227 mediagoblin/edit/views.py:247
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
msgid "Account settings saved"
msgstr "Kontoeinstellungen gespeichert"
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:251
msgid "Wrong password"
msgstr "Falsches Passwort"
-#: mediagoblin/edit/views.py:288 mediagoblin/submit/views.py:211
-#: mediagoblin/user_pages/views.py:215
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
#, python-format
msgid "You already have a collection called \"%s\"!"
-msgstr ""
+msgstr "Du hast bereits eine Sammlung mit Namen \"%s\"!"
-#: mediagoblin/edit/views.py:292
+#: mediagoblin/edit/views.py:291
msgid "A collection with that slug already exists for this user."
-msgstr ""
+msgstr "Eine Sammlung mit diesem Kürzel existiert bereits für diesen Benutzer."
-#: mediagoblin/edit/views.py:309
+#: mediagoblin/edit/views.py:308
msgid "You are editing another user's collection. Proceed with caution."
-msgstr ""
+msgstr "Du bearbeitest die Sammlung eines anderen Benutzers. Sei vorsichtig."
#: mediagoblin/gmg_commands/theme.py:58
msgid "Cannot link theme... no theme set\n"
@@ -242,7 +249,7 @@ msgid "However, old link directory symlink found; removed.\n"
msgstr "Trotzdem wurde eine alte Verknüpfung gefunden; sie wurde entfernt\n"
#: mediagoblin/media_types/__init__.py:60
-#: mediagoblin/media_types/__init__.py:120
+#: mediagoblin/media_types/__init__.py:101
msgid "Sorry, I don't support that file type :("
msgstr "Entschuldigung, dieser Dateityp wird nicht unterstützt."
@@ -252,41 +259,41 @@ msgstr "Videokonvertierung fehlgeschlagen"
#: mediagoblin/plugins/oauth/forms.py:26
msgid "Client ID"
-msgstr ""
+msgstr "Client-ID"
#: mediagoblin/plugins/oauth/forms.py:28
msgid "Next URL"
-msgstr ""
+msgstr "Nächste URL"
#: mediagoblin/plugins/oauth/forms.py:30
msgid "Allow"
-msgstr ""
+msgstr "Erlauben"
#: mediagoblin/plugins/oauth/forms.py:31
msgid "Deny"
-msgstr ""
+msgstr "Verweigern"
#: mediagoblin/plugins/oauth/forms.py:35
msgid "Name"
-msgstr ""
+msgstr "Name"
#: mediagoblin/plugins/oauth/forms.py:36
msgid "The name of the OAuth client"
-msgstr ""
+msgstr "Der Name des OAuth-Clients"
#: mediagoblin/plugins/oauth/forms.py:37
msgid "Description"
-msgstr ""
+msgstr "Beschreibung"
#: mediagoblin/plugins/oauth/forms.py:39
msgid ""
"This will be visible to users allowing your\n"
" application to authenticate as them."
-msgstr ""
+msgstr "Dies wird für Benutzer sichtbar sein, die deiner\nAnwendung erlauben, sich als sie zu authentifizieren.."
#: mediagoblin/plugins/oauth/forms.py:41
msgid "Type"
-msgstr ""
+msgstr "Typ"
#: mediagoblin/plugins/oauth/forms.py:46
msgid ""
@@ -296,25 +303,25 @@ 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>Vertraulich</strong> - Der Client kann\n Anfragen an die GNU MediaGoblin Instanz stellen, die nicht durch den \n Benutzer-Agent (z.B. serverseitiger Client) unterbunden werden können.<br />\n <strong>Öffentlich</strong> - Der Client kann keine vertraulichen \n Anfragen an die GNU MediaGoblin Instanz stellen (z.B. clientseitiger\n JavaScript Client)."
#: mediagoblin/plugins/oauth/forms.py:53
msgid "Redirect URI"
-msgstr ""
+msgstr "Weiterleitungs-URI"
#: mediagoblin/plugins/oauth/forms.py:55
msgid ""
"The redirect URI for the applications, this field\n"
" is <strong>required</strong> for public clients."
-msgstr ""
+msgstr "Die Weiterleitungs-URI für die Anwendung, dieses Feld\n ist <strong>Pflicht</strong> für öffentliche Clients."
#: mediagoblin/plugins/oauth/forms.py:67
msgid "This field is required for public clients"
-msgstr ""
+msgstr "Dieses Feld ist Pflicht für öffentliche Clients"
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:60
msgid "The client {0} has been registered!"
-msgstr ""
+msgstr "Client {0} wurde registriert!"
#: mediagoblin/processing/__init__.py:138
msgid "Invalid file given for media type."
@@ -330,69 +337,50 @@ msgstr "Du musst eine Datei angeben."
#: mediagoblin/submit/views.py:164
msgid "Woohoo! Submitted!"
-msgstr "Yeeeaaah! Geschafft!"
+msgstr "JAAA! Geschafft!"
#: mediagoblin/submit/views.py:215
#, python-format
msgid "Collection \"%s\" added!"
-msgstr ""
+msgstr "Sammlung \"%s\" hinzugefügt!"
-#: mediagoblin/templates/mediagoblin/404.html:24
-msgid "Image of 404 goblin stressing out"
-msgstr "Bild eines angespannten Goblins"
-
-#: mediagoblin/templates/mediagoblin/404.html:25
-msgid "Oops!"
-msgstr "Hoppla!"
-
-#: mediagoblin/templates/mediagoblin/404.html:26
-msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr "Tut uns Leid, aber unter der angegebenen Adresse gibt es keine Seite!"
-
-#: mediagoblin/templates/mediagoblin/404.html:28
-msgid ""
-"If you're sure the address is correct, maybe the page you're looking for has"
-" been moved or deleted."
-msgstr "Wenn du sicher bist, dass die Adresse stimmt, wurde die Seite eventuell verschoben oder gelöscht."
-
-#: mediagoblin/templates/mediagoblin/base.html:50
+#: mediagoblin/templates/mediagoblin/base.html:48
msgid "MediaGoblin logo"
-msgstr "MediaGoblin-Logo"
+msgstr "MediaGoblin Logo"
-#: mediagoblin/templates/mediagoblin/base.html:60
-msgid "Verify your email!"
-msgstr "Bitte bestätige deine E-Mail-Adresse!"
-
-#: mediagoblin/templates/mediagoblin/base.html:66
-msgid "+ Add media"
-msgstr "+ Medien hinzufügen"
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, 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:67
-msgid "+ Add collection"
-msgstr ""
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
+msgstr "abmelden"
-#: mediagoblin/templates/mediagoblin/base.html:69
-msgid "View your profile"
-msgstr "Dein Profil ansehen"
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
+msgstr "Medien hinzufügen"
-#: mediagoblin/templates/mediagoblin/base.html:70
-msgid "Log out"
-msgstr "Abmelden"
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
+msgstr "Bitte bestätige Deine E-Mail-Adresse!"
-#: mediagoblin/templates/mediagoblin/base.html:75
+#: 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:89
+#: mediagoblin/templates/mediagoblin/base.html:87
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project."
msgstr "Diese Seite setzt das <a href=\"http://gnu.org/\">GNU</a>-Projekt <a href=\"http://mediagoblin.org/\">MediaGoblin</a> ein."
-#: mediagoblin/templates/mediagoblin/base.html:92
+#: mediagoblin/templates/mediagoblin/base.html:90
#, python-format
msgid ""
"Released under the <a "
@@ -400,31 +388,56 @@ msgid ""
"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/root.html:24
+#: mediagoblin/templates/mediagoblin/error.html:24
+msgid "Image of goblin stressing out"
+msgstr "Bild eines gestressten Goblins"
+
+#: mediagoblin/templates/mediagoblin/root.html:25
+msgid "Actions"
+msgstr "Aktionen"
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr " Neues Album erstellen"
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr "Kontoeinstellungen ändern"
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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 "Medienverarbeitung"
+
+#: mediagoblin/templates/mediagoblin/root.html:51
msgid "Explore"
msgstr "Entdecken"
-#: mediagoblin/templates/mediagoblin/root.html:26
+#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Hi there, welcome to this MediaGoblin site!"
msgstr "Hallo du, willkommen auf dieser MediaGoblin-Seite!"
-#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/root.html:55
msgid ""
"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an "
"extraordinarily great piece of media hosting software."
-msgstr "Diese Seite setzt <a href=\"http://mediagoblin.org\">MediaGoblin</a> ein, eine großartige Software für Medienhosting."
+msgstr "Diese Webseite setzt <a href=\"http://mediagoblin.org\">MediaGoblin</a> ein, eine großartige Software für Medienhosting."
-#: mediagoblin/templates/mediagoblin/root.html:29
+#: mediagoblin/templates/mediagoblin/root.html:56
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, zu kommentieren und mehr."
+msgstr "Melde Dich mit Deinem MediaGoblin-Konto an, um eigene Medien hinzuzufügen, andere zu kommentieren und vieles mehr."
-#: mediagoblin/templates/mediagoblin/root.html:31
+#: mediagoblin/templates/mediagoblin/root.html:58
msgid "Don't have one yet? It's easy!"
msgstr "Hast du noch keinen? Das geht ganz einfach!"
-#: mediagoblin/templates/mediagoblin/root.html:32
+#: mediagoblin/templates/mediagoblin/root.html:59
#, python-format
msgid ""
"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
@@ -432,17 +445,10 @@ msgid ""
" <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:40
+#: mediagoblin/templates/mediagoblin/root.html:67
msgid "Most recent media"
msgstr "Neuste Medien"
-#: 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 "Medienverarbeitung"
-
#: mediagoblin/templates/mediagoblin/admin/panel.html:29
msgid ""
"Here you can track the state of media being processed on this instance."
@@ -515,11 +521,11 @@ msgstr "Anmeldevorgang fehlgeschlagen!"
#: mediagoblin/templates/mediagoblin/auth/login.html:44
msgid "Don't have an account yet?"
-msgstr "Hast du noch keines? Es geht ganz einfach!"
+msgstr "Hast du noch keines?"
#: mediagoblin/templates/mediagoblin/auth/login.html:45
msgid "Create one here!"
-msgstr "Registriere dich hier!"
+msgstr "Registriere dich einfach hier!"
#: mediagoblin/templates/mediagoblin/auth/login.html:51
msgid "Forgot your password?"
@@ -528,7 +534,7 @@ msgstr "Passwort vergessen?"
#: mediagoblin/templates/mediagoblin/auth/register.html:28
#: mediagoblin/templates/mediagoblin/auth/register.html:36
msgid "Create an account!"
-msgstr "Neues Konto registrieren!"
+msgstr "Neues Nutzerkonto registrieren!"
#: mediagoblin/templates/mediagoblin/auth/register.html:40
msgid "Create"
@@ -543,38 +549,51 @@ msgid ""
"your web browser:\n"
"\n"
"%(verification_url)s"
-msgstr "Hallo %(username)s,\n\num dein Konto bei GNU MediaGoblin zu aktivieren, musst du folgende Adresse in deinem Webbrowser öffnen:\n\n%(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/edit/attachments.html:23
#: mediagoblin/templates/mediagoblin/edit/attachments.html:35
#, python-format
msgid "Editing attachments for %(media_title)s"
-msgstr ""
+msgstr "Bearbeite Anhänge von %(media_title)s"
-#: 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 bearbeiten"
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:43
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
+msgid "Attachments"
+msgstr "Anhänge"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr "Anhang hinzufügen"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:53
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
msgid "Cancel"
msgstr "Abbrechen"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:43
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
msgid "Save changes"
msgstr "Änderungen speichern"
+#: 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 bearbeiten"
+
#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:41
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
#, python-format
msgid "Changing %(username)s's account settings"
msgstr "%(username)ss Kontoeinstellungen ändern"
@@ -582,7 +601,7 @@ msgstr "%(username)ss Kontoeinstellungen ändern"
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29
#, python-format
msgid "Editing %(collection_title)s"
-msgstr ""
+msgstr "Bearbeite %(collection_title)s"
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:23
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
@@ -600,13 +619,12 @@ 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/image.html:23
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
msgid "Download"
msgstr "Download"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:27
msgid "Original"
msgstr "Original"
@@ -633,6 +651,56 @@ msgstr "Originaldatei"
msgid "WebM file (Vorbis codec)"
msgstr "WebM-Datei (Vorbis-Codec)"
+#: 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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr "Bild für %(media_title)s"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
+msgid "Toggle Rotate"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113
+msgid "Perspective"
+msgstr "Perspektive"
+
+#: 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 ""
+
+#: 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 "Objekthöhe"
+
#: mediagoblin/templates/mediagoblin/media_displays/video.html:40
msgid ""
"Sorry, this video will not work because \n"
@@ -653,11 +721,11 @@ msgstr "WebM-Datei (640p; VP8/Vorbis)"
#: mediagoblin/templates/mediagoblin/submit/collection.html:26
msgid "Add a collection"
-msgstr ""
+msgstr "Eine Sammlung hinzufügen"
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
#: mediagoblin/templates/mediagoblin/submit/start.html:34
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:83
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
msgid "Add"
msgstr "Hinzufügen"
@@ -669,12 +737,12 @@ msgstr "Deine Medien"
#: 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 collection)"
#: 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 by <a href=\"%(user_url)s\">%(username)s</a>"
#: mediagoblin/templates/mediagoblin/user_pages/collection.html:52
#: mediagoblin/templates/mediagoblin/user_pages/media.html:87
@@ -686,14 +754,6 @@ msgstr "Bearbeiten"
msgid "Delete"
msgstr "Löschen"
-#: mediagoblin/templates/mediagoblin/user_pages/collection.html:59
-#, python-format
-msgid ""
-"<p>\n"
-" %(collection_description)s\n"
-" </p>"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
@@ -701,18 +761,18 @@ msgid "Really delete %(title)s?"
msgstr "Möchtest du %(title)s wirklich löschen?"
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "Dauerhaft löschen"
#: 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 "Wirklich %(media_title)s aus %(collection_title)s entfernen?"
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
msgid "Remove"
-msgstr ""
+msgstr "Entfernen"
#: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19
#, python-format
@@ -736,12 +796,6 @@ 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:67
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
-#, python-format
-msgid "Image for %(media_title)s"
-msgstr "Bild für %(media_title)s"
-
#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
msgid "Add a comment"
msgstr "Einen Kommentar schreiben"
@@ -768,32 +822,27 @@ msgid ""
" <p>%(date)s</p>"
msgstr "<h3>Veröffentlicht am</h3>\n <p>%(date)s</p>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
-msgid "Attachments"
-msgstr "Anhänge"
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
-msgid "Add attachment"
-msgstr "Anhang hinzufügen"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
+msgstr "Medien zu einem Album hinzufügen"
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
#, python-format
msgid "Add %(title)s to collection"
-msgstr ""
+msgstr "%(title)s zur Sammlung hinzufügen"
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
msgid "+"
-msgstr ""
+msgstr "+"
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
msgid "Add a new collection"
-msgstr ""
+msgstr "Eine neue Sammlung hinzufügen"
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:29
msgid ""
"You can track the state of media being processed for your gallery here."
-msgstr "Du kannst den Status der Medien, die sich gerade in Bearbeitung befinden, hier betrachten."
+msgstr "Du kannst hier den Status der Medien verfolgen, die sich gerade in Bearbeitung befinden."
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:89
msgid "Your last 10 successful uploads"
@@ -812,7 +861,7 @@ msgstr "Dieser Benutzer konnte leider nicht gefunden werden."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:50
#: mediagoblin/templates/mediagoblin/user_pages/user.html:70
msgid "Email verification needed"
-msgstr "E-Mail-Bestätigung benötigt"
+msgstr "E-Mail Aktivierung benötigt"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:53
msgid "Almost done! Your account still needs to be activated."
@@ -821,15 +870,15 @@ msgstr "Fast fertig! Dein Konto muss noch freigeschaltet werden."
#: 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 "Gleich solltest du eine E-Mail erhalten, die dir erklärt, was du noch machen musst."
+msgstr "Gleich solltest du eine E-Mail erhalten, die beschreibt was noch zu tun bleibt."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:62
msgid "In case it doesn't:"
-msgstr "Wenn sie nicht ankommt:"
+msgstr "Falls sie nicht ankommt:"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:65
msgid "Resend verification email"
-msgstr "Bestätigungs-E-Mail erneut senden"
+msgstr "Aktivierungsmail erneut senden"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:73
msgid ""
@@ -842,11 +891,11 @@ msgstr "Jemand hat bereits ein Konto mit diesem Benutzernamen registriert, aber
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 "Wenn dir dieses Konto gehört und die Bestätigungsmail verloren gegangen ist, kannst du dich <a href=\"%(login_url)s\">anmelden</a> und sie erneut senden."
+msgstr "Wenn dir dieses Konto gehört und die Aktivierungsmail verloren gegangen ist, kannst du dich <a href=\"%(login_url)s\">anmelden</a> und sie erneut senden."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:96
msgid "Here's a spot to tell others about yourself."
-msgstr "Hier kannst du Anderen etwas über dich erzählen."
+msgstr "Hier kannst Du Dich selbst beschreiben."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:101
#: mediagoblin/templates/mediagoblin/user_pages/user.html:118
@@ -857,47 +906,31 @@ msgstr "Profil bearbeiten"
msgid "This user hasn't filled in their profile (yet)."
msgstr "Dieser Benutzer hat (noch) keine Daten in seinem Profil."
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:125
-msgid "Change account settings"
-msgstr "Kontoeinstellungen ändern"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:138
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
#, python-format
msgid "View all of %(username)s's media"
msgstr "Alle Medien von %(username)s anschauen"
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
msgid ""
"This is where your media will appear, but you don't seem to have added "
"anything yet."
msgstr "Hier erscheinen deine Medien, sobald du etwas hochgeladen hast."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:157
-msgid "Add media"
-msgstr "Medien hinzufügen"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:163
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:87
-#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:72
+#: 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 "Scheinbar gibt es hier noch nichts …"
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:39
-#, python-format
-msgid ""
-"<br />\n"
-" <a href=\"%(entry_url)s\">%(note)s</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:47
-#, python-format
-msgid "<br /><a href=\"%(remove_url)s\" class=\"remove\">(remove)</a>"
-msgstr ""
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
+msgstr "(entfernen)"
#: mediagoblin/templates/mediagoblin/utils/collections.html:20
#, python-format
msgid "In collections (%(collected)s)"
-msgstr ""
+msgstr "In den Sammlungen (%(collected)s)"
#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
msgid "feed icon"
@@ -911,7 +944,7 @@ msgstr "Atom-Feed"
msgid "Location"
msgstr "Aufnahmeort"
-#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:38
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
#, python-format
msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
msgstr "In <a href=\"%(osm_url)s\">OpenStreetMap</a> öffnen"
@@ -950,94 +983,120 @@ msgstr "Schlagwörter"
msgid "Could not read the image file."
msgstr "Die Bilddatei konnte nicht gelesen werden."
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr "Hoppla!"
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr "Ein Fehler trat auf"
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr "Funktion nicht erlaubt"
+
+#: mediagoblin/tools/response.py:47
+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 "So nicht!</p><p>Du wolltest eine Funktion verwenden zu der Du nicht die nötigen Rechte Rechte besitzt. Wolltest Du etwa schon wieder alle Nutzerkonten löschen?"
+
+#: mediagoblin/tools/response.py:55
+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 "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/user_pages/forms.py:28
msgid "I am sure I want to delete this"
msgstr "Ja, wirklich löschen"
#: mediagoblin/user_pages/forms.py:32
msgid "I am sure I want to remove this item from the collection"
-msgstr ""
+msgstr "Ich bin sicher, dass ich dieses Objekt aus der Sammlung entfernen möchte"
#: mediagoblin/user_pages/forms.py:35
msgid "-- Select --"
-msgstr ""
+msgstr "-- Auswählen --"
#: mediagoblin/user_pages/forms.py:37
msgid "Include a note"
-msgstr ""
+msgstr "Notiz anfügen"
#: mediagoblin/user_pages/lib.py:56
msgid "commented on your post"
msgstr "hat dein Medium kommentiert"
-#: mediagoblin/user_pages/views.py:161
+#: mediagoblin/user_pages/views.py:156
msgid "Oops, your comment was empty."
-msgstr "Ohh, der Kommentar war leer."
+msgstr "Hoppla, der Kommentartext fehlte."
-#: mediagoblin/user_pages/views.py:167
+#: mediagoblin/user_pages/views.py:162
msgid "Your comment has been posted!"
-msgstr "Dein Kommentar wurde gesendet!"
+msgstr "Dein Kommentar wurde angenommen!"
-#: mediagoblin/user_pages/views.py:235
+#: mediagoblin/user_pages/views.py:230
msgid "You have to select or add a collection"
-msgstr ""
+msgstr "Du musst eine Sammlung auswählen oder hinzufügen"
-#: mediagoblin/user_pages/views.py:243
+#: mediagoblin/user_pages/views.py:238
#, python-format
msgid "\"%s\" already in collection \"%s\""
-msgstr ""
+msgstr "\"%s\" ist bereits in der Sammlung \"%s\""
-#: mediagoblin/user_pages/views.py:258
+#: mediagoblin/user_pages/views.py:253
#, python-format
msgid "\"%s\" added to collection \"%s\""
-msgstr ""
+msgstr "\"%s\" zur Sammlung \"%s\" hinzugefügt"
-#: mediagoblin/user_pages/views.py:266
+#: mediagoblin/user_pages/views.py:261
msgid "Please check your entries and try again."
-msgstr ""
+msgstr "Bitte prüfe deinen Einträge und versuche erneut."
-#: mediagoblin/user_pages/views.py:297
+#: mediagoblin/user_pages/views.py:292
msgid ""
"Some of the files with this entry seem to be missing. Deleting anyway."
msgstr "Manche Dateien dieses Eintrags scheinen zu fehlen. Es wird trotzdem gelöscht."
-#: mediagoblin/user_pages/views.py:302
+#: mediagoblin/user_pages/views.py:297
msgid "You deleted the media."
msgstr "Du hast das Medium gelöscht."
-#: mediagoblin/user_pages/views.py:309
+#: mediagoblin/user_pages/views.py:304
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:317
+#: mediagoblin/user_pages/views.py:312
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:379
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
-msgstr ""
+msgstr "Du hast das Objekt aus der Sammlung gelöscht."
-#: mediagoblin/user_pages/views.py:383
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
-msgstr ""
+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:393
+#: mediagoblin/user_pages/views.py:384
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
-msgstr ""
+msgstr "Du bist dabei ein Objekt aus der Sammlung eines anderen Nutzers zu entfernen. Sei vorsichtig."
-#: mediagoblin/user_pages/views.py:426
+#: mediagoblin/user_pages/views.py:417
#, python-format
msgid "You deleted the collection \"%s\""
-msgstr ""
+msgstr "Du hast die Sammlung \"%s\" gelöscht"
-#: mediagoblin/user_pages/views.py:433
+#: mediagoblin/user_pages/views.py:424
msgid ""
"The collection was not deleted because you didn't check that you were sure."
-msgstr ""
+msgstr "Die Sammlung wurde nicht gelöscht, weil du nicht bestätigt hast, dass du dir sicher bist."
-#: mediagoblin/user_pages/views.py:443
+#: mediagoblin/user_pages/views.py:434
msgid ""
"You are about to delete another user's collection. Proceed with caution."
-msgstr ""
+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 3e589f71..3ac01f5a 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: 2012-09-24 14:01-0500\n"
+"POT-Creation-Date: 2012-12-20 10:11-0600\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"
@@ -89,7 +89,7 @@ msgstr ""
msgid "You can now log in using your new password."
msgstr ""
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:83
+#: 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:40
msgid "Title"
@@ -100,7 +100,7 @@ msgid "Description of this work"
msgstr ""
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:87 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:44
msgid ""
"You can use\n"
@@ -117,11 +117,11 @@ msgstr ""
msgid "Separate tags by commas."
msgstr ""
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:91
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr ""
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:92
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr ""
@@ -160,20 +160,20 @@ msgstr ""
msgid "New password"
msgstr ""
-#: mediagoblin/edit/forms.py:72
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr ""
-#: mediagoblin/edit/forms.py:84
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:43
msgid "Description of this collection"
msgstr ""
-#: mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
@@ -187,33 +187,38 @@ msgstr ""
msgid "You are editing another user's media. Proceed with caution."
msgstr ""
-#: mediagoblin/edit/views.py:182
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr ""
+
+#: mediagoblin/edit/views.py:181
msgid "You are editing a user's profile. Proceed with caution."
msgstr ""
-#: mediagoblin/edit/views.py:198
+#: mediagoblin/edit/views.py:197
msgid "Profile changes saved"
msgstr ""
-#: mediagoblin/edit/views.py:227 mediagoblin/edit/views.py:247
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
msgid "Account settings saved"
msgstr ""
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:251
msgid "Wrong password"
msgstr ""
-#: mediagoblin/edit/views.py:288 mediagoblin/submit/views.py:211
-#: mediagoblin/user_pages/views.py:215
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr ""
-#: mediagoblin/edit/views.py:292
+#: mediagoblin/edit/views.py:291
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:309
+#: mediagoblin/edit/views.py:308
msgid "You are editing another user's collection. Proceed with caution."
msgstr ""
@@ -230,7 +235,7 @@ msgid "However, old link directory symlink found; removed.\n"
msgstr ""
#: mediagoblin/media_types/__init__.py:60
-#: mediagoblin/media_types/__init__.py:120
+#: mediagoblin/media_types/__init__.py:101
msgid "Sorry, I don't support that file type :("
msgstr ""
@@ -304,7 +309,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:60
msgid "The client {0} has been registered!"
msgstr ""
@@ -329,62 +334,43 @@ msgstr ""
msgid "Collection \"%s\" added!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/404.html:24
-msgid "Image of 404 goblin stressing out"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/404.html:25
-msgid "Oops!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/404.html:26
-msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/404.html:28
-msgid ""
-"If you're sure the address is correct, maybe the page you're looking for "
-"has been moved or deleted."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:50
+#: mediagoblin/templates/mediagoblin/base.html:48
msgid "MediaGoblin logo"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:60
-msgid "Verify your email!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:66
-msgid "+ Add media"
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:67
-msgid "+ Add collection"
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:69
-msgid "View your profile"
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:70
-msgid "Log out"
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:75
+#: 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:89
+#: mediagoblin/templates/mediagoblin/base.html:87
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project."
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:92
+#: mediagoblin/templates/mediagoblin/base.html:90
#, python-format
msgid ""
"Released under the <a "
@@ -392,31 +378,56 @@ msgid ""
" href=\"%(source_link)s\">Source code</a> available."
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:24
+#: mediagoblin/templates/mediagoblin/error.html:24
+msgid "Image of goblin stressing out"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:25
+msgid "Actions"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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/root.html:51
msgid "Explore"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:26
+#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Hi there, welcome to this MediaGoblin site!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/root.html:55
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:29
+#: mediagoblin/templates/mediagoblin/root.html:56
msgid ""
"To add your own media, place comments, and more, you can log in with your"
" MediaGoblin account."
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:31
+#: mediagoblin/templates/mediagoblin/root.html:58
msgid "Don't have one yet? It's easy!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:32
+#: mediagoblin/templates/mediagoblin/root.html:59
#, python-format
msgid ""
"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an "
@@ -427,17 +438,10 @@ msgid ""
"your own server</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:40
+#: mediagoblin/templates/mediagoblin/root.html:67
msgid "Most recent media"
msgstr ""
-#: 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/admin/panel.html:29
msgid "Here you can track the state of media being processed on this instance."
msgstr ""
@@ -545,30 +549,43 @@ msgstr ""
msgid "Editing attachments for %(media_title)s"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit.html:23
-#: mediagoblin/templates/mediagoblin/edit/edit.html:35
-#, python-format
-msgid "Editing %(media_title)s"
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:43
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
+msgid "Attachments"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:53
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
msgid "Cancel"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit.html:43
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
msgid "Save changes"
msgstr ""
+#: mediagoblin/templates/mediagoblin/edit/edit.html:23
+#: mediagoblin/templates/mediagoblin/edit/edit.html:35
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:41
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
#, python-format
msgid "Changing %(username)s's account settings"
msgstr ""
@@ -594,13 +611,12 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:23
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
msgid "Download"
msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:27
msgid "Original"
msgstr ""
@@ -627,6 +643,56 @@ msgstr ""
msgid "WebM file (Vorbis codec)"
msgstr ""
+#: 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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr ""
+
+#: 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 ""
+
+#: 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:40
msgid ""
"Sorry, this video will not work because \n"
@@ -651,7 +717,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
#: mediagoblin/templates/mediagoblin/submit/start.html:34
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:83
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
msgid "Add"
msgstr ""
@@ -680,14 +746,6 @@ msgstr ""
msgid "Delete"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection.html:59
-#, python-format
-msgid ""
-"<p>\n"
-" %(collection_description)s\n"
-" </p>"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
@@ -695,7 +753,7 @@ msgid "Really delete %(title)s?"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr ""
@@ -704,7 +762,7 @@ msgstr ""
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
msgid "Remove"
msgstr ""
@@ -731,12 +789,6 @@ msgstr ""
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:67
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
-#, python-format
-msgid "Image for %(media_title)s"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
msgid "Add a comment"
msgstr ""
@@ -763,13 +815,8 @@ msgid ""
" <p>%(date)s</p>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
-msgid "Attachments"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
-msgid "Add attachment"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
@@ -777,11 +824,11 @@ msgstr ""
msgid "Add %(title)s to collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
msgid "+"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
msgid "Add a new collection"
msgstr ""
@@ -850,41 +897,25 @@ msgstr ""
msgid "This user hasn't filled in their profile (yet)."
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:125
-msgid "Change account settings"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:138
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
#, python-format
msgid "View all of %(username)s's media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
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:157
-msgid "Add media"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:163
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:87
-#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:72
+#: 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:39
-#, python-format
-msgid ""
-"<br />\n"
-" <a href=\"%(entry_url)s\">%(note)s</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:47
-#, python-format
-msgid "<br /><a href=\"%(remove_url)s\" class=\"remove\">(remove)</a>"
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
msgstr ""
#: mediagoblin/templates/mediagoblin/utils/collections.html:20
@@ -904,7 +935,7 @@ msgstr ""
msgid "Location"
msgstr ""
-#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:38
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
#, python-format
msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
msgstr ""
@@ -943,6 +974,32 @@ msgstr ""
msgid "Could not read the image file."
msgstr ""
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr ""
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr ""
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr ""
+
+#: mediagoblin/tools/response.py:47
+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:55
+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/user_pages/forms.py:28
msgid "I am sure I want to delete this"
msgstr ""
@@ -963,74 +1020,74 @@ msgstr ""
msgid "commented on your post"
msgstr ""
-#: mediagoblin/user_pages/views.py:161
+#: mediagoblin/user_pages/views.py:156
msgid "Oops, your comment was empty."
msgstr ""
-#: mediagoblin/user_pages/views.py:167
+#: mediagoblin/user_pages/views.py:162
msgid "Your comment has been posted!"
msgstr ""
-#: mediagoblin/user_pages/views.py:235
+#: mediagoblin/user_pages/views.py:230
msgid "You have to select or add a collection"
msgstr ""
-#: mediagoblin/user_pages/views.py:243
+#: mediagoblin/user_pages/views.py:238
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:258
+#: mediagoblin/user_pages/views.py:253
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:266
+#: mediagoblin/user_pages/views.py:261
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:297
+#: mediagoblin/user_pages/views.py:292
msgid "Some of the files with this entry seem to be missing. Deleting anyway."
msgstr ""
-#: mediagoblin/user_pages/views.py:302
+#: mediagoblin/user_pages/views.py:297
msgid "You deleted the media."
msgstr ""
-#: mediagoblin/user_pages/views.py:309
+#: mediagoblin/user_pages/views.py:304
msgid "The media was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:317
+#: mediagoblin/user_pages/views.py:312
msgid "You are about to delete another user's media. Proceed with caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr ""
-#: mediagoblin/user_pages/views.py:383
+#: 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:393
+#: mediagoblin/user_pages/views.py:384
msgid ""
"You are about to delete an item from another user's collection. Proceed "
"with caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:426
+#: mediagoblin/user_pages/views.py:417
#, python-format
msgid "You deleted the collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:433
+#: mediagoblin/user_pages/views.py:424
msgid ""
"The collection was not deleted because you didn't check that you were "
"sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:443
+#: mediagoblin/user_pages/views.py:434
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 dbd2bc4d..28500ceb 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 2bfb4319..3b1dce48 100644
--- a/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.po
@@ -10,9 +10,9 @@ msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2012-09-24 11:41-0500\n"
-"PO-Revision-Date: 2012-09-24 18:27+0000\n"
-"Last-Translator: aleksejrs <deletesoftware@yandex.ru>\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 15:14+0000\n"
+"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -94,7 +94,7 @@ msgstr "Mi trovis neniun kun tiu salutnomo aÅ­ retpoÅtadreso."
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:83
+#: 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:40
msgid "Title"
@@ -105,7 +105,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:87 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:44
msgid ""
"You can use\n"
@@ -121,11 +121,11 @@ msgstr "Etikedoj"
msgid "Separate tags by commas."
msgstr "Dividu la etikedojn per komoj."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:91
+#: 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:92
+#: 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"
@@ -164,20 +164,20 @@ msgstr "Enigu vian malnovan pasvorton por pruvi, ke ĉi tiu konto estas via."
msgid "New password"
msgstr "La nova pasvorto"
-#: mediagoblin/edit/forms.py:72
+#: 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:84
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:43
msgid "Description of this collection"
-msgstr "Priskribo de ĉi tiu kolekto"
+msgstr "Priskribo de la kolekto"
-#: mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
@@ -191,34 +191,40 @@ msgstr "Ĉi tiu uzanto jam havas dosieron kun tiu distingiga adresparto."
msgid "You are editing another user's media. Proceed with caution."
msgstr "Vi priredaktas dosieron de alia uzanto. Agu singardeme."
-#: mediagoblin/edit/views.py:182
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr ""
+
+#: mediagoblin/edit/views.py:181
msgid "You are editing a user's profile. Proceed with caution."
msgstr "Vi redaktas profilon de alia uzanto. Agu singardeme."
-#: mediagoblin/edit/views.py:198
+#: mediagoblin/edit/views.py:197
msgid "Profile changes saved"
msgstr "ProfilÅanÄoj estis konservitaj"
-#: mediagoblin/edit/views.py:227 mediagoblin/edit/views.py:247
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
msgid "Account settings saved"
msgstr "Kontagordoj estis konservitaj"
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:251
msgid "Wrong password"
msgstr "MalÄusta pasvorto"
-#: mediagoblin/edit/views.py:287
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
#, python-format
-msgid "You already have a collection called \"%s\"!title"
-msgstr "Vi jam havas kolekton kun la nomo «%s»!title"
+msgid "You already have a collection called \"%s\"!"
+msgstr "Vi jam havas kolekton kun la nomo «%s»!"
-#: mediagoblin/edit/views.py:290
+#: mediagoblin/edit/views.py:291
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:307
+#: mediagoblin/edit/views.py:308
msgid "You are editing another user's collection. Proceed with caution."
-msgstr ""
+msgstr "Vi redaktas kolekton de alia uzanto. Agu singardeme."
#: mediagoblin/gmg_commands/theme.py:58
msgid "Cannot link theme... no theme set\n"
@@ -233,7 +239,7 @@ msgid "However, old link directory symlink found; removed.\n"
msgstr "Tamen trovitas — kaj forigitas — malnova simbola ligilo al dosierujo.\n"
#: mediagoblin/media_types/__init__.py:60
-#: mediagoblin/media_types/__init__.py:120
+#: mediagoblin/media_types/__init__.py:101
msgid "Sorry, I don't support that file type :("
msgstr "Mi pardonpetas, mi ne subtenas tiun dosiertipon :("
@@ -303,7 +309,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:60
msgid "The client {0} has been registered!"
msgstr ""
@@ -323,72 +329,48 @@ msgstr "Vi devas provizi dosieron."
msgid "Woohoo! Submitted!"
msgstr "Hura! AlÅutitas!"
-#: mediagoblin/submit/views.py:211 mediagoblin/user_pages/views.py:215
-#, python-format
-msgid "You already have a collection called \"%s\"!"
-msgstr ""
-
#: mediagoblin/submit/views.py:215
#, python-format
msgid "Collection \"%s\" added!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/404.html:24
-msgid "Image of 404 goblin stressing out"
-msgstr "Bildo de 404-koboldo penÅvitanta."
+msgstr "Kolekto «%s» aldonitas!"
-#: mediagoblin/templates/mediagoblin/404.html:25
-msgid "Oops!"
-msgstr "Oj!"
-
-#: mediagoblin/templates/mediagoblin/404.html:26
-msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr "VerÅajne ĉe ĉi tiu adreso ne estas paÄo. Ni bedaÅ­ras!"
-
-#: mediagoblin/templates/mediagoblin/404.html:28
-msgid ""
-"If you're sure the address is correct, maybe the page you're looking for has"
-" been moved or deleted."
-msgstr "Se vi estas certa, ke la adreso estas Äusta, eble la serĉata de vi paÄo estis movita aÅ­ forigita."
-
-#: mediagoblin/templates/mediagoblin/base.html:50
+#: mediagoblin/templates/mediagoblin/base.html:48
msgid "MediaGoblin logo"
msgstr "Emblemo de MediaGoblin"
-#: mediagoblin/templates/mediagoblin/base.html:60
-msgid "Verify your email!"
-msgstr "Konfirmu viecon de la retpoÅtadreso!"
-
-#: mediagoblin/templates/mediagoblin/base.html:66
-msgid "+ Add media"
-msgstr "+ Aldoni dosieron"
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
+msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:67
-msgid "+ Add collection"
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:69
-msgid "View your profile"
-msgstr "Vidi vian profilon"
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
+msgstr "Aldoni dosieron"
-#: mediagoblin/templates/mediagoblin/base.html:70
-msgid "Log out"
-msgstr "Elsaluti"
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
+msgstr "Konfirmu viecon de la retpoÅtadreso!"
-#: mediagoblin/templates/mediagoblin/base.html:75
+#: 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:89
+#: mediagoblin/templates/mediagoblin/base.html:87
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project."
msgstr "Funkcias per <a href=\"http://mediagoblin.org\">MediaGoblin</a>, unu el la <a href=\"http://gnu.org/\">projektoj de GNU</a>."
-#: mediagoblin/templates/mediagoblin/base.html:92
+#: mediagoblin/templates/mediagoblin/base.html:90
#, python-format
msgid ""
"Released under the <a "
@@ -396,31 +378,56 @@ msgid ""
"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/root.html:24
+#: mediagoblin/templates/mediagoblin/error.html:24
+msgid "Image of goblin stressing out"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:25
+msgid "Actions"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr "ÅœanÄi kontagordojn"
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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 "Kontrolejo pri dosierpreparado."
+
+#: mediagoblin/templates/mediagoblin/root.html:51
msgid "Explore"
msgstr "Ĉirkaŭrigardi"
-#: mediagoblin/templates/mediagoblin/root.html:26
+#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Hi there, welcome to this MediaGoblin site!"
msgstr "Saluton, kaj bonvenon al ĉi tiu MediaGoblina retpaÄaro!"
-#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/root.html:55
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:29
+#: mediagoblin/templates/mediagoblin/root.html:56
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:31
+#: mediagoblin/templates/mediagoblin/root.html:58
msgid "Don't have one yet? It's easy!"
msgstr "Ĉu vi ankoraÅ­ ne havas tian? Ne malÄoju!"
-#: mediagoblin/templates/mediagoblin/root.html:32
+#: mediagoblin/templates/mediagoblin/root.html:59
#, python-format
msgid ""
"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
@@ -428,17 +435,10 @@ msgid ""
" <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:40
+#: mediagoblin/templates/mediagoblin/root.html:67
msgid "Most recent media"
msgstr "Laste aldonitaj dosieroj"
-#: 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 "Kontrolejo pri dosierpreparado."
-
#: mediagoblin/templates/mediagoblin/admin/panel.html:29
msgid ""
"Here you can track the state of media being processed on this instance."
@@ -547,30 +547,43 @@ msgstr "Sal %(username)s,\n\npor aktivigi vian GNU MediaGoblin konton, malfermu
msgid "Editing attachments for %(media_title)s"
msgstr "Aldoni kundosierojn por %(media_title)s"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:23
-#: mediagoblin/templates/mediagoblin/edit/edit.html:35
-#, python-format
-msgid "Editing %(media_title)s"
-msgstr "Priredaktado de %(media_title)s"
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:43
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
+msgid "Attachments"
+msgstr "Kundosieroj"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr "Aldoni kundosieron"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:53
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
msgid "Cancel"
msgstr "Nuligi"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:43
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
msgid "Save changes"
msgstr "Konservi ÅanÄojn"
+#: mediagoblin/templates/mediagoblin/edit/edit.html:23
+#: mediagoblin/templates/mediagoblin/edit/edit.html:35
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "Priredaktado de %(media_title)s"
+
#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:41
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
#, python-format
msgid "Changing %(username)s's account settings"
msgstr "ÅœanÄado de kontagordoj de %(username)s"
@@ -596,13 +609,12 @@ 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/image.html:23
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
msgid "Download"
msgstr "ElÅuti"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:27
msgid "Original"
msgstr "Originalo"
@@ -629,6 +641,56 @@ msgstr "originalan dosieron"
msgid "WebM file (Vorbis codec)"
msgstr "WebMan dosieron (kun Vorbisa kodaĵo)"
+#: 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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr "Bildo de «%(media_title)s»"
+
+#: 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 ""
+
+#: 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:40
msgid ""
"Sorry, this video will not work because \n"
@@ -649,11 +711,11 @@ msgstr "la WebM-dosieron (640p; VP8/Vorbis)"
#: mediagoblin/templates/mediagoblin/submit/collection.html:26
msgid "Add a collection"
-msgstr ""
+msgstr "Aldonado de kolekto"
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
#: mediagoblin/templates/mediagoblin/submit/start.html:34
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:83
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
msgid "Add"
msgstr "Aldoni"
@@ -665,12 +727,12 @@ msgstr "Aldono de via dosiero"
#: mediagoblin/templates/mediagoblin/user_pages/collection.html:30
#, python-format
msgid "%(collection_title)s (%(username)s's collection)"
-msgstr ""
+msgstr "%(collection_title)s (kolekto de %(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 ""
+msgstr "%(collection_title)s de <a href=\"%(user_url)s\">%(username)s</a>"
#: mediagoblin/templates/mediagoblin/user_pages/collection.html:52
#: mediagoblin/templates/mediagoblin/user_pages/media.html:87
@@ -682,14 +744,6 @@ msgstr "ÅœanÄi"
msgid "Delete"
msgstr "Forigi"
-#: mediagoblin/templates/mediagoblin/user_pages/collection.html:59
-#, python-format
-msgid ""
-"<p>\n"
-" %(collection_description)s\n"
-" </p>"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
@@ -697,18 +751,18 @@ msgid "Really delete %(title)s?"
msgstr "Ĉu vere forigi %(title)s?"
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "Forigi senrevene"
#: 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 "Ĉu vere forigi %(media_title)s el %(collection_title)s?"
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
msgid "Remove"
-msgstr ""
+msgstr "Forigi"
#: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19
#, python-format
@@ -732,12 +786,6 @@ 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:67
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
-#, python-format
-msgid "Image for %(media_title)s"
-msgstr "Bildo de «%(media_title)s»"
-
#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
msgid "Add a comment"
msgstr "Aldoni komenton"
@@ -764,27 +812,22 @@ msgid ""
" <p>%(date)s</p>"
msgstr "<h3>Aldonita je</h3>\n <p>la %(date)s</p>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
-msgid "Attachments"
-msgstr "Kundosieroj"
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
-msgid "Add attachment"
-msgstr "Aldoni kundosieron"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
+msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
#, python-format
msgid "Add %(title)s to collection"
-msgstr ""
+msgstr "Aldonado de %(title)s al kolekto"
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
msgid "+"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
msgid "Add a new collection"
-msgstr ""
+msgstr "Aldoni novan kolekton"
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:29
msgid ""
@@ -853,47 +896,31 @@ msgstr "Redakti profilon"
msgid "This user hasn't filled in their profile (yet)."
msgstr "Ĉi tiu uzanto ne jam aldonis informojn pri si."
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:125
-msgid "Change account settings"
-msgstr "ÅœanÄi kontagordojn"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:138
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
#, python-format
msgid "View all of %(username)s's media"
msgstr "Rigardi ĉiujn dosierojn de %(username)s"
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
msgid ""
"This is where your media will appear, but you don't seem to have added "
"anything yet."
msgstr "Äœuste ĉi tie aperos viaj dosieroj, sed vi Åajne ankoraÅ­ nenion alÅutis."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:157
-msgid "Add media"
-msgstr "Aldoni dosieron"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:163
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:87
-#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:72
+#: 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 "Ĉi tie Åajne estas ankoraÅ­ neniuj dosieroj…"
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:39
-#, python-format
-msgid ""
-"<br />\n"
-" <a href=\"%(entry_url)s\">%(note)s</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:47
-#, python-format
-msgid "<br /><a href=\"%(remove_url)s\" class=\"remove\">(remove)</a>"
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
msgstr ""
#: mediagoblin/templates/mediagoblin/utils/collections.html:20
#, python-format
msgid "In collections (%(collected)s)"
-msgstr ""
+msgstr "En %(collected)s kolekto(j)"
#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
msgid "feed icon"
@@ -907,7 +934,7 @@ msgstr "Atom-a informfluo"
msgid "Location"
msgstr "Loko"
-#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:38
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
#, python-format
msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
msgstr "Vidi sur <a href=\"%(osm_url)s\">OpenStreetMap</a>"
@@ -946,94 +973,120 @@ msgstr "Markita per"
msgid "Could not read the image file."
msgstr "Malsukcesis lego de la bildodosiero"
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr "Oj!"
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr ""
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr ""
+
+#: mediagoblin/tools/response.py:47
+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:55
+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/user_pages/forms.py:28
msgid "I am sure I want to delete this"
msgstr "Jes, mi volas forigi ĉi tion."
#: mediagoblin/user_pages/forms.py:32
msgid "I am sure I want to remove this item from the collection"
-msgstr ""
+msgstr "Jes, mi volas forigi ĉi tiun dosieron el la kolekto"
#: mediagoblin/user_pages/forms.py:35
msgid "-- Select --"
-msgstr ""
+msgstr "-- Elektu --"
#: mediagoblin/user_pages/forms.py:37
msgid "Include a note"
-msgstr ""
+msgstr "Rimarko"
#: mediagoblin/user_pages/lib.py:56
msgid "commented on your post"
msgstr "komentis je via afiÅo"
-#: mediagoblin/user_pages/views.py:161
+#: mediagoblin/user_pages/views.py:156
msgid "Oops, your comment was empty."
msgstr "Oj, via komento estis malplena."
-#: mediagoblin/user_pages/views.py:167
+#: mediagoblin/user_pages/views.py:162
msgid "Your comment has been posted!"
msgstr "Via komento estis afiÅita!"
-#: mediagoblin/user_pages/views.py:235
+#: mediagoblin/user_pages/views.py:230
msgid "You have to select or add a collection"
-msgstr ""
+msgstr "Necesas elekti aÅ­ aldoni kolekton"
-#: mediagoblin/user_pages/views.py:243
+#: mediagoblin/user_pages/views.py:238
#, python-format
msgid "\"%s\" already in collection \"%s\""
-msgstr ""
+msgstr "«%s» jam estas en la kolekto «%s»"
-#: mediagoblin/user_pages/views.py:258
+#: mediagoblin/user_pages/views.py:253
#, python-format
msgid "\"%s\" added to collection \"%s\""
-msgstr ""
+msgstr "«%s» estis aldonita al la kolekto «%s»"
-#: mediagoblin/user_pages/views.py:266
+#: mediagoblin/user_pages/views.py:261
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:297
+#: mediagoblin/user_pages/views.py:292
msgid ""
"Some of the files with this entry seem to be missing. Deleting anyway."
msgstr "Iuj dosieroj de ĉi tiu ero Åajne mankas. Mi tamen forigas."
-#: mediagoblin/user_pages/views.py:302
+#: mediagoblin/user_pages/views.py:297
msgid "You deleted the media."
msgstr "Vi forigis la dosieron."
-#: mediagoblin/user_pages/views.py:309
+#: mediagoblin/user_pages/views.py:304
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:317
+#: mediagoblin/user_pages/views.py:312
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:379
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
-msgstr ""
+msgstr "Vi forigis la dosieron el la kolekto."
-#: mediagoblin/user_pages/views.py:383
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
-msgstr ""
+msgstr "La dosiero ne estis forigita, ĉar vi ne konfirmis vian certecon per la markilo."
-#: mediagoblin/user_pages/views.py:393
+#: mediagoblin/user_pages/views.py:384
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
-msgstr ""
+msgstr "Vi estas forigonta dosieron el kolekto de alia uzanto. Agu singardeme."
-#: mediagoblin/user_pages/views.py:426
+#: mediagoblin/user_pages/views.py:417
#, python-format
msgid "You deleted the collection \"%s\""
-msgstr ""
+msgstr "Vi forigis la kolekton «%s»"
-#: mediagoblin/user_pages/views.py:433
+#: mediagoblin/user_pages/views.py:424
msgid ""
"The collection was not deleted because you didn't check that you were sure."
-msgstr ""
+msgstr "La kolekto ne estis forigita, ĉar vi ne konfirmis vian certecon per la markilo."
-#: mediagoblin/user_pages/views.py:443
+#: mediagoblin/user_pages/views.py:434
msgid ""
"You are about to delete another user's collection. Proceed with caution."
-msgstr ""
+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 b06a995e..98dbebdd 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 1429f887..e1249591 100644
--- a/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.po
@@ -18,9 +18,9 @@ msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2012-09-24 11:41-0500\n"
-"PO-Revision-Date: 2012-09-24 17:10+0000\n"
-"Last-Translator: Elesa <stardustprincess17@hotmail.com>\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 15:14+0000\n"
+"Last-Translator: cwebber <cwebber@dustycloud.org>\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"
@@ -102,7 +102,7 @@ msgstr "No se pudo encontrar a alguien con ese nombre de usuario o correo electr
msgid "You can now log in using your new password."
msgstr "Ahora tu puedes entrar usando tu nueva contraseña."
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:83
+#: 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:40
msgid "Title"
@@ -113,7 +113,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:87 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:44
msgid ""
"You can use\n"
@@ -129,11 +129,11 @@ msgstr "Etiquetas"
msgid "Separate tags by commas."
msgstr "Separa las etiquetas por comas."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:91
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "Ficha"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:92
+#: 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"
@@ -172,20 +172,20 @@ msgstr "Escriba la anterior contraseña para demostrar que esta cuenta te perten
msgid "New password"
msgstr "Nueva contraseña"
-#: mediagoblin/edit/forms.py:72
+#: 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:84
+#: 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:86 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:43
msgid "Description of this collection"
msgstr "Descripción de esta colección"
-#: mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
@@ -199,32 +199,38 @@ msgstr "Una entrada con esa ficha ya existe para este usuario."
msgid "You are editing another user's media. Proceed with caution."
msgstr "Estás editando el contenido de otro usuario. Proceder con precaución."
-#: mediagoblin/edit/views.py:182
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr "¡Has añadido el adjunto %s!"
+
+#: mediagoblin/edit/views.py:181
msgid "You are editing a user's profile. Proceed with caution."
msgstr "Estás editando un perfil de usuario. Proceder con precaución."
-#: mediagoblin/edit/views.py:198
+#: mediagoblin/edit/views.py:197
msgid "Profile changes saved"
msgstr "Los cambios de perfil fueron salvados"
-#: mediagoblin/edit/views.py:227 mediagoblin/edit/views.py:247
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
msgid "Account settings saved"
msgstr "las configuraciones de cuenta fueron salvadas"
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:251
msgid "Wrong password"
msgstr "Contraseña incorrecta"
-#: mediagoblin/edit/views.py:287
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
#, python-format
-msgid "You already have a collection called \"%s\"!title"
-msgstr "Ya tienes una colección llamada \"%s\"!title"
+msgid "You already have a collection called \"%s\"!"
+msgstr "¡Ya tienes una colección llamada \"%s\"!"
-#: mediagoblin/edit/views.py:290
+#: mediagoblin/edit/views.py:291
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:307
+#: mediagoblin/edit/views.py:308
msgid "You are editing another user's collection. Proceed with caution."
msgstr "Estás editando la colección de otro usuario/a. Ten cuidado."
@@ -241,7 +247,7 @@ 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/media_types/__init__.py:60
-#: mediagoblin/media_types/__init__.py:120
+#: mediagoblin/media_types/__init__.py:101
msgid "Sorry, I don't support that file type :("
msgstr "Lo sentidos, No soportamos ese tipo de archivo :("
@@ -311,7 +317,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:60
msgid "The client {0} has been registered!"
msgstr "¡El cliente {0} ha sido registrado!"
@@ -331,72 +337,48 @@ msgstr "Debes proporcionar un archivo."
msgid "Woohoo! Submitted!"
msgstr "¡Yujú! ¡Enviado!"
-#: mediagoblin/submit/views.py:211 mediagoblin/user_pages/views.py:215
-#, python-format
-msgid "You already have a collection called \"%s\"!"
-msgstr "¡Ya tienes una colección llamada \"%s\"!"
-
#: mediagoblin/submit/views.py:215
#, python-format
msgid "Collection \"%s\" added!"
msgstr "¡Colección \"%s\" añadida!"
-#: mediagoblin/templates/mediagoblin/404.html:24
-msgid "Image of 404 goblin stressing out"
-msgstr "Imagen de 404 goblin estresándose"
-
-#: mediagoblin/templates/mediagoblin/404.html:25
-msgid "Oops!"
-msgstr "¡Ups!"
-
-#: mediagoblin/templates/mediagoblin/404.html:26
-msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr "Parece no haber una página en esta dirección. ¡Lo sentimos!"
-
-#: mediagoblin/templates/mediagoblin/404.html:28
-msgid ""
-"If you're sure the address is correct, maybe the page you're looking for has"
-" been moved or deleted."
-msgstr "Si estás seguro que la dirección es correcta, puede ser que la pagina haya sido movida o borrada."
-
-#: mediagoblin/templates/mediagoblin/base.html:50
+#: mediagoblin/templates/mediagoblin/base.html:48
msgid "MediaGoblin logo"
msgstr "Logo de MediaGoblin"
-#: mediagoblin/templates/mediagoblin/base.html:60
-msgid "Verify your email!"
-msgstr "¡Verifica tu email!"
-
-#: mediagoblin/templates/mediagoblin/base.html:66
-msgid "+ Add media"
-msgstr "+Agregar contenido"
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, 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:67
-msgid "+ Add collection"
-msgstr "+ Añadir colección"
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
+msgstr "cerrar sesión"
-#: mediagoblin/templates/mediagoblin/base.html:69
-msgid "View your profile"
-msgstr "Ver tu perfil"
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
+msgstr "Añadir contenido"
-#: mediagoblin/templates/mediagoblin/base.html:70
-msgid "Log out"
-msgstr "Salir "
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
+msgstr "¡Verifica tu email!"
-#: mediagoblin/templates/mediagoblin/base.html:75
+#: 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 "Conectarse"
-#: mediagoblin/templates/mediagoblin/base.html:89
+#: mediagoblin/templates/mediagoblin/base.html:87
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project."
msgstr "Proveído por <a href=\"http://mediagoblin.org\">MediaGoblin</a>, un proyecto <a href=\"http://gnu.org/\">GNU</a>."
-#: mediagoblin/templates/mediagoblin/base.html:92
+#: mediagoblin/templates/mediagoblin/base.html:90
#, python-format
msgid ""
"Released under the <a "
@@ -404,31 +386,56 @@ msgid ""
"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/root.html:24
+#: mediagoblin/templates/mediagoblin/error.html:24
+msgid "Image of goblin stressing out"
+msgstr "Imagen de un goblin estresándose"
+
+#: mediagoblin/templates/mediagoblin/root.html:25
+msgid "Actions"
+msgstr "Acciones"
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr "Crear nueva colección"
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr "Cambiar la configuración de la cuenta"
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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 "Panel de procesamiento de contenido"
+
+#: mediagoblin/templates/mediagoblin/root.html:51
msgid "Explore"
msgstr "Explorar"
-#: mediagoblin/templates/mediagoblin/root.html:26
+#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Hi there, welcome to this MediaGoblin site!"
msgstr "Hola, ¡bienvenido a este sitio de MediaGoblin!"
-#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/root.html:55
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:29
+#: mediagoblin/templates/mediagoblin/root.html:56
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:31
+#: mediagoblin/templates/mediagoblin/root.html:58
msgid "Don't have one yet? It's easy!"
msgstr "¿Aún no tienes una? ¡Es fácil!"
-#: mediagoblin/templates/mediagoblin/root.html:32
+#: mediagoblin/templates/mediagoblin/root.html:59
#, python-format
msgid ""
"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
@@ -436,17 +443,10 @@ msgid ""
" <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:40
+#: mediagoblin/templates/mediagoblin/root.html:67
msgid "Most recent media"
msgstr "El contenido más reciente"
-#: 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 "Panel de procesamiento de contenido"
-
#: mediagoblin/templates/mediagoblin/admin/panel.html:29
msgid ""
"Here you can track the state of media being processed on this instance."
@@ -555,30 +555,43 @@ msgstr "Hola %(username)s,\n\npara activar tu cuenta de GNU MediaGoblin, abre la
msgid "Editing attachments for %(media_title)s"
msgstr "Editando archivos adjuntos a %(media_title)s"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:23
-#: mediagoblin/templates/mediagoblin/edit/edit.html:35
-#, python-format
-msgid "Editing %(media_title)s"
-msgstr "Editando %(media_title)s "
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:43
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
+msgid "Attachments"
+msgstr "Adjuntos"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr "Agregar adjunto"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:53
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
msgid "Cancel"
msgstr "Cancelar"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:43
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
msgid "Save changes"
msgstr "Guardar cambios"
+#: mediagoblin/templates/mediagoblin/edit/edit.html:23
+#: mediagoblin/templates/mediagoblin/edit/edit.html:35
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "Editando %(media_title)s "
+
#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:41
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
#, python-format
msgid "Changing %(username)s's account settings"
msgstr "Cambio de %(username)s la configuración de la cuenta "
@@ -604,13 +617,12 @@ 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/image.html:23
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
msgid "Download"
msgstr "Descargar"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:27
msgid "Original"
msgstr "Original"
@@ -637,6 +649,56 @@ msgstr "Archivo original"
msgid "WebM file (Vorbis codec)"
msgstr "Archivo WebM (códec Vorbis)"
+#: 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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr "Imágenes para %(media_title)s"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
+msgid "Toggle Rotate"
+msgstr "Alternar Rotar"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113
+msgid "Perspective"
+msgstr "Perspectiva"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117
+msgid "Front"
+msgstr "Frente"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121
+msgid "Top"
+msgstr "Arriba"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125
+msgid "Side"
+msgstr "Lateral"
+
+#: 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 "Descargar modelo"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146
+msgid "File Format"
+msgstr "Formato de Archivo"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148
+msgid "Object Height"
+msgstr "Altura del Objeto"
+
#: mediagoblin/templates/mediagoblin/media_displays/video.html:40
msgid ""
"Sorry, this video will not work because \n"
@@ -661,7 +723,7 @@ msgstr "Añadir una colección"
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
#: mediagoblin/templates/mediagoblin/submit/start.html:34
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:83
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
msgid "Add"
msgstr "Añadir "
@@ -690,14 +752,6 @@ msgstr "Editar"
msgid "Delete"
msgstr "Borrar"
-#: mediagoblin/templates/mediagoblin/user_pages/collection.html:59
-#, python-format
-msgid ""
-"<p>\n"
-" %(collection_description)s\n"
-" </p>"
-msgstr "<p>\n%(collection_description)s\n</p>"
-
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
@@ -705,7 +759,7 @@ msgid "Really delete %(title)s?"
msgstr "¿Realmente deseas eliminar %(title)s?"
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "Eliminar permanentemente"
@@ -714,7 +768,7 @@ msgstr "Eliminar permanentemente"
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:54
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
msgid "Remove"
msgstr "Quitar"
@@ -740,12 +794,6 @@ msgstr "Contenido de <a href=\"%(user_url)s\">%(username)s</a>'s"
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:67
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
-#, python-format
-msgid "Image for %(media_title)s"
-msgstr "Imágenes para %(media_title)s"
-
#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
msgid "Add a comment"
msgstr "Añadir un comentario"
@@ -772,25 +820,20 @@ msgid ""
" <p>%(date)s</p>"
msgstr "<h3>Añadido en</h3>\n <p>%(date)s</p>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
-msgid "Attachments"
-msgstr "Adjuntos"
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
-msgid "Add attachment"
-msgstr "Agregar adjunto"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
+msgstr "Añadir contenido a la colección"
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
#, python-format
msgid "Add %(title)s to collection"
msgstr "Añadir %(title)s a la colección"
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
msgid "+"
msgstr "+"
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
msgid "Add a new collection"
msgstr "Añadir una nueva colección"
@@ -861,42 +904,26 @@ msgstr "Editar perfil"
msgid "This user hasn't filled in their profile (yet)."
msgstr "Este usuario (todavía) no ha completado su perfil."
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:125
-msgid "Change account settings"
-msgstr "Cambiar la configuración de la cuenta"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:138
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
#, python-format
msgid "View all of %(username)s's media"
msgstr "Ver todo el contenido de %(username)s"
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
msgid ""
"This is where your media will appear, but you don't seem to have added "
"anything yet."
msgstr "Aquí es donde estará ubicado tu contenido, pero parece que aún no has agregado nada."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:157
-msgid "Add media"
-msgstr "Añadir contenido"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:163
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:87
-#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:72
+#: 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 "Parece que aún no hay ningún contenido aquí..."
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:39
-#, python-format
-msgid ""
-"<br />\n"
-" <a href=\"%(entry_url)s\">%(note)s</a>"
-msgstr "<br />⎠<a href=\"%(entry_url)s\">%(note)s</a>"
-
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:47
-#, python-format
-msgid "<br /><a href=\"%(remove_url)s\" class=\"remove\">(remove)</a>"
-msgstr "<br /><a href=\"%(remove_url)s\" class=\"remove\">(remove)</a>"
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
+msgstr "(borrar)"
#: mediagoblin/templates/mediagoblin/utils/collections.html:20
#, python-format
@@ -915,7 +942,7 @@ msgstr "Atom feed"
msgid "Location"
msgstr "Locación"
-#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:38
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
#, python-format
msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
msgstr "Ver en <a href=\"%(osm_url)s\">OpenStreetMap</a>"
@@ -954,6 +981,32 @@ msgstr "Marcado con"
msgid "Could not read the image file."
msgstr "No se pudo leer el archivo de imagen."
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr "¡Ups!"
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr "Ha ocurrido un error"
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr "Operación no permitida"
+
+#: mediagoblin/tools/response.py:47
+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 "¡Lo siento Dave, no puedo permitir que hagas eso!</p><p>Has intentado realizar una operación no permitida. ¿Has vuelto a intentar borrar todas las cuentas de usuario?"
+
+#: mediagoblin/tools/response.py:55
+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 "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/user_pages/forms.py:28
msgid "I am sure I want to delete this"
msgstr "Estoy seguro de que quiero borrar esto"
@@ -974,74 +1027,74 @@ msgstr "Incluir una nota"
msgid "commented on your post"
msgstr "comentó tu publicación"
-#: mediagoblin/user_pages/views.py:161
+#: mediagoblin/user_pages/views.py:156
msgid "Oops, your comment was empty."
msgstr "Ups, tu comentario estaba vacío."
-#: mediagoblin/user_pages/views.py:167
+#: mediagoblin/user_pages/views.py:162
msgid "Your comment has been posted!"
msgstr "¡Tu comentario ha sido publicado!"
-#: mediagoblin/user_pages/views.py:235
+#: mediagoblin/user_pages/views.py:230
msgid "You have to select or add a collection"
msgstr "Tienes que seleccionar o añadir una colección"
-#: mediagoblin/user_pages/views.py:243
+#: mediagoblin/user_pages/views.py:238
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr "%s\" ya está en la colección \"%s\""
-#: mediagoblin/user_pages/views.py:258
+#: mediagoblin/user_pages/views.py:253
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr "\"%s\" añadido a la colección \"%s\""
-#: mediagoblin/user_pages/views.py:266
+#: mediagoblin/user_pages/views.py:261
msgid "Please check your entries and try again."
msgstr "Por favor, revisa tus entradas e inténtalo de nuevo."
-#: mediagoblin/user_pages/views.py:297
+#: mediagoblin/user_pages/views.py:292
msgid ""
"Some of the files with this entry seem to be missing. Deleting anyway."
msgstr "Al parecer algunos de los ficheros en esta entrada se han perdido. Borrando igualmente."
-#: mediagoblin/user_pages/views.py:302
+#: mediagoblin/user_pages/views.py:297
msgid "You deleted the media."
msgstr "Eliminaste el contenido"
-#: mediagoblin/user_pages/views.py:309
+#: mediagoblin/user_pages/views.py:304
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:317
+#: mediagoblin/user_pages/views.py:312
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. Proceder con precaución."
-#: mediagoblin/user_pages/views.py:379
+#: 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:383
+#: 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:393
+#: mediagoblin/user_pages/views.py:384
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:426
+#: mediagoblin/user_pages/views.py:417
#, python-format
msgid "You deleted the collection \"%s\""
msgstr "Borraste la colección \"%s\""
-#: mediagoblin/user_pages/views.py:433
+#: mediagoblin/user_pages/views.py:424
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:443
+#: mediagoblin/user_pages/views.py:434
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 4996877b..ba9aad9b 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 2037f36e..44e8b802 100644
--- a/mediagoblin/i18n/fa/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/fa/LC_MESSAGES/mediagoblin.po
@@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2012-09-24 14:01-0500\n"
-"PO-Revision-Date: 2012-09-24 18:57+0000\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 15:14+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
@@ -92,7 +92,7 @@ msgstr ""
msgid "You can now log in using your new password."
msgstr ""
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:83
+#: 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:40
msgid "Title"
@@ -103,7 +103,7 @@ msgid "Description of this work"
msgstr ""
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:87 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:44
msgid ""
"You can use\n"
@@ -119,11 +119,11 @@ msgstr "برچسب"
msgid "Separate tags by commas."
msgstr ""
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:91
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr ""
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:92
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr ""
@@ -162,20 +162,20 @@ msgstr ""
msgid "New password"
msgstr ""
-#: mediagoblin/edit/forms.py:72
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr ""
-#: mediagoblin/edit/forms.py:84
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:43
msgid "Description of this collection"
msgstr ""
-#: mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
@@ -189,33 +189,38 @@ msgstr ""
msgid "You are editing another user's media. Proceed with caution."
msgstr "شما در حال ویرایش رسانه کاربر دیگری هستید.با احتیاط عمل کنید"
-#: mediagoblin/edit/views.py:182
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr ""
+
+#: mediagoblin/edit/views.py:181
msgid "You are editing a user's profile. Proceed with caution."
msgstr "شما در حال ویرایش نمایه کاربر دیگری هستید.با احتیاط عمل کنید."
-#: mediagoblin/edit/views.py:198
+#: mediagoblin/edit/views.py:197
msgid "Profile changes saved"
msgstr ""
-#: mediagoblin/edit/views.py:227 mediagoblin/edit/views.py:247
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
msgid "Account settings saved"
msgstr ""
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:251
msgid "Wrong password"
msgstr ""
-#: mediagoblin/edit/views.py:288 mediagoblin/submit/views.py:211
-#: mediagoblin/user_pages/views.py:215
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr ""
-#: mediagoblin/edit/views.py:292
+#: mediagoblin/edit/views.py:291
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:309
+#: mediagoblin/edit/views.py:308
msgid "You are editing another user's collection. Proceed with caution."
msgstr ""
@@ -232,7 +237,7 @@ msgid "However, old link directory symlink found; removed.\n"
msgstr ""
#: mediagoblin/media_types/__init__.py:60
-#: mediagoblin/media_types/__init__.py:120
+#: mediagoblin/media_types/__init__.py:101
msgid "Sorry, I don't support that file type :("
msgstr ""
@@ -302,7 +307,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:60
msgid "The client {0} has been registered!"
msgstr ""
@@ -327,62 +332,43 @@ msgstr "هورا!ثبت شد!"
msgid "Collection \"%s\" added!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/404.html:24
-msgid "Image of 404 goblin stressing out"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/404.html:25
-msgid "Oops!"
-msgstr "اوه"
-
-#: mediagoblin/templates/mediagoblin/404.html:26
-msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr "Ù…ØªØ§Ø³ÙØ§Ù†Ù‡ به نظر نمی رسد Ú©Ù‡ چنین ØµÙØ­Ù‡ ای در این آدرس وجود داشته باشد!"
-
-#: mediagoblin/templates/mediagoblin/404.html:28
-msgid ""
-"If you're sure the address is correct, maybe the page you're looking for has"
-" been moved or deleted."
-msgstr "اگر مطمين هستین Ú©Ù‡ آدرس درست است،ممکن است ØµÙØ­Ù‡ ای Ú©Ù‡ شما آنرا جستجو Ù…ÛŒ کنید انتقال داده شده Ùˆ یا حذ٠شده باشد."
-
-#: mediagoblin/templates/mediagoblin/base.html:50
+#: mediagoblin/templates/mediagoblin/base.html:48
msgid "MediaGoblin logo"
msgstr "لوگو مدیاگوبلین"
-#: mediagoblin/templates/mediagoblin/base.html:60
-msgid "Verify your email!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:66
-msgid "+ Add media"
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:67
-msgid "+ Add collection"
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:69
-msgid "View your profile"
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:70
-msgid "Log out"
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:75
+#: 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:89
+#: mediagoblin/templates/mediagoblin/base.html:87
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project."
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:92
+#: mediagoblin/templates/mediagoblin/base.html:90
#, python-format
msgid ""
"Released under the <a "
@@ -390,31 +376,56 @@ msgid ""
"href=\"%(source_link)s\">Source code</a> available."
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:24
+#: mediagoblin/templates/mediagoblin/error.html:24
+msgid "Image of goblin stressing out"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:25
+msgid "Actions"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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/root.html:51
msgid "Explore"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:26
+#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Hi there, welcome to this MediaGoblin site!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/root.html:55
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:29
+#: mediagoblin/templates/mediagoblin/root.html:56
msgid ""
"To add your own media, place comments, and more, you can log in with your "
"MediaGoblin account."
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:31
+#: mediagoblin/templates/mediagoblin/root.html:58
msgid "Don't have one yet? It's easy!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:32
+#: mediagoblin/templates/mediagoblin/root.html:59
#, python-format
msgid ""
"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
@@ -422,17 +433,10 @@ msgid ""
" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:40
+#: mediagoblin/templates/mediagoblin/root.html:67
msgid "Most recent media"
msgstr ""
-#: 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/admin/panel.html:29
msgid ""
"Here you can track the state of media being processed on this instance."
@@ -541,30 +545,43 @@ msgstr "سلام %(username)s,\n\nبرای ÙØ¹Ø§Ù„ سازی شناسه کارب
msgid "Editing attachments for %(media_title)s"
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/attachments.html:43
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
+msgid "Attachments"
+msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:53
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
msgid "Cancel"
msgstr "انصراÙ"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:43
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
msgid "Save changes"
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:41
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
#, python-format
msgid "Changing %(username)s's account settings"
msgstr ""
@@ -590,13 +607,12 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:23
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
msgid "Download"
msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:27
msgid "Original"
msgstr ""
@@ -623,6 +639,56 @@ msgstr ""
msgid "WebM file (Vorbis codec)"
msgstr ""
+#: 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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr ""
+
+#: 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 ""
+
+#: 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:40
msgid ""
"Sorry, this video will not work because \n"
@@ -647,7 +713,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
#: mediagoblin/templates/mediagoblin/submit/start.html:34
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:83
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
msgid "Add"
msgstr ""
@@ -676,14 +742,6 @@ msgstr ""
msgid "Delete"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection.html:59
-#, python-format
-msgid ""
-"<p>\n"
-" %(collection_description)s\n"
-" </p>"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
@@ -691,7 +749,7 @@ msgid "Really delete %(title)s?"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr ""
@@ -700,7 +758,7 @@ msgstr ""
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
msgid "Remove"
msgstr ""
@@ -726,12 +784,6 @@ 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:67
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
-#, python-format
-msgid "Image for %(media_title)s"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
msgid "Add a comment"
msgstr ""
@@ -758,13 +810,8 @@ msgid ""
" <p>%(date)s</p>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
-msgid "Attachments"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
-msgid "Add attachment"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
@@ -772,11 +819,11 @@ msgstr ""
msgid "Add %(title)s to collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
msgid "+"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
msgid "Add a new collection"
msgstr ""
@@ -847,41 +894,25 @@ msgstr "ویرایش نمایه"
msgid "This user hasn't filled in their profile (yet)."
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:125
-msgid "Change account settings"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:138
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
#, python-format
msgid "View all of %(username)s's media"
msgstr "نمایش تمامی رسانه های %(username)s"
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
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:157
-msgid "Add media"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:163
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:87
-#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:72
+#: 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:39
-#, python-format
-msgid ""
-"<br />\n"
-" <a href=\"%(entry_url)s\">%(note)s</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:47
-#, python-format
-msgid "<br /><a href=\"%(remove_url)s\" class=\"remove\">(remove)</a>"
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
msgstr ""
#: mediagoblin/templates/mediagoblin/utils/collections.html:20
@@ -901,7 +932,7 @@ msgstr ""
msgid "Location"
msgstr ""
-#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:38
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
#, python-format
msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
msgstr ""
@@ -940,6 +971,32 @@ msgstr ""
msgid "Could not read the image file."
msgstr ""
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr "اوه"
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr ""
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr ""
+
+#: mediagoblin/tools/response.py:47
+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:55
+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/user_pages/forms.py:28
msgid "I am sure I want to delete this"
msgstr ""
@@ -960,74 +1017,74 @@ msgstr ""
msgid "commented on your post"
msgstr ""
-#: mediagoblin/user_pages/views.py:161
+#: mediagoblin/user_pages/views.py:156
msgid "Oops, your comment was empty."
msgstr ""
-#: mediagoblin/user_pages/views.py:167
+#: mediagoblin/user_pages/views.py:162
msgid "Your comment has been posted!"
msgstr ""
-#: mediagoblin/user_pages/views.py:235
+#: mediagoblin/user_pages/views.py:230
msgid "You have to select or add a collection"
msgstr ""
-#: mediagoblin/user_pages/views.py:243
+#: mediagoblin/user_pages/views.py:238
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:258
+#: mediagoblin/user_pages/views.py:253
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:266
+#: mediagoblin/user_pages/views.py:261
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:297
+#: mediagoblin/user_pages/views.py:292
msgid ""
"Some of the files with this entry seem to be missing. Deleting anyway."
msgstr ""
-#: mediagoblin/user_pages/views.py:302
+#: mediagoblin/user_pages/views.py:297
msgid "You deleted the media."
msgstr ""
-#: mediagoblin/user_pages/views.py:309
+#: mediagoblin/user_pages/views.py:304
msgid "The media was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:317
+#: mediagoblin/user_pages/views.py:312
msgid "You are about to delete another user's media. Proceed with caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr ""
-#: mediagoblin/user_pages/views.py:383
+#: 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:393
+#: mediagoblin/user_pages/views.py:384
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:426
+#: mediagoblin/user_pages/views.py:417
#, python-format
msgid "You deleted the collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:433
+#: mediagoblin/user_pages/views.py:424
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:443
+#: mediagoblin/user_pages/views.py:434
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 8262b37f..b0106832 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 560484bb..39480ea9 100644
--- a/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.po
@@ -4,6 +4,7 @@
#
# Translators:
# <a5565930@nepwk.com>, 2011.
+# <alexispay@gmail.com>, 2012.
# <chesuidayeur@yahoo.fr>, 2011.
# <joehillen@gmail.com>, 2011.
# <marktraceur@gmail.com>, 2011.
@@ -14,8 +15,8 @@ msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2012-09-24 14:01-0500\n"
-"PO-Revision-Date: 2012-09-24 18:57+0000\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 15:14+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"
@@ -39,11 +40,11 @@ msgstr "Adresse e-mail"
#: mediagoblin/auth/forms.py:51
msgid "Username or email"
-msgstr ""
+msgstr "Nom d'utilisateur ou email"
#: mediagoblin/auth/forms.py:58
msgid "Incorrect input"
-msgstr ""
+msgstr "Entrée incorrecte"
#: mediagoblin/auth/views.py:55
msgid "Sorry, registration is disabled on this instance."
@@ -82,7 +83,7 @@ msgstr "E-mail de vérification renvoyé."
#: mediagoblin/auth/views.py:263
msgid ""
"An email has been sent with instructions on how to change your password."
-msgstr ""
+msgstr "Un email contenant les instructions pour changer votre mot de passe viens de vous être envoyé"
#: mediagoblin/auth/views.py:273
msgid ""
@@ -92,13 +93,13 @@ msgstr "Impossible d'envoyer un email de récupération de mot de passe : votre
#: mediagoblin/auth/views.py:285
msgid "Couldn't find someone with that username or email."
-msgstr ""
+msgstr "Impossible de trouver un utilisateur avec ce nom ou cette email."
#: mediagoblin/auth/views.py:333
msgid "You can now log in using your new password."
-msgstr ""
+msgstr "Vous pouvez maintenant vous connecter avec votre nouveau mot de passe."
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:83
+#: 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:40
msgid "Title"
@@ -109,13 +110,13 @@ msgid "Description of this work"
msgstr "Descriptif pour ce travail"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:87 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:44
msgid ""
"You can use\n"
" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n"
" Markdown</a> for formatting."
-msgstr ""
+msgstr "Vous pouvez utiliser\n <a href=\"http://daringfireball.net/projects/markdown/basics\">\n Markdown</a> pour le formattage."
#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36
msgid "Tags"
@@ -123,13 +124,13 @@ msgstr "Tags"
#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38
msgid "Separate tags by commas."
-msgstr ""
+msgstr "Séparez les champs avec des virgules."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:91
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "Légende"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:92
+#: 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."
@@ -137,12 +138,12 @@ msgstr "La légende ne peut pas être laissée vide."
msgid ""
"The title part of this media's address. You usually don't need to change "
"this."
-msgstr ""
+msgstr "Le titre présent dans l'URL du média. Vous n'avez généralement pas besoin de le modifier"
#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41
#: mediagoblin/templates/mediagoblin/utils/license.html:20
msgid "License"
-msgstr ""
+msgstr "Licence"
#: mediagoblin/edit/forms.py:50
msgid "Bio"
@@ -154,7 +155,7 @@ msgstr "Site web"
#: mediagoblin/edit/forms.py:58
msgid "This address contains errors"
-msgstr ""
+msgstr "Cette adresse contiens des erreurs"
#: mediagoblin/edit/forms.py:63
msgid "Old password"
@@ -162,30 +163,30 @@ msgstr "Ancien mot de passe."
#: mediagoblin/edit/forms.py:64
msgid "Enter your old password to prove you own this account."
-msgstr ""
+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 ""
+msgstr "Nouveau mot de passe"
-#: mediagoblin/edit/forms.py:72
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
-msgstr ""
+msgstr "Me prévenir par email lorsque d'autres commentent mes médias"
-#: mediagoblin/edit/forms.py:84
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
-msgstr ""
+msgstr "Le titre ne peut être vide"
-#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:43
msgid "Description of this collection"
-msgstr ""
+msgstr "Description de cette collection"
-#: mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
-msgstr ""
+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:65
msgid "An entry with that slug already exists for this user."
@@ -195,56 +196,61 @@ msgstr "Une entrée existe déjà pour cet utilisateur avec la même légende."
msgid "You are editing another user's media. Proceed with caution."
msgstr "Vous vous apprêtez à modifier le média d'un autre utilisateur. Veuillez prendre garde."
-#: mediagoblin/edit/views.py:182
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr ""
+
+#: mediagoblin/edit/views.py:181
msgid "You are editing a user's profile. Proceed with caution."
msgstr "Vous vous apprêtez à modifier le profil d'un utilisateur. Veuillez prendre garde."
-#: mediagoblin/edit/views.py:198
+#: mediagoblin/edit/views.py:197
msgid "Profile changes saved"
-msgstr ""
+msgstr "Les changements apportés au profile ont étés sauvegardés"
-#: mediagoblin/edit/views.py:227 mediagoblin/edit/views.py:247
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
msgid "Account settings saved"
-msgstr ""
+msgstr "Les changements des préférences du compte ont étés sauvegardés"
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:251
msgid "Wrong password"
msgstr "Mauvais mot de passe"
-#: mediagoblin/edit/views.py:288 mediagoblin/submit/views.py:211
-#: mediagoblin/user_pages/views.py:215
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
#, python-format
msgid "You already have a collection called \"%s\"!"
-msgstr ""
+msgstr "Vous avez déjà une collection appelée \"%s\" !"
-#: mediagoblin/edit/views.py:292
+#: mediagoblin/edit/views.py:291
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:309
+#: mediagoblin/edit/views.py:308
msgid "You are editing another user's collection. Proceed with caution."
-msgstr ""
+msgstr "Vous éditez la collection d'un autre utilisateurs. Faites attention."
#: mediagoblin/gmg_commands/theme.py:58
msgid "Cannot link theme... no theme set\n"
-msgstr ""
+msgstr "Impossible de lier le thème... Aucun thème associé\n"
#: mediagoblin/gmg_commands/theme.py:71
msgid "No asset directory for this theme\n"
-msgstr ""
+msgstr "Aucun répertoire \"asset\" pour ce thème\n"
#: mediagoblin/gmg_commands/theme.py:74
msgid "However, old link directory symlink found; removed.\n"
msgstr ""
#: mediagoblin/media_types/__init__.py:60
-#: mediagoblin/media_types/__init__.py:120
+#: mediagoblin/media_types/__init__.py:101
msgid "Sorry, I don't support that file type :("
-msgstr ""
+msgstr "Désolé, mais je ne prends pas en charge cette extension de fichier :("
#: mediagoblin/media_types/video/processing.py:35
msgid "Video transcoding failed"
-msgstr ""
+msgstr "L'encodage de la vidéo à échoué"
#: mediagoblin/plugins/oauth/forms.py:26
msgid "Client ID"
@@ -252,19 +258,19 @@ msgstr ""
#: mediagoblin/plugins/oauth/forms.py:28
msgid "Next URL"
-msgstr ""
+msgstr "Prochaine URL"
#: mediagoblin/plugins/oauth/forms.py:30
msgid "Allow"
-msgstr ""
+msgstr "Autoriser"
#: mediagoblin/plugins/oauth/forms.py:31
msgid "Deny"
-msgstr ""
+msgstr "Refuser"
#: mediagoblin/plugins/oauth/forms.py:35
msgid "Name"
-msgstr ""
+msgstr "Nom"
#: mediagoblin/plugins/oauth/forms.py:36
msgid "The name of the OAuth client"
@@ -272,7 +278,7 @@ msgstr ""
#: mediagoblin/plugins/oauth/forms.py:37
msgid "Description"
-msgstr ""
+msgstr "Description"
#: mediagoblin/plugins/oauth/forms.py:39
msgid ""
@@ -282,7 +288,7 @@ msgstr ""
#: mediagoblin/plugins/oauth/forms.py:41
msgid "Type"
-msgstr ""
+msgstr "Type"
#: mediagoblin/plugins/oauth/forms.py:46
msgid ""
@@ -296,21 +302,21 @@ msgstr ""
#: mediagoblin/plugins/oauth/forms.py:53
msgid "Redirect URI"
-msgstr ""
+msgstr "URL de redirection"
#: mediagoblin/plugins/oauth/forms.py:55
msgid ""
"The redirect URI for the applications, this field\n"
" is <strong>required</strong> for public clients."
-msgstr ""
+msgstr "L'URI de redirection pour l'application, ce champ est <strong>requis</strong> pour les clients publics"
#: mediagoblin/plugins/oauth/forms.py:67
msgid "This field is required for public clients"
-msgstr ""
+msgstr "Ce champ est requis pour les clients publics"
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:60
msgid "The client {0} has been registered!"
-msgstr ""
+msgstr "Le client {0} as été enregistré !"
#: mediagoblin/processing/__init__.py:138
msgid "Invalid file given for media type."
@@ -331,118 +337,117 @@ msgstr "Youhou, c'est envoyé !"
#: mediagoblin/submit/views.py:215
#, python-format
msgid "Collection \"%s\" added!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/404.html:24
-msgid "Image of 404 goblin stressing out"
-msgstr "Image de 404 gobelin angoissé"
-
-#: mediagoblin/templates/mediagoblin/404.html:25
-msgid "Oops!"
-msgstr "Zut !"
-
-#: mediagoblin/templates/mediagoblin/404.html:26
-msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr "Il ne semble pas y avoir de page à cette adresse. Désolé !"
-
-#: mediagoblin/templates/mediagoblin/404.html:28
-msgid ""
-"If you're sure the address is correct, maybe the page you're looking for has"
-" been moved or deleted."
-msgstr "Si vous êtes sûr que l'adresse est correcte, peut-être la page que vous recherchez a été déplacée ou supprimée."
+msgstr "Collection \"%s\" ajoutée !"
-#: mediagoblin/templates/mediagoblin/base.html:50
+#: mediagoblin/templates/mediagoblin/base.html:48
msgid "MediaGoblin logo"
msgstr "Logo MediaGoblin"
-#: mediagoblin/templates/mediagoblin/base.html:60
-msgid "Verify your email!"
-msgstr "Vérifiez votre adresse e-mail !"
-
-#: mediagoblin/templates/mediagoblin/base.html:66
-msgid "+ Add media"
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:67
-msgid "+ Add collection"
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:69
-msgid "View your profile"
-msgstr ""
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
+msgstr "Ajouter des médias"
-#: mediagoblin/templates/mediagoblin/base.html:70
-msgid "Log out"
-msgstr ""
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
+msgstr "Vérifiez votre adresse e-mail !"
-#: mediagoblin/templates/mediagoblin/base.html:75
+#: 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:89
+#: mediagoblin/templates/mediagoblin/base.html:87
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project."
-msgstr ""
+msgstr "Conçu avec <a href=\"http://mediagoblin.org\">MediaGoblin</a>, un projet <a href=\"http://gnu.org/\">GNU</a>."
-#: mediagoblin/templates/mediagoblin/base.html:92
+#: mediagoblin/templates/mediagoblin/base.html:90
#, 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:25
+msgid "Actions"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:24
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr "Changer les paramètres du compte"
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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 "Panneau pour le traitement des médias"
+
+#: mediagoblin/templates/mediagoblin/root.html:51
msgid "Explore"
msgstr "Explorer"
-#: mediagoblin/templates/mediagoblin/root.html:26
+#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Hi there, welcome to this MediaGoblin site!"
msgstr "Bonjour, et bienvenu sur ce site MediaGoblin !"
-#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/root.html:55
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:29
+#: mediagoblin/templates/mediagoblin/root.html:56
msgid ""
"To add your own media, place comments, and more, you can log in with your "
"MediaGoblin account."
-msgstr ""
+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:31
+#: mediagoblin/templates/mediagoblin/root.html:58
msgid "Don't have one yet? It's easy!"
msgstr "Vous n'en avez pas ? C'est facile !"
-#: mediagoblin/templates/mediagoblin/root.html:32
+#: mediagoblin/templates/mediagoblin/root.html:59
#, 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 ""
+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:40
+#: mediagoblin/templates/mediagoblin/root.html:67
msgid "Most recent media"
msgstr "Tout derniers media"
-#: 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 "Panneau pour le traitement des médias"
-
#: mediagoblin/templates/mediagoblin/admin/panel.html:29
msgid ""
"Here you can track the state of media being processed on this instance."
-msgstr ""
+msgstr "Ici, vous pouvez suivre l'état des médias en cours de traitement par cette instance."
#: mediagoblin/templates/mediagoblin/admin/panel.html:32
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32
@@ -462,25 +467,25 @@ msgstr "Le traitement de ces ajouts a échoué :"
#: mediagoblin/templates/mediagoblin/admin/panel.html:90
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86
msgid "No failed entries!"
-msgstr ""
+msgstr "Aucune entrée ayant échoué !"
#: mediagoblin/templates/mediagoblin/admin/panel.html:92
msgid "Last 10 successful uploads"
-msgstr ""
+msgstr "10 derniers envois terminés"
#: mediagoblin/templates/mediagoblin/admin/panel.html:112
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107
msgid "No processed entries, yet!"
-msgstr ""
+msgstr "Aucune entrée traitée jusqu'à présent !"
#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28
#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36
msgid "Set your new password"
-msgstr ""
+msgstr "Enregistrez votre nouveau mot de passe"
#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39
msgid "Set password"
-msgstr ""
+msgstr "Enregistrez votre mot de passe"
#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23
#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31
@@ -545,40 +550,53 @@ msgstr "Bonjour %(username)s,\n\npour activer votre compte sur GNU MediaGoblin,
#: mediagoblin/templates/mediagoblin/edit/attachments.html:35
#, python-format
msgid "Editing attachments for %(media_title)s"
-msgstr ""
+msgstr "Éditer les pièces jointes de %(media_title)s"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:23
-#: mediagoblin/templates/mediagoblin/edit/edit.html:35
-#, python-format
-msgid "Editing %(media_title)s"
-msgstr "Modification de %(media_title)s"
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:43
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
+msgid "Attachments"
+msgstr "Pièces jointes"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr "Ajouter une pièce jointe"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:53
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
msgid "Cancel"
msgstr "Annuler"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:43
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
msgid "Save changes"
msgstr "Enregistrer les modifications"
+#: mediagoblin/templates/mediagoblin/edit/edit.html:23
+#: mediagoblin/templates/mediagoblin/edit/edit.html:35
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "Modification de %(media_title)s"
+
#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:41
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
#, python-format
msgid "Changing %(username)s's account settings"
-msgstr ""
+msgstr "Changement des préférences du compte de %(username)s"
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29
#, python-format
msgid "Editing %(collection_title)s"
-msgstr ""
+msgstr "Modification de %(collection_title)s"
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:23
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
@@ -596,13 +614,12 @@ 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/image.html:23
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
msgid "Download"
-msgstr ""
+msgstr "Télécharger"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:27
msgid "Original"
msgstr "Original"
@@ -611,22 +628,72 @@ msgid ""
"Sorry, this audio will not work because \n"
"\tyour web browser does not support HTML5 \n"
"\taudio."
-msgstr ""
+msgstr "Désolé, mais ce fichier audio ne se lancera pas car\nvotre navigateur web ne supporte pas l'audio 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 ""
+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/video.html:56
msgid "Original file"
-msgstr ""
+msgstr "Fichier original"
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:63
msgid "WebM file (Vorbis codec)"
+msgstr "fichier WebM (codec Vorbis)"
+
+#: 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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr "Image de %(media_title)s"
+
+#: 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 ""
+
+#: 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:40
@@ -634,33 +701,33 @@ msgid ""
"Sorry, this video will not work because \n"
"\t your web browser does not support HTML5 \n"
"\t video."
-msgstr ""
+msgstr "Désolé, cette vidéo ne s'affichera pas car\nvotre navigateur ne prends pas en charge le HTML5 pour les vidéos"
#: mediagoblin/templates/mediagoblin/media_displays/video.html:43
msgid ""
"You can get a modern web browser that \n"
"\t can play this video at <a href=\"http://getfirefox.com\">\n"
"\t http://getfirefox.com</a>!"
-msgstr ""
+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/video.html:59
msgid "WebM file (640p; VP8/Vorbis)"
-msgstr ""
+msgstr "fichier WebM (640p; VP8/Vorbis)"
#: mediagoblin/templates/mediagoblin/submit/collection.html:26
msgid "Add a collection"
-msgstr ""
+msgstr "Ajouter une collection"
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
#: mediagoblin/templates/mediagoblin/submit/start.html:34
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:83
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
msgid "Add"
-msgstr ""
+msgstr "Ajouter"
#: mediagoblin/templates/mediagoblin/submit/start.html:23
#: mediagoblin/templates/mediagoblin/submit/start.html:30
msgid "Add your media"
-msgstr ""
+msgstr "Ajoutez votre média"
#: mediagoblin/templates/mediagoblin/user_pages/collection.html:30
#, python-format
@@ -670,7 +737,7 @@ 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 ""
+msgstr "%(collection_title)s de <a href=\"%(user_url)s\">%(username)s</a>"
#: mediagoblin/templates/mediagoblin/user_pages/collection.html:52
#: mediagoblin/templates/mediagoblin/user_pages/media.html:87
@@ -682,14 +749,6 @@ msgstr "Éditer"
msgid "Delete"
msgstr "Effacer"
-#: mediagoblin/templates/mediagoblin/user_pages/collection.html:59
-#, python-format
-msgid ""
-"<p>\n"
-" %(collection_description)s\n"
-" </p>"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
@@ -697,25 +756,25 @@ msgid "Really delete %(title)s?"
msgstr "Voulez-vous vraiment supprimer %(title)s ?"
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
-msgstr ""
+msgstr "Supprimer définitivement"
#: 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 "Voulez vous vraiment retirer %(media_title)s de %(collection_title)s ?"
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
msgid "Remove"
-msgstr ""
+msgstr "Retirer"
#: 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 "Bonjour %(username)s,\n%(comment_author)s a commenté votre post (%(comment_url)s) sur %(instance_name)s\n"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30
#, python-format
@@ -730,28 +789,22 @@ msgstr "Médias de <a href=\"%(user_url)s\">%(username)s</a>"
#: mediagoblin/templates/mediagoblin/user_pages/media.html:46
#, python-format
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:67
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
-#, python-format
-msgid "Image for %(media_title)s"
-msgstr ""
+msgstr "■Parcourir les médias de <a href=\"%(user_url)s\">%(username)s</a>"
#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
msgid "Add a comment"
-msgstr ""
+msgstr "Ajouter un commentaire"
#: mediagoblin/templates/mediagoblin/user_pages/media.html:109
msgid ""
"You can use <a "
"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for"
" formatting."
-msgstr ""
+msgstr "Vous pouvez utilisez les <a href=\"http://daringfireball.net/projects/markdown/basics\">Balises</a> pour la mise en page."
#: mediagoblin/templates/mediagoblin/user_pages/media.html:113
msgid "Add this comment"
-msgstr ""
+msgstr "Ajouter ce commentaire"
#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
msgid "at"
@@ -762,29 +815,24 @@ msgstr "à"
msgid ""
"<h3>Added on</h3>\n"
" <p>%(date)s</p>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
-msgid "Attachments"
-msgstr ""
+msgstr "<h3>Ajouté le</h3>\n<p>%(date)s</p>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
-msgid "Add attachment"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
#, python-format
msgid "Add %(title)s to collection"
-msgstr ""
+msgstr "Ajouter %(title)s à la collection"
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
msgid "+"
-msgstr ""
+msgstr "+"
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
msgid "Add a new collection"
-msgstr ""
+msgstr "Ajouter une nouvelle collection"
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:29
msgid ""
@@ -793,7 +841,7 @@ msgstr "Vous pouvez suivre l'état des médias en cours de traitement pour votre
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:89
msgid "Your last 10 successful uploads"
-msgstr ""
+msgstr "Vos 10 derniers envois réussis"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:31
#: mediagoblin/templates/mediagoblin/user_pages/user.html:89
@@ -853,47 +901,31 @@ msgstr "Modifier le profil"
msgid "This user hasn't filled in their profile (yet)."
msgstr "Cet utilisateur n'a pas (encore) rempli son profil."
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:125
-msgid "Change account settings"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:138
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
#, python-format
msgid "View all of %(username)s's media"
msgstr "Voir tous les médias de %(username)s"
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
msgid ""
"This is where your media will appear, but you don't seem to have added "
"anything yet."
msgstr "C'est là où vos médias apparaîssent, mais vous ne semblez pas avoir encore ajouté quoi que ce soit."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:157
-msgid "Add media"
-msgstr "Ajouter des médias"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:163
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:87
-#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:72
+#: 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 "Il ne semble pas y avoir de média là, pour l'instant ..."
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:39
-#, python-format
-msgid ""
-"<br />\n"
-" <a href=\"%(entry_url)s\">%(note)s</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:47
-#, python-format
-msgid "<br /><a href=\"%(remove_url)s\" class=\"remove\">(remove)</a>"
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
msgstr ""
#: mediagoblin/templates/mediagoblin/utils/collections.html:20
#, python-format
msgid "In collections (%(collected)s)"
-msgstr ""
+msgstr "Dans les collections (%(collected)s)"
#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
msgid "feed icon"
@@ -905,24 +937,24 @@ msgstr "flux Atom"
#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:25
msgid "Location"
-msgstr ""
+msgstr "Position"
-#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:38
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
#, python-format
msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
-msgstr ""
+msgstr "Regarder sur <a href=\"%(osm_url)s\">OpenStreetMap</a>"
#: mediagoblin/templates/mediagoblin/utils/license.html:25
msgid "All rights reserved"
-msgstr ""
+msgstr "Tous droits réservés"
#: mediagoblin/templates/mediagoblin/utils/pagination.html:39
msgid "↠Newer"
-msgstr ""
+msgstr "↠Le plus récent"
#: mediagoblin/templates/mediagoblin/utils/pagination.html:45
msgid "Older →"
-msgstr ""
+msgstr "Le plus vieux →"
#: mediagoblin/templates/mediagoblin/utils/pagination.html:48
msgid "Go to page:"
@@ -931,19 +963,45 @@ msgstr "Aller à la page :"
#: mediagoblin/templates/mediagoblin/utils/prev_next.html:28
#: mediagoblin/templates/mediagoblin/utils/prev_next.html:33
msgid "newer"
-msgstr ""
+msgstr "le plus récent"
#: mediagoblin/templates/mediagoblin/utils/prev_next.html:39
#: mediagoblin/templates/mediagoblin/utils/prev_next.html:44
msgid "older"
-msgstr ""
+msgstr "le plus vieux"
#: mediagoblin/templates/mediagoblin/utils/tags.html:20
msgid "Tagged with"
-msgstr ""
+msgstr "Taggé avec"
#: mediagoblin/tools/exif.py:78
msgid "Could not read the image file."
+msgstr "Impossible de lire l'image."
+
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr "Zut !"
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr ""
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr ""
+
+#: mediagoblin/tools/response.py:47
+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:55
+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/user_pages/forms.py:28
@@ -952,88 +1010,88 @@ msgstr "Je suis sûr de vouloir supprimer cela"
#: mediagoblin/user_pages/forms.py:32
msgid "I am sure I want to remove this item from the collection"
-msgstr ""
+msgstr "Je suis certain de vouloir retirer cet élément de la collection"
#: mediagoblin/user_pages/forms.py:35
msgid "-- Select --"
-msgstr ""
+msgstr "-- Sélectionner --"
#: mediagoblin/user_pages/forms.py:37
msgid "Include a note"
-msgstr ""
+msgstr "Inclure une note"
#: mediagoblin/user_pages/lib.py:56
msgid "commented on your post"
-msgstr ""
+msgstr "a commenté votre post"
-#: mediagoblin/user_pages/views.py:161
+#: mediagoblin/user_pages/views.py:156
msgid "Oops, your comment was empty."
msgstr "Oups, votre commentaire était vide."
-#: mediagoblin/user_pages/views.py:167
+#: mediagoblin/user_pages/views.py:162
msgid "Your comment has been posted!"
msgstr "Votre commentaire a été posté !"
-#: mediagoblin/user_pages/views.py:235
+#: mediagoblin/user_pages/views.py:230
msgid "You have to select or add a collection"
-msgstr ""
+msgstr "Vous devez sélectionner ou ajouter une collection"
-#: mediagoblin/user_pages/views.py:243
+#: mediagoblin/user_pages/views.py:238
#, python-format
msgid "\"%s\" already in collection \"%s\""
-msgstr ""
+msgstr "\"%s\" est déjà dans la collection \"%s\""
-#: mediagoblin/user_pages/views.py:258
+#: mediagoblin/user_pages/views.py:253
#, python-format
msgid "\"%s\" added to collection \"%s\""
-msgstr ""
+msgstr "\"%s\" as été ajouté à la collection \"%s\""
-#: mediagoblin/user_pages/views.py:266
+#: mediagoblin/user_pages/views.py:261
msgid "Please check your entries and try again."
-msgstr ""
+msgstr "Veuillez vérifier vos entrées et réessayer."
-#: mediagoblin/user_pages/views.py:297
+#: mediagoblin/user_pages/views.py:292
msgid ""
"Some of the files with this entry seem to be missing. Deleting anyway."
-msgstr ""
+msgstr "Certains fichiers correspondant à cette entrée semblent manquant. Suppression tout de même."
-#: mediagoblin/user_pages/views.py:302
+#: mediagoblin/user_pages/views.py:297
msgid "You deleted the media."
msgstr "Vous avez supprimé le media."
-#: mediagoblin/user_pages/views.py:309
+#: mediagoblin/user_pages/views.py:304
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:317
+#: mediagoblin/user_pages/views.py:312
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:379
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
-msgstr ""
+msgstr "Vous avez supprimé cet élément de la collection."
-#: mediagoblin/user_pages/views.py:383
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
-msgstr ""
+msgstr "L'élément n'as pas été supprimé car vous n'avez pas confirmé votre certitude."
-#: mediagoblin/user_pages/views.py:393
+#: mediagoblin/user_pages/views.py:384
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
-msgstr ""
+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:426
+#: mediagoblin/user_pages/views.py:417
#, python-format
msgid "You deleted the collection \"%s\""
-msgstr ""
+msgstr "Vous avez supprimé la collection \"%s\""
-#: mediagoblin/user_pages/views.py:433
+#: mediagoblin/user_pages/views.py:424
msgid ""
"The collection was not deleted because you didn't check that you were sure."
-msgstr ""
+msgstr "La collection n'as pas été supprimée car vous n'avez pas confirmé votre certitude"
-#: mediagoblin/user_pages/views.py:443
+#: mediagoblin/user_pages/views.py:434
msgid ""
"You are about to delete another user's collection. Proceed with caution."
-msgstr ""
+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
new file mode 100644
index 00000000..d38d8938
--- /dev/null
+++ 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
new file mode 100644
index 00000000..8041742b
--- /dev/null
+++ b/mediagoblin/i18n/he/LC_MESSAGES/mediagoblin.po
@@ -0,0 +1,1091 @@
+# Translations template for PROJECT.
+# Copyright (C) 2012 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+#
+# Translators:
+# <genghiskhan@gmx.ca>, 2012.
+# Isratine Citizen <genghiskhan@gmx.ca>, 2012.
+msgid ""
+msgstr ""
+"Project-Id-Version: GNU MediaGoblin\n"
+"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 15:14+0000\n"
+"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 0.9.6\n"
+"Language: he\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:41
+msgid "Username"
+msgstr "×©× ×ž×©×ª×ž×©"
+
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+msgid "Password"
+msgstr "סיסמה"
+
+#: mediagoblin/auth/forms.py:34
+msgid "Email address"
+msgstr "כתובת דו×״ל"
+
+#: mediagoblin/auth/forms.py:51
+msgid "Username or email"
+msgstr "×©× ×ž×©×ª×ž×© ×ו דו×״ל"
+
+#: mediagoblin/auth/forms.py:58
+msgid "Incorrect input"
+msgstr "קלט שגוי"
+
+#: mediagoblin/auth/views.py:55
+msgid "Sorry, registration is disabled on this instance."
+msgstr "צר לי, ×¨×™×©×•× ×”×™× ×• מנוטרל על שרת ×–×”."
+
+#: mediagoblin/auth/views.py:75
+msgid "Sorry, a user with that name already exists."
+msgstr "צר לי, משתמש ×¢× ×©× ×–×” כבר ×§×™×™×."
+
+#: mediagoblin/auth/views.py:79
+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 "מפתח ×”×ימות ×ו זהות משתמש ×”×™× × ×©×’×•×™×™×"
+
+#: 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:263
+msgid ""
+"An email has been sent with instructions on how to change your password."
+msgstr "דו×״ל נשלח בצירוף הור×ות בנוגע לכיצד ניתן לשנות ×ת סיסמתך."
+
+#: mediagoblin/auth/views.py:273
+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:285
+msgid "Couldn't find someone with that username or email."
+msgstr "×œ× ×”×™×” ניתן ×œ×ž×¦×•× ×ž×™×©×”×• ×¢× ×©× ×ž×©×ª×ž×© ×ו דו×״ל ×–×”."
+
+#: mediagoblin/auth/views.py:333
+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:40
+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:44
+msgid ""
+"You can use\n"
+" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n"
+" Markdown</a> for formatting."
+msgstr "ביכולתך להשתמש בתחביר\n <a href=\"http://daringfireball.net/projects/markdown/basics\">\n 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 "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: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:43
+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/views.py:65
+msgid "An entry with that slug already exists for this user."
+msgstr "רשומה ×¢× ×—×©×•×¤×™×ª זו כבר קיימת עבור משתמש ×–×”."
+
+#: mediagoblin/edit/views.py:86
+msgid "You are editing another user's media. Proceed with caution."
+msgstr "×תה עורך מדיה של משתמש ×חר. המשך בזהירות."
+
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr "הוספת ×ת התצריף %s!"
+
+#: mediagoblin/edit/views.py:181
+msgid "You are editing a user's profile. Proceed with caution."
+msgstr "×תה עורך דיוקן של משתמש. המשך בזהירות."
+
+#: mediagoblin/edit/views.py:197
+msgid "Profile changes saved"
+msgstr "שינויי דיוקן נשמרו"
+
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
+msgid "Account settings saved"
+msgstr "הגדרות חשבון נשמרו"
+
+#: mediagoblin/edit/views.py:251
+msgid "Wrong password"
+msgstr "סיסמה שגויה"
+
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
+#, python-format
+msgid "You already have a collection called \"%s\"!"
+msgstr "כבר יש לך ×וסף שקרוי ×‘×©× \"%s\"!"
+
+#: mediagoblin/edit/views.py:291
+msgid "A collection with that slug already exists for this user."
+msgstr "×וסף ×¢× ×—×©×•×¤×™×ª זו כבר ×§×™×™× ×¢×‘×•×¨ משתמש ×–×”."
+
+#: mediagoblin/edit/views.py:308
+msgid "You are editing another user's collection. Proceed with caution."
+msgstr "×תה עורך ×וסף של משתמש ×חר. המשך בזהירות."
+
+#: mediagoblin/gmg_commands/theme.py:58
+msgid "Cannot link theme... no theme set\n"
+msgstr "×œ× × ×™×ª×Ÿ לקשר ×ל מוטיב... ×œ× ×”×•×’×“×¨ מוטיב\n"
+
+#: mediagoblin/gmg_commands/theme.py:71
+msgid "No asset directory for this theme\n"
+msgstr "×ין מדור נכס עבור מוטיב ×–×”\n"
+
+#: mediagoblin/gmg_commands/theme.py:74
+msgid "However, old link directory symlink found; removed.\n"
+msgstr "בכל ×ופן, קישור מדור symlink נמצ×; הוסר.\n"
+
+#: mediagoblin/media_types/__init__.py:60
+#: mediagoblin/media_types/__init__.py:101
+msgid "Sorry, I don't support that file type :("
+msgstr "צר לי, ××™× × ×™ תומך בטיפוס קובץ ×–×” :("
+
+#: mediagoblin/media_types/video/processing.py:35
+msgid "Video transcoding failed"
+msgstr "המרת ויד×ו נכשלה"
+
+#: mediagoblin/plugins/oauth/forms.py:26
+msgid "Client ID"
+msgstr "זהות לקוח"
+
+#: mediagoblin/plugins/oauth/forms.py:28
+msgid "Next URL"
+msgstr "כתובת ב××”"
+
+#: mediagoblin/plugins/oauth/forms.py:30
+msgid "Allow"
+msgstr "התר"
+
+#: mediagoblin/plugins/oauth/forms.py:31
+msgid "Deny"
+msgstr "×סור"
+
+#: mediagoblin/plugins/oauth/forms.py:35
+msgid "Name"
+msgstr "ש×"
+
+#: mediagoblin/plugins/oauth/forms.py:36
+msgid "The name of the OAuth client"
+msgstr "×”×©× ×©×œ לקוח OAuth"
+
+#: mediagoblin/plugins/oauth/forms.py:37
+msgid "Description"
+msgstr "תי×ור"
+
+#: mediagoblin/plugins/oauth/forms.py:39
+msgid ""
+"This will be visible to users allowing your\n"
+" application to authenticate as them."
+msgstr ""
+
+#: mediagoblin/plugins/oauth/forms.py:41
+msgid "Type"
+msgstr "טיפוס"
+
+#: mediagoblin/plugins/oauth/forms.py:46
+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> - הלקוח יכול\n ליצור בקשות ×ל שרת GNU MediaGoblin ×©×œ× ×™×›×•×œ×•×ª להיבל×\n על ידי user agent (למשל לקוח server-side).<br />\n <strong>פומבי</strong> - הלקוח ×œ× ×™×›×•×œ ליצור בקשות\n סודיות ×ל של GNU MediaGoblin (למשל לקוח\n ‫JavaScript מתופעל client-side)."
+
+#: mediagoblin/plugins/oauth/forms.py:53
+msgid "Redirect URI"
+msgstr ""
+
+#: mediagoblin/plugins/oauth/forms.py:55
+msgid ""
+"The redirect URI for the applications, this field\n"
+" is <strong>required</strong> for public clients."
+msgstr ""
+
+#: mediagoblin/plugins/oauth/forms.py:67
+msgid "This field is required for public clients"
+msgstr "שדה ×–×” הינו דרוש עבור לקוחות פומביי×"
+
+#: mediagoblin/plugins/oauth/views.py:60
+msgid "The client {0} has been registered!"
+msgstr "הלקוח {0} נרש×!"
+
+#: mediagoblin/processing/__init__.py:138
+msgid "Invalid file given for media type."
+msgstr "ניתן קובץ שגוי עבור טיפוס מדיה."
+
+#: mediagoblin/submit/forms.py:26
+msgid "File"
+msgstr "קובץ"
+
+#: mediagoblin/submit/views.py:57
+msgid "You must provide a file."
+msgstr "עליך לספק קובץ."
+
+#: mediagoblin/submit/views.py:164
+msgid "Woohoo! Submitted!"
+msgstr "הידד! נשלח!"
+
+#: mediagoblin/submit/views.py:215
+#, python-format
+msgid "Collection \"%s\" added!"
+msgstr "×וסף \"%s\" התווסף!"
+
+#: mediagoblin/templates/mediagoblin/base.html:48
+msgid "MediaGoblin logo"
+msgstr "לוגו MediaGoblin"
+
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, 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:60
+msgid "log out"
+msgstr "התנתקות"
+
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
+msgstr "הוספת מדיה"
+
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
+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:87
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
+"href=\"http://gnu.org/\">GNU</a> project."
+msgstr "מופעל על ידי <a href=\"http://mediagoblin.org\">MediaGoblin</a>, פרויקט <a href=\"http://gnu.org/\">GNU</a>."
+
+#: mediagoblin/templates/mediagoblin/base.html:90
+#, 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:25
+msgid "Actions"
+msgstr "פעולות"
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr "צור ×וסף חדש"
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr "שנה הגדרות חשבון"
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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/root.html:51
+msgid "Explore"
+msgstr "לחקור"
+
+#: mediagoblin/templates/mediagoblin/root.html:53
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "×©×œ×•× ×œ×š, ברוך בו×ך ×ל ×תר MediaGoblin ×–×”!"
+
+#: mediagoblin/templates/mediagoblin/root.html:55
+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:56
+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:58
+msgid "Don't have one yet? It's easy!"
+msgstr "×ין ברשותך חשבון עדיין? ×–×” קל!"
+
+#: mediagoblin/templates/mediagoblin/root.html:59
+#, 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:67
+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\n%(verification_url)s\n\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\n%(verification_url)s"
+
+#: 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:43
+#: 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:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr "הוספת תצריף"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
+msgid "Cancel"
+msgstr "ביטול"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
+#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
+msgid "Save changes"
+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_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:35
+#, 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/stl.html:136
+#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
+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 "צר לי, ×ודיו ×–×” ×œ× ×™×¢×‘×•×“ מכיוון \n\tשדפדפן הרשת שלך ×œ× ×ª×•×ž×š \n\t×ודיו של 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 "ביכולתך להשיג דפדפן רשת מודרני שכן \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/video.html:56
+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/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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr "תמונה עבור %(media_title)s"
+
+#: 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 ""
+
+#: 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:40
+msgid ""
+"Sorry, this video will not work because \n"
+"\t your web browser does not support HTML5 \n"
+"\t video."
+msgstr "צר לי, ויד×ו ×–×” ×œ× ×™×¢×‘×•×“ מכיוון \n\t שדפדפן הרשת שלך ×œ× ×ª×•×ž×š \n\t ויד×ו של HTML5."
+
+#: mediagoblin/templates/mediagoblin/media_displays/video.html:43
+msgid ""
+"You can get a modern web browser that \n"
+"\t can play this video 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>!"
+
+#: mediagoblin/templates/mediagoblin/media_displays/video.html:59
+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/collection.html:30
+#: mediagoblin/templates/mediagoblin/submit/start.html:34
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
+msgid "Add"
+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 מ×ת <a href=\"%(user_url)s\">%(username)s</a>"
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:87
+msgid "Edit"
+msgstr "ערוך"
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:91
+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_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+msgid "Delete permanently"
+msgstr "מחק לצמיתות"
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:31
+#, python-format
+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
+msgid "Remove"
+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 "×©×œ×•× %(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 "המדיה של %(username)s"
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:37
+#, 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:46
+#, 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:102
+msgid "Add a comment"
+msgstr "הוסף תגובה"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:109
+msgid ""
+"You can use <a "
+"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for"
+" formatting."
+msgstr "ביכולתך לעשות שימוש בתחביר <a href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> לעיצוב."
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:113
+msgid "Add this comment"
+msgstr "הוסף ×ת תגובה זו"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+msgid "at"
+msgstr "×צל"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#, python-format
+msgid ""
+"<h3>Added on</h3>\n"
+" <p>%(date)s</p>"
+msgstr "<h3>הוסף בת×ריך</h3>\n <p>%(date)s</p>"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
+msgstr "הוסף מדיה ל×וסף"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
+#, python-format
+msgid "Add %(title)s to collection"
+msgstr "הוסף ×ת %(title)s ל×וסף"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
+msgid "+"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
+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:101
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:118
+msgid "Edit profile"
+msgstr "ערוך דיוקן"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:106
+msgid "This user hasn't filled in their profile (yet)."
+msgstr "משתמש ×–×” ×œ× ×ž×™×œ× ×“×™×•×§×Ÿ (עדיין)."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
+#, python-format
+msgid "View all of %(username)s's media"
+msgstr "צפיה בכל המדיה של %(username)s"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
+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:157
+#: 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:20
+#, python-format
+msgid "In collections (%(collected)s)"
+msgstr "ב××•×¡×¤×™× (%(collected)s)"
+
+#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
+msgid "feed icon"
+msgstr "צלמית ערוץ"
+
+#: mediagoblin/templates/mediagoblin/utils/feed_link.html:23
+msgid "Atom feed"
+msgstr "ערוץ Atom"
+
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:25
+msgid "Location"
+msgstr "מיקו×"
+
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
+#, python-format
+msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
+msgstr "הצגה ×צל <a href=\"%(osm_url)s\">OpenStreetMap</a>"
+
+#: 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:78
+msgid "Could not read the image file."
+msgstr "×œ× ×”×™×” ניתן ×œ×§×¨×•× ×ת קובץ התמונה."
+
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr "×ופס!"
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr "×ירעה שגי××”"
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr "פעולה ×œ× ×ž×•×¨×©×™×ª"
+
+#: mediagoblin/tools/response.py:47
+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:55
+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/user_pages/forms.py:28
+msgid "I am sure I want to delete this"
+msgstr "×× ×™ בטוח שברצוני למחוק ×–×ת"
+
+#: mediagoblin/user_pages/forms.py:32
+msgid "I am sure I want to remove this item from the collection"
+msgstr "×× ×™ בטוח שברצוני להסיר ×ת פריט ×–×” מן ×”×וסף"
+
+#: mediagoblin/user_pages/forms.py:35
+msgid "-- Select --"
+msgstr "-- בחר --"
+
+#: mediagoblin/user_pages/forms.py:37
+msgid "Include a note"
+msgstr "הכללת פתק"
+
+#: mediagoblin/user_pages/lib.py:56
+msgid "commented on your post"
+msgstr "הגיב/ה על פרסומך"
+
+#: mediagoblin/user_pages/views.py:156
+msgid "Oops, your comment was empty."
+msgstr "×ופס, תגובתך היתה ריקה."
+
+#: mediagoblin/user_pages/views.py:162
+msgid "Your comment has been posted!"
+msgstr "תגובתך פורסמה!"
+
+#: mediagoblin/user_pages/views.py:230
+msgid "You have to select or add a collection"
+msgstr "עליך לבחור ×ו להוסיף ×וסף"
+
+#: mediagoblin/user_pages/views.py:238
+#, python-format
+msgid "\"%s\" already in collection \"%s\""
+msgstr "\"%s\" כבר ×§×™×™× ×‘×וסף \"%s\""
+
+#: mediagoblin/user_pages/views.py:253
+#, python-format
+msgid "\"%s\" added to collection \"%s\""
+msgstr "\"%s\" התווסף ×ל ×”×וסף \"%s\""
+
+#: mediagoblin/user_pages/views.py:261
+msgid "Please check your entries and try again."
+msgstr "×× × ×‘×“×•×§ ×ת רשומותיך ונסה שוב."
+
+#: mediagoblin/user_pages/views.py:292
+msgid ""
+"Some of the files with this entry seem to be missing. Deleting anyway."
+msgstr "נר××” שכמה ×§×‘×¦×™× ×¢× ×¨×™×©×•× ×–×” חסרי×. מוחק בכל ×–×ת"
+
+#: mediagoblin/user_pages/views.py:297
+msgid "You deleted the media."
+msgstr "מחקת ×ת מדיה זו."
+
+#: mediagoblin/user_pages/views.py:304
+msgid "The media was not deleted because you didn't check that you were sure."
+msgstr "המדיה ×œ× × ×ž×—×§×” מכיוון ×©×œ× ×¡×™×ž× ×ª ש×תה בטוח."
+
+#: mediagoblin/user_pages/views.py:312
+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:384
+msgid ""
+"You are about to delete an item from another user's collection. Proceed with"
+" caution."
+msgstr "בחרת למחוק פריט מן ×וסף של משתמש ×חר. המשך בזהירות."
+
+#: mediagoblin/user_pages/views.py:417
+#, python-format
+msgid "You deleted the collection \"%s\""
+msgstr "מחקת ×ת ×”×וסף \"%s\""
+
+#: mediagoblin/user_pages/views.py:424
+msgid ""
+"The collection was not deleted because you didn't check that you were sure."
+msgstr "×”×וסף ×œ× ×”×•×¡×¨ מכיוון ×©×œ× ×¡×™×ž× ×ª ש×תה בטוח."
+
+#: mediagoblin/user_pages/views.py:434
+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 b55044f7..32ec1bc2 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 d16e0022..34f97df5 100644
--- a/mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.po
@@ -9,8 +9,8 @@ msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2012-09-24 14:01-0500\n"
-"PO-Revision-Date: 2012-09-24 18:57+0000\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 15:14+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
@@ -93,7 +93,7 @@ msgstr ""
msgid "You can now log in using your new password."
msgstr ""
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:83
+#: 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:40
msgid "Title"
@@ -104,7 +104,7 @@ msgid "Description of this work"
msgstr ""
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:87 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:44
msgid ""
"You can use\n"
@@ -120,11 +120,11 @@ msgstr "Etiquettas"
msgid "Separate tags by commas."
msgstr ""
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:91
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr ""
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:92
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr ""
@@ -163,20 +163,20 @@ msgstr ""
msgid "New password"
msgstr ""
-#: mediagoblin/edit/forms.py:72
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr ""
-#: mediagoblin/edit/forms.py:84
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:43
msgid "Description of this collection"
msgstr ""
-#: mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
@@ -190,33 +190,38 @@ msgstr ""
msgid "You are editing another user's media. Proceed with caution."
msgstr ""
-#: mediagoblin/edit/views.py:182
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr ""
+
+#: mediagoblin/edit/views.py:181
msgid "You are editing a user's profile. Proceed with caution."
msgstr ""
-#: mediagoblin/edit/views.py:198
+#: mediagoblin/edit/views.py:197
msgid "Profile changes saved"
msgstr ""
-#: mediagoblin/edit/views.py:227 mediagoblin/edit/views.py:247
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
msgid "Account settings saved"
msgstr ""
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:251
msgid "Wrong password"
msgstr ""
-#: mediagoblin/edit/views.py:288 mediagoblin/submit/views.py:211
-#: mediagoblin/user_pages/views.py:215
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr ""
-#: mediagoblin/edit/views.py:292
+#: mediagoblin/edit/views.py:291
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:309
+#: mediagoblin/edit/views.py:308
msgid "You are editing another user's collection. Proceed with caution."
msgstr ""
@@ -233,7 +238,7 @@ msgid "However, old link directory symlink found; removed.\n"
msgstr ""
#: mediagoblin/media_types/__init__.py:60
-#: mediagoblin/media_types/__init__.py:120
+#: mediagoblin/media_types/__init__.py:101
msgid "Sorry, I don't support that file type :("
msgstr ""
@@ -303,7 +308,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:60
msgid "The client {0} has been registered!"
msgstr ""
@@ -328,62 +333,43 @@ msgstr ""
msgid "Collection \"%s\" added!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/404.html:24
-msgid "Image of 404 goblin stressing out"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/404.html:25
-msgid "Oops!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/404.html:26
-msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/404.html:28
-msgid ""
-"If you're sure the address is correct, maybe the page you're looking for has"
-" been moved or deleted."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:50
+#: mediagoblin/templates/mediagoblin/base.html:48
msgid "MediaGoblin logo"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:60
-msgid "Verify your email!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:66
-msgid "+ Add media"
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:67
-msgid "+ Add collection"
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:69
-msgid "View your profile"
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:70
-msgid "Log out"
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:75
+#: 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:89
+#: mediagoblin/templates/mediagoblin/base.html:87
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project."
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:92
+#: mediagoblin/templates/mediagoblin/base.html:90
#, python-format
msgid ""
"Released under the <a "
@@ -391,31 +377,56 @@ msgid ""
"href=\"%(source_link)s\">Source code</a> available."
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:24
+#: mediagoblin/templates/mediagoblin/error.html:24
+msgid "Image of goblin stressing out"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:25
+msgid "Actions"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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/root.html:51
msgid "Explore"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:26
+#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Hi there, welcome to this MediaGoblin site!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/root.html:55
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:29
+#: mediagoblin/templates/mediagoblin/root.html:56
msgid ""
"To add your own media, place comments, and more, you can log in with your "
"MediaGoblin account."
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:31
+#: mediagoblin/templates/mediagoblin/root.html:58
msgid "Don't have one yet? It's easy!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:32
+#: mediagoblin/templates/mediagoblin/root.html:59
#, python-format
msgid ""
"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
@@ -423,17 +434,10 @@ msgid ""
" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:40
+#: mediagoblin/templates/mediagoblin/root.html:67
msgid "Most recent media"
msgstr ""
-#: 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/admin/panel.html:29
msgid ""
"Here you can track the state of media being processed on this instance."
@@ -542,30 +546,43 @@ msgstr ""
msgid "Editing attachments for %(media_title)s"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit.html:23
-#: mediagoblin/templates/mediagoblin/edit/edit.html:35
-#, python-format
-msgid "Editing %(media_title)s"
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:43
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
+msgid "Attachments"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:53
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
msgid "Cancel"
msgstr "Cancellar"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:43
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
msgid "Save changes"
msgstr ""
+#: mediagoblin/templates/mediagoblin/edit/edit.html:23
+#: mediagoblin/templates/mediagoblin/edit/edit.html:35
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:41
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
#, python-format
msgid "Changing %(username)s's account settings"
msgstr ""
@@ -591,13 +608,12 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:23
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
msgid "Download"
msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:27
msgid "Original"
msgstr ""
@@ -624,6 +640,56 @@ msgstr ""
msgid "WebM file (Vorbis codec)"
msgstr ""
+#: 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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr ""
+
+#: 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 ""
+
+#: 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:40
msgid ""
"Sorry, this video will not work because \n"
@@ -648,7 +714,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
#: mediagoblin/templates/mediagoblin/submit/start.html:34
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:83
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
msgid "Add"
msgstr ""
@@ -677,14 +743,6 @@ msgstr ""
msgid "Delete"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection.html:59
-#, python-format
-msgid ""
-"<p>\n"
-" %(collection_description)s\n"
-" </p>"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
@@ -692,7 +750,7 @@ msgid "Really delete %(title)s?"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr ""
@@ -701,7 +759,7 @@ msgstr ""
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
msgid "Remove"
msgstr ""
@@ -727,12 +785,6 @@ msgstr ""
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:67
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
-#, python-format
-msgid "Image for %(media_title)s"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
msgid "Add a comment"
msgstr ""
@@ -759,13 +811,8 @@ msgid ""
" <p>%(date)s</p>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
-msgid "Attachments"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
-msgid "Add attachment"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
@@ -773,11 +820,11 @@ msgstr ""
msgid "Add %(title)s to collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
msgid "+"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
msgid "Add a new collection"
msgstr ""
@@ -848,41 +895,25 @@ msgstr ""
msgid "This user hasn't filled in their profile (yet)."
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:125
-msgid "Change account settings"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:138
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
#, python-format
msgid "View all of %(username)s's media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
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:157
-msgid "Add media"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:163
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:87
-#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:72
+#: 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:39
-#, python-format
-msgid ""
-"<br />\n"
-" <a href=\"%(entry_url)s\">%(note)s</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:47
-#, python-format
-msgid "<br /><a href=\"%(remove_url)s\" class=\"remove\">(remove)</a>"
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
msgstr ""
#: mediagoblin/templates/mediagoblin/utils/collections.html:20
@@ -902,7 +933,7 @@ msgstr ""
msgid "Location"
msgstr ""
-#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:38
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
#, python-format
msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
msgstr ""
@@ -941,6 +972,32 @@ msgstr ""
msgid "Could not read the image file."
msgstr ""
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr ""
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr ""
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr ""
+
+#: mediagoblin/tools/response.py:47
+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:55
+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/user_pages/forms.py:28
msgid "I am sure I want to delete this"
msgstr ""
@@ -961,74 +1018,74 @@ msgstr ""
msgid "commented on your post"
msgstr ""
-#: mediagoblin/user_pages/views.py:161
+#: mediagoblin/user_pages/views.py:156
msgid "Oops, your comment was empty."
msgstr ""
-#: mediagoblin/user_pages/views.py:167
+#: mediagoblin/user_pages/views.py:162
msgid "Your comment has been posted!"
msgstr ""
-#: mediagoblin/user_pages/views.py:235
+#: mediagoblin/user_pages/views.py:230
msgid "You have to select or add a collection"
msgstr ""
-#: mediagoblin/user_pages/views.py:243
+#: mediagoblin/user_pages/views.py:238
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:258
+#: mediagoblin/user_pages/views.py:253
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:266
+#: mediagoblin/user_pages/views.py:261
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:297
+#: mediagoblin/user_pages/views.py:292
msgid ""
"Some of the files with this entry seem to be missing. Deleting anyway."
msgstr ""
-#: mediagoblin/user_pages/views.py:302
+#: mediagoblin/user_pages/views.py:297
msgid "You deleted the media."
msgstr ""
-#: mediagoblin/user_pages/views.py:309
+#: mediagoblin/user_pages/views.py:304
msgid "The media was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:317
+#: mediagoblin/user_pages/views.py:312
msgid "You are about to delete another user's media. Proceed with caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr ""
-#: mediagoblin/user_pages/views.py:383
+#: 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:393
+#: mediagoblin/user_pages/views.py:384
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:426
+#: mediagoblin/user_pages/views.py:417
#, python-format
msgid "You deleted the collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:433
+#: mediagoblin/user_pages/views.py:424
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:443
+#: mediagoblin/user_pages/views.py:434
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
new file mode 100644
index 00000000..23f9f1bf
--- /dev/null
+++ 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
new file mode 100644
index 00000000..04a1f7f6
--- /dev/null
+++ b/mediagoblin/i18n/is_IS/LC_MESSAGES/mediagoblin.po
@@ -0,0 +1,1090 @@
+# Translations template for PROJECT.
+# Copyright (C) 2012 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+#
+# Translators:
+# <tryggvib@fsfi.is>, 2012.
+msgid ""
+msgstr ""
+"Project-Id-Version: GNU MediaGoblin\n"
+"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 15:14+0000\n"
+"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 0.9.6\n"
+"Language: is_IS\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:41
+msgid "Username"
+msgstr "Notandanafn"
+
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+msgid "Password"
+msgstr "Lykilorð"
+
+#: mediagoblin/auth/forms.py:34
+msgid "Email address"
+msgstr "Netfang"
+
+#: mediagoblin/auth/forms.py:51
+msgid "Username or email"
+msgstr "Notandanafn eða netfang"
+
+#: mediagoblin/auth/forms.py:58
+msgid "Incorrect input"
+msgstr "Ógild innsending"
+
+#: mediagoblin/auth/views.py:55
+msgid "Sorry, registration is disabled on this instance."
+msgstr "Því miður er nýskráning ekki leyfð á þessu svæði."
+
+#: mediagoblin/auth/views.py:75
+msgid "Sorry, a user with that name already exists."
+msgstr "Því miður er nú þegar til notandi með þetta nafn."
+
+#: mediagoblin/auth/views.py:79
+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: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:188
+msgid "The verification key or user id is incorrect"
+msgstr "Staðfestingarlykillinn eða notendaauðkennið er rangt"
+
+#: 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:214
+msgid "You've already verified your email address!"
+msgstr "Þú hefur staðfest netfangið þitt!"
+
+#: mediagoblin/auth/views.py:227
+msgid "Resent your verification email."
+msgstr "Endursendi staðfestingartölvupóst"
+
+#: mediagoblin/auth/views.py:263
+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:273
+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:285
+msgid "Couldn't find someone with that username or email."
+msgstr "Gat ekki fundið neinn með það notandanafn eða lykilorð."
+
+#: mediagoblin/auth/views.py:333
+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:82
+#: mediagoblin/submit/forms.py:28 mediagoblin/submit/forms.py:47
+#: mediagoblin/user_pages/forms.py:40
+msgid "Title"
+msgstr "Titill"
+
+#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31
+msgid "Description of this work"
+msgstr "Lýsing á þessu efni"
+
+#: 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:44
+msgid ""
+"You can use\n"
+" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n"
+" Markdown</a> for formatting."
+msgstr "Þú getur notað\n <a href=\"http://daringfireball.net/projects/markdown/basics\">\n Markdown</a> til að stílgera textann."
+
+#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36
+msgid "Tags"
+msgstr "Efnisorð"
+
+#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38
+msgid "Separate tags by commas."
+msgstr "Aðskildu efnisorðin með kommum."
+
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
+msgid "Slug"
+msgstr "Vefslóðarormur"
+
+#: 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"
+
+#: mediagoblin/edit/forms.py:40
+msgid ""
+"The title part of this media's address. You usually don't need to change "
+"this."
+msgstr "Titilhlutinn í vefslóð þessa efnis. Þú þarft vanalega ekki að breyta þessu."
+
+#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41
+#: mediagoblin/templates/mediagoblin/utils/license.html:20
+msgid "License"
+msgstr "Leyfi"
+
+#: mediagoblin/edit/forms.py:50
+msgid "Bio"
+msgstr "Lýsing"
+
+#: mediagoblin/edit/forms.py:56
+msgid "Website"
+msgstr "Vefsíða"
+
+#: mediagoblin/edit/forms.py:58
+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: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:83
+msgid "The title can't be empty"
+msgstr "Þessi titill getur verið innihaldslaus"
+
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
+#: mediagoblin/user_pages/forms.py:43
+msgid "Description of this collection"
+msgstr "Lýsing á þessu albúmi"
+
+#: 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:65
+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."
+
+#: mediagoblin/edit/views.py:86
+msgid "You are editing another user's media. Proceed with caution."
+msgstr "Þú ert að breyta efni annars notanda. Farðu mjög varlega."
+
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr "Þú bættir við viðhenginu %s!"
+
+#: mediagoblin/edit/views.py:181
+msgid "You are editing a user's profile. Proceed with caution."
+msgstr "Þú ert að breyta kenniskrá notanda. Farðu mjög varlega."
+
+#: mediagoblin/edit/views.py:197
+msgid "Profile changes saved"
+msgstr "Breytingar á kenniskrá vistaðar"
+
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
+msgid "Account settings saved"
+msgstr "Aðgangsstillingar vistaðar"
+
+#: mediagoblin/edit/views.py:251
+msgid "Wrong password"
+msgstr "Vitlaust lykilorð"
+
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
+#, python-format
+msgid "You already have a collection called \"%s\"!"
+msgstr "Þú hefur nú þegar albúm sem kallast \"%s\"!"
+
+#: mediagoblin/edit/views.py:291
+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:308
+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
+msgid "Cannot link theme... no theme set\n"
+msgstr "Get ekki hlekkjað í þema... ekkert þema stillt\n"
+
+#: mediagoblin/gmg_commands/theme.py:71
+msgid "No asset directory for this theme\n"
+msgstr "Engin eignamappa fyrir þetta þema\n"
+
+#: mediagoblin/gmg_commands/theme.py:74
+msgid "However, old link directory symlink found; removed.\n"
+msgstr "Fann samt gamlan táknrænan tengil á möppu; fjarlægður.\n"
+
+#: mediagoblin/media_types/__init__.py:60
+#: mediagoblin/media_types/__init__.py:101
+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:35
+msgid "Video transcoding failed"
+msgstr "Myndbandsþverkótun mistókst"
+
+#: mediagoblin/plugins/oauth/forms.py:26
+msgid "Client ID"
+msgstr "Auðkenni biðlara"
+
+#: mediagoblin/plugins/oauth/forms.py:28
+msgid "Next URL"
+msgstr "Næsta vefslóð"
+
+#: mediagoblin/plugins/oauth/forms.py:30
+msgid "Allow"
+msgstr "Leyfa"
+
+#: mediagoblin/plugins/oauth/forms.py:31
+msgid "Deny"
+msgstr "Banna"
+
+#: mediagoblin/plugins/oauth/forms.py:35
+msgid "Name"
+msgstr "Nafn"
+
+#: mediagoblin/plugins/oauth/forms.py:36
+msgid "The name of the OAuth client"
+msgstr "Nafn OAuth biðlarans"
+
+#: mediagoblin/plugins/oauth/forms.py:37
+msgid "Description"
+msgstr "Lýsing"
+
+#: mediagoblin/plugins/oauth/forms.py:39
+msgid ""
+"This will be visible to users allowing your\n"
+" application to authenticate as them."
+msgstr "Þetta verður sýnilegt öðrum notendum sem leyfir\n forritinu þínu að skrá sig inn sem þeir."
+
+#: mediagoblin/plugins/oauth/forms.py:41
+msgid "Type"
+msgstr "Tegund"
+
+#: mediagoblin/plugins/oauth/forms.py:46
+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>Trúnaður</strong> - Biðlarinn getur\n sent beiðnir til GNU MediaGoblin vefsvæðisins sem geta ekki verið\n truflaðar af notandaforriti (t.d. forriti á vefþjóni).<br />\n <strong>Opinbert</strong> - Biðlarinn getur ekki gert trúnaðarbundnar\n beiðnir til GNU MediaGoblin vefsvæðisins (t.d. Javascript biðlara\n hjá notanda)."
+
+#: mediagoblin/plugins/oauth/forms.py:53
+msgid "Redirect URI"
+msgstr "Ãframsendingarvefslóð"
+
+#: mediagoblin/plugins/oauth/forms.py:55
+msgid ""
+"The redirect URI for the applications, this field\n"
+" is <strong>required</strong> for public clients."
+msgstr "Ãframsendingarvefslóðin fyrir forritin, þessi reitur\n er <strong>nauðsynlegur</strong> fyrir opinbera biðlara."
+
+#: mediagoblin/plugins/oauth/forms.py:67
+msgid "This field is required for public clients"
+msgstr "Þessi reitur er nauðsynlegur fyrir opinbera biðlara"
+
+#: mediagoblin/plugins/oauth/views.py:60
+msgid "The client {0} has been registered!"
+msgstr "Biðlarinn {0} hefur verið skráður!"
+
+#: mediagoblin/processing/__init__.py:138
+msgid "Invalid file given for media type."
+msgstr "Ógild skrá gefin fyrir þessa margmiðlunartegund."
+
+#: mediagoblin/submit/forms.py:26
+msgid "File"
+msgstr "Skrá"
+
+#: mediagoblin/submit/views.py:57
+msgid "You must provide a file."
+msgstr "Þú verður að gefa upp skrá."
+
+#: mediagoblin/submit/views.py:164
+msgid "Woohoo! Submitted!"
+msgstr "Jibbí jei! Það tókst að senda inn!"
+
+#: mediagoblin/submit/views.py:215
+#, python-format
+msgid "Collection \"%s\" added!"
+msgstr "Albúmið \"%s\" var búið til!"
+
+#: mediagoblin/templates/mediagoblin/base.html:48
+msgid "MediaGoblin logo"
+msgstr "MediaGoblin einkennismerkið"
+
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, 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>"
+
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
+msgstr "útskrá"
+
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
+msgstr "Senda inn efni"
+
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
+msgstr "Staðfestu netfangið þitt!"
+
+#: 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"
+
+#: mediagoblin/templates/mediagoblin/base.html:87
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
+"href=\"http://gnu.org/\">GNU</a> project."
+msgstr "Keyrt af <a href=\"http://mediagoblin.org\">MediaGoblin</a>, sem er <a href=\"http://gnu.org/\">GNU</a> verkefni."
+
+#: mediagoblin/templates/mediagoblin/base.html:90
+#, 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:25
+msgid "Actions"
+msgstr "Aðgerðir"
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr "Búa til nýtt albúm"
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr "Breyta stillingum notandaaðgangs"
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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 "Margmiðlunarvinnsluskiki"
+
+#: mediagoblin/templates/mediagoblin/root.html:51
+msgid "Explore"
+msgstr "Skoða"
+
+#: mediagoblin/templates/mediagoblin/root.html:53
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "Hæ! Gakktu í bæinn á þetta MediaGoblin vefsvæði!"
+
+#: mediagoblin/templates/mediagoblin/root.html:55
+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:56
+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:58
+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:59
+#, 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:67
+msgid "Most recent media"
+msgstr "Nýlegt efni"
+
+#: mediagoblin/templates/mediagoblin/admin/panel.html:29
+msgid ""
+"Here you can track the state of media being processed on this instance."
+msgstr "Hér getur þú fylgst með margmiðlunarefni sem verið er að vinna á þessu vefsvæði."
+
+#: mediagoblin/templates/mediagoblin/admin/panel.html:32
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32
+msgid "Media in-processing"
+msgstr "Efni í vinnslu"
+
+#: mediagoblin/templates/mediagoblin/admin/panel.html:58
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56
+msgid "No media in-processing"
+msgstr "Ekkert efni í vinnslu"
+
+#: mediagoblin/templates/mediagoblin/admin/panel.html:61
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59
+msgid "These uploads failed to process:"
+msgstr "Það mistókst að fullvinna þessar innsendingar:"
+
+#: mediagoblin/templates/mediagoblin/admin/panel.html:90
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86
+msgid "No failed entries!"
+msgstr "Engar bilaðar innsendingar!"
+
+#: mediagoblin/templates/mediagoblin/admin/panel.html:92
+msgid "Last 10 successful uploads"
+msgstr "Síðustu 10 árangursríku innsendingarnar"
+
+#: mediagoblin/templates/mediagoblin/admin/panel.html:112
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107
+msgid "No processed entries, yet!"
+msgstr "Ekkert fullunnið efni enn!"
+
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36
+msgid "Set your new password"
+msgstr "Skrifaðu inn nýja lykilorðið þitt"
+
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:39
+msgid "Set password"
+msgstr "Skrá lykilorð"
+
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:23
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:31
+msgid "Recover password"
+msgstr "Endurstilla lykilorð"
+
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:34
+msgid "Send instructions"
+msgstr "Senda leiðbeiningar"
+
+#: 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 "Hæ %(username)s,\n\ntil að breyta GNU MediaGoblin lykilorðinu þínu opnar þú eftirfarandi vefslóð í \nvafranum þínum:\n\n%(verification_url)s\n\nEf þú heldur að það sé einhver vitleysa í gangi husnar þú bara þennan póst og heldur áfram að vera\nánægður durtur!"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:39
+msgid "Logging in failed!"
+msgstr "Mistókst að skrá þig inn."
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:44
+msgid "Don't have an account yet?"
+msgstr "Ertu ekki með notendaaðgang?"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:45
+msgid "Create one here!"
+msgstr "Búðu til aðgang hérna!"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:51
+msgid "Forgot your password?"
+msgstr "Gleymdirðu lykilorðinu þínu?"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:28
+#: mediagoblin/templates/mediagoblin/auth/register.html:36
+msgid "Create an account!"
+msgstr "Búðu til nýjan aðgang!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:40
+msgid "Create"
+msgstr "Búa til"
+
+#: 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 "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/edit/attachments.html:23
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:35
+#, python-format
+msgid "Editing attachments for %(media_title)s"
+msgstr "Breyti viðhengjum við: %(media_title)s"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:43
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
+msgid "Attachments"
+msgstr "Viðhengi"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr "Bæta við viðhengi"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
+msgid "Cancel"
+msgstr "Hætta við"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
+#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
+msgid "Save changes"
+msgstr "Vista breytingar"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:23
+#: mediagoblin/templates/mediagoblin/edit/edit.html:35
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "Breyti %(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 "Breyti notandaaðgangsstillingum fyrir: %(username)s"
+
+#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29
+#, python-format
+msgid "Editing %(collection_title)s"
+msgstr "Breyti %(collection_title)s"
+
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:23
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
+#, python-format
+msgid "Editing %(username)s's profile"
+msgstr "Breyti kenniskrá notandans: %(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 "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/stl.html:136
+#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
+msgid "Download"
+msgstr "Sækja af Netinu"
+
+#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
+msgid "Original"
+msgstr "Upphafleg skrá"
+
+#: 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 "Því miður mun þessi hljóðskrá ekki virka því \n\tvafrinn þinn styður ekki HTML5 \n\thljóðskrár."
+
+#: 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 "Þú 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/video.html:56
+msgid "Original file"
+msgstr "Upphaflega skráin"
+
+#: mediagoblin/templates/mediagoblin/media_displays/audio.html:63
+msgid "WebM file (Vorbis codec)"
+msgstr "WebM skrá (Vorbis víxlþjöppun)"
+
+#: 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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr "Mynd fyrir %(media_title)s"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
+msgid "Toggle Rotate"
+msgstr "Stilla snúning af eða á"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113
+msgid "Perspective"
+msgstr "Sjónhorf"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117
+msgid "Front"
+msgstr "Framhlið"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121
+msgid "Top"
+msgstr "Toppur"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125
+msgid "Side"
+msgstr "Hlið"
+
+#: 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 "Hala niður líkani"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146
+msgid "File Format"
+msgstr "Skráarsnið"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148
+msgid "Object Height"
+msgstr "Hæð hlutar"
+
+#: mediagoblin/templates/mediagoblin/media_displays/video.html:40
+msgid ""
+"Sorry, this video will not work because \n"
+"\t your web browser does not support HTML5 \n"
+"\t video."
+msgstr "Því miður mun þetta myndband ekki virka vegna þess að \n\t vafrinn þinn styður ekki HTML5 \n\t myndbönd."
+
+#: mediagoblin/templates/mediagoblin/media_displays/video.html:43
+msgid ""
+"You can get a modern web browser that \n"
+"\t can play this video at <a href=\"http://getfirefox.com\">\n"
+"\t http://getfirefox.com</a>!"
+msgstr "Þú getur náð í nýlegan vafra sem \n\t getur spilað þetta myndband á <a href=\"http://getfirefox.com\">\n\t http://getfirefox.com</a>!"
+
+#: mediagoblin/templates/mediagoblin/media_displays/video.html:59
+msgid "WebM file (640p; VP8/Vorbis)"
+msgstr "WebM skrá (640p; VP8/Vorbis)"
+
+#: mediagoblin/templates/mediagoblin/submit/collection.html:26
+msgid "Add a collection"
+msgstr "Búa til albúm"
+
+#: mediagoblin/templates/mediagoblin/submit/collection.html:30
+#: mediagoblin/templates/mediagoblin/submit/start.html:34
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
+msgid "Add"
+msgstr "Bæta við"
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:23
+#: mediagoblin/templates/mediagoblin/submit/start.html:30
+msgid "Add your media"
+msgstr "Sendu inn efni"
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection.html:30
+#, python-format
+msgid "%(collection_title)s (%(username)s's collection)"
+msgstr "%(collection_title)s (albúm sem %(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 sem <a href=\"%(user_url)s\">%(username)s</a> bjó til"
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:87
+msgid "Edit"
+msgstr "Breyta"
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:91
+msgid "Delete"
+msgstr "Eyða"
+
+#: 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 "Virkilega eyða %(title)s?"
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+msgid "Delete permanently"
+msgstr "Eytt algjörlega"
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:31
+#, python-format
+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
+msgid "Remove"
+msgstr "Fjarlægja"
+
+#: 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 "Hæ %(username)s,\n%(comment_author)s skrifaði athugasemd við færsluna þína (%(comment_url)s) á %(instance_name)s\n"
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30
+#, python-format
+msgid "%(username)s's media"
+msgstr "Efni sem %(username)s á"
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:37
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media"
+msgstr "Efni sem <a href=\"%(user_url)s\">%(username)s</a> á"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:46
+#, python-format
+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:102
+msgid "Add a comment"
+msgstr "Bæta við athugasemd"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:109
+msgid ""
+"You can use <a "
+"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for"
+" formatting."
+msgstr "Þú getur notað <a href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> til að stílgera textann"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:113
+msgid "Add this comment"
+msgstr "Senda inn þessa athugasemd"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+msgid "at"
+msgstr "hjá"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#, python-format
+msgid ""
+"<h3>Added on</h3>\n"
+" <p>%(date)s</p>"
+msgstr "<h3>Bætt við:</h3>\n <p>%(date)s</p>"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
+msgstr "Bæta efni við albúmið"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
+#, python-format
+msgid "Add %(title)s to collection"
+msgstr "Setja %(title)s í albúm"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
+msgid "+"
+msgstr "+"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
+msgid "Add a new collection"
+msgstr "Búa til nýtt albúm"
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:29
+msgid ""
+"You can track the state of media being processed for your gallery here."
+msgstr "Þú getur fylgst með hvernig gengur að vinna með margmiðlunarefnið fyrir safnið þitt hérna."
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:89
+msgid "Your last 10 successful uploads"
+msgstr "Síðustu 10 árangursíku innsendingarnar þínar"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:31
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:89
+#, python-format
+msgid "%(username)s's profile"
+msgstr "Kenniskrá fyrir: %(username)s"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:43
+msgid "Sorry, no such user found."
+msgstr "Því miður fannst notandinn ekki."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:70
+msgid "Email verification needed"
+msgstr "Staðfesting á netfangi nauðsynleg"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:53
+msgid "Almost done! Your account still needs to be activated."
+msgstr "Næstum því búið! Notandaaðgangurinn þinn verður að vera staðfestur."
+
+#: 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 "Tölvupóstur ætti að berast til þín eftir smástund með leiðbeiningum um hvernig þú átt að gera það."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:62
+msgid "In case it doesn't:"
+msgstr "Ef það gerist ekki:"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:65
+msgid "Resend verification email"
+msgstr "Endursenda staðfestingarpóst"
+
+#: 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 "Einhver hefur búið til aðgang með þessu notandanafni en hefur ekki enn virkjað aðganginn."
+
+#: 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 "Ef þú ert þessi aðili en hefur týnt staðfestingarpóstinum getur þú <a href=\"%(login_url)s\">skráð þig inn</a> og endursent hann"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:96
+msgid "Here's a spot to tell others about yourself."
+msgstr "Hér er svæði til að segja öðrum frá þér."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:101
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:118
+msgid "Edit profile"
+msgstr "Breyta kenniskrá"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:106
+msgid "This user hasn't filled in their profile (yet)."
+msgstr "Þessi notandi hefur ekki fyllt inn í upplýsingar um sig (ennþá)."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
+#, python-format
+msgid "View all of %(username)s's media"
+msgstr "Skoða efnið sem %(username)s á"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
+msgid ""
+"This is where your media will appear, but you don't seem to have added "
+"anything yet."
+msgstr "Þetta er staðurinn þar sem efnið þitt birtist en þú virðist ekki hafa sent neitt inn ennþá."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:157
+#: 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 "Það virðist ekki vera neitt efni hérna ennþá..."
+
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
+msgstr "(fjarlægja)"
+
+#: mediagoblin/templates/mediagoblin/utils/collections.html:20
+#, python-format
+msgid "In collections (%(collected)s)"
+msgstr "à albúmum (%(collected)s)"
+
+#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
+msgid "feed icon"
+msgstr "fréttaveituteikn"
+
+#: mediagoblin/templates/mediagoblin/utils/feed_link.html:23
+msgid "Atom feed"
+msgstr "Atom fréttaveita"
+
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:25
+msgid "Location"
+msgstr "Staðsetning"
+
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
+#, python-format
+msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
+msgstr "Skoða á <a href=\"%(osm_url)s\">OpenStreetMap</a>"
+
+#: mediagoblin/templates/mediagoblin/utils/license.html:25
+msgid "All rights reserved"
+msgstr "Öll réttindi áskilin"
+
+#: mediagoblin/templates/mediagoblin/utils/pagination.html:39
+msgid "↠Newer"
+msgstr "↠Nýrri"
+
+#: mediagoblin/templates/mediagoblin/utils/pagination.html:45
+msgid "Older →"
+msgstr "Eldri →"
+
+#: mediagoblin/templates/mediagoblin/utils/pagination.html:48
+msgid "Go to page:"
+msgstr "Fara á síðu:"
+
+#: mediagoblin/templates/mediagoblin/utils/prev_next.html:28
+#: mediagoblin/templates/mediagoblin/utils/prev_next.html:33
+msgid "newer"
+msgstr "nýrri"
+
+#: mediagoblin/templates/mediagoblin/utils/prev_next.html:39
+#: mediagoblin/templates/mediagoblin/utils/prev_next.html:44
+msgid "older"
+msgstr "eldri"
+
+#: mediagoblin/templates/mediagoblin/utils/tags.html:20
+msgid "Tagged with"
+msgstr "Merkt með"
+
+#: mediagoblin/tools/exif.py:78
+msgid "Could not read the image file."
+msgstr "Gat ekki lesið myndskrána."
+
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr "Obbosí!"
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr "Villa kom upp"
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr "Aðgerð ekki leyfileg"
+
+#: mediagoblin/tools/response.py:47
+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 "Fyrirgefðu Davíð. Ég get ekki leyft þér að gera þetta!</p></p>Þú hefur reynt að framkvæma aðger sem þú hefur ekki leyfi til. Varstu að reyna að eyða öllum notendunum aftur?"
+
+#: mediagoblin/tools/response.py:55
+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 "Þ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/user_pages/forms.py:28
+msgid "I am sure I want to delete this"
+msgstr "Ég er viss um að ég vilji eyða þessu"
+
+#: mediagoblin/user_pages/forms.py:32
+msgid "I am sure I want to remove this item from the collection"
+msgstr "Ég er viss um að ég vilji fjarlægja þetta efni úr albúminu"
+
+#: mediagoblin/user_pages/forms.py:35
+msgid "-- Select --"
+msgstr "-- Velja --"
+
+#: mediagoblin/user_pages/forms.py:37
+msgid "Include a note"
+msgstr "Bæta við minnispunktum"
+
+#: mediagoblin/user_pages/lib.py:56
+msgid "commented on your post"
+msgstr "skrifaði athugasemd við færsluna þína"
+
+#: mediagoblin/user_pages/views.py:156
+msgid "Oops, your comment was empty."
+msgstr "Obbosí! Athugasemdin þín var innihaldslaus."
+
+#: mediagoblin/user_pages/views.py:162
+msgid "Your comment has been posted!"
+msgstr "Athugasemdin þín var skráð!"
+
+#: mediagoblin/user_pages/views.py:230
+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:238
+#, python-format
+msgid "\"%s\" already in collection \"%s\""
+msgstr "\"%s\" er nú þegar í albúminu \"%s\""
+
+#: mediagoblin/user_pages/views.py:253
+#, python-format
+msgid "\"%s\" added to collection \"%s\""
+msgstr "\"%s\" sett í albúmið \"%s\""
+
+#: mediagoblin/user_pages/views.py:261
+msgid "Please check your entries and try again."
+msgstr "Vinsamlegast kíktu á innsendingarnar þínar og reyndu aftur."
+
+#: mediagoblin/user_pages/views.py:292
+msgid ""
+"Some of the files with this entry seem to be missing. Deleting anyway."
+msgstr "Sumar af skránum við þessa innsendingu virðast vera horfnar. Eyði þrátt fyrir það."
+
+#: mediagoblin/user_pages/views.py:297
+msgid "You deleted the media."
+msgstr "Þú eyddir þessu efni."
+
+#: mediagoblin/user_pages/views.py:304
+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:312
+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:370
+msgid "You deleted the item from the collection."
+msgstr "Þú tókst þetta efni úr albúminu."
+
+#: 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:384
+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:417
+#, python-format
+msgid "You deleted the collection \"%s\""
+msgstr "Þú eyddir albúminu \"%s\""
+
+#: mediagoblin/user_pages/views.py:424
+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:434
+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 5658950c..dad0aec4 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 fd04ba6e..e91926a1 100644
--- a/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.po
@@ -11,8 +11,8 @@ msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2012-09-24 14:01-0500\n"
-"PO-Revision-Date: 2012-09-24 18:57+0000\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 15:14+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
@@ -95,7 +95,7 @@ msgstr "Impossibile trovare qualcuno con questo nome utente o password."
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:83
+#: 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:40
msgid "Title"
@@ -106,7 +106,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:87 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:44
msgid ""
"You can use\n"
@@ -122,11 +122,11 @@ msgstr "Tags"
msgid "Separate tags by commas."
msgstr "Separa le tags con la virgola."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:91
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr ""
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:92
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr ""
@@ -165,20 +165,20 @@ msgstr "Inserisci la vecchia password per dimostrare di essere il proprietario d
msgid "New password"
msgstr "Nuova password"
-#: mediagoblin/edit/forms.py:72
+#: 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:84
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:43
msgid "Description of this collection"
msgstr ""
-#: mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
@@ -192,33 +192,38 @@ msgstr ""
msgid "You are editing another user's media. Proceed with caution."
msgstr "Stai modificando files multimediali di un altro utente. Procedi con attenzione."
-#: mediagoblin/edit/views.py:182
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr ""
+
+#: mediagoblin/edit/views.py:181
msgid "You are editing a user's profile. Proceed with caution."
msgstr "Stai modificando il profilo di un utente. Procedi con attenzione."
-#: mediagoblin/edit/views.py:198
+#: mediagoblin/edit/views.py:197
msgid "Profile changes saved"
msgstr "Cambiamenti del profilo salvati"
-#: mediagoblin/edit/views.py:227 mediagoblin/edit/views.py:247
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
msgid "Account settings saved"
msgstr "Impostazioni del profilo salvate"
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:251
msgid "Wrong password"
msgstr "Password errata"
-#: mediagoblin/edit/views.py:288 mediagoblin/submit/views.py:211
-#: mediagoblin/user_pages/views.py:215
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr ""
-#: mediagoblin/edit/views.py:292
+#: mediagoblin/edit/views.py:291
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:309
+#: mediagoblin/edit/views.py:308
msgid "You are editing another user's collection. Proceed with caution."
msgstr ""
@@ -235,7 +240,7 @@ msgid "However, old link directory symlink found; removed.\n"
msgstr ""
#: mediagoblin/media_types/__init__.py:60
-#: mediagoblin/media_types/__init__.py:120
+#: mediagoblin/media_types/__init__.py:101
msgid "Sorry, I don't support that file type :("
msgstr "Mi dispiace, non supporto questo tipo di file :("
@@ -305,7 +310,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:60
msgid "The client {0} has been registered!"
msgstr ""
@@ -330,62 +335,43 @@ msgstr "Evviva! Caricato!"
msgid "Collection \"%s\" added!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/404.html:24
-msgid "Image of 404 goblin stressing out"
-msgstr "Immagine di 404 folletti che stressano"
-
-#: mediagoblin/templates/mediagoblin/404.html:25
-msgid "Oops!"
-msgstr "Oops!"
-
-#: mediagoblin/templates/mediagoblin/404.html:26
-msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr "Non sembra esserci una pagina a questo indirizzo. Spiacente!"
-
-#: mediagoblin/templates/mediagoblin/404.html:28
-msgid ""
-"If you're sure the address is correct, maybe the page you're looking for has"
-" been moved or deleted."
-msgstr "Se sei sicuro che l'indirizzo è corretto, forse la pagina che stai cercando è stata spostata o cancellata."
-
-#: mediagoblin/templates/mediagoblin/base.html:50
+#: mediagoblin/templates/mediagoblin/base.html:48
msgid "MediaGoblin logo"
msgstr "Simbolo di MediaGoblin"
-#: mediagoblin/templates/mediagoblin/base.html:60
-msgid "Verify your email!"
-msgstr "Verifica la tua email!"
-
-#: mediagoblin/templates/mediagoblin/base.html:66
-msgid "+ Add media"
-msgstr "+ Aggiungi files multimediali"
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
+msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:67
-msgid "+ Add collection"
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:69
-msgid "View your profile"
-msgstr "Vedi il tuo profilo"
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
+msgstr "Aggiungi files multimediali"
-#: mediagoblin/templates/mediagoblin/base.html:70
-msgid "Log out"
-msgstr "Esci"
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
+msgstr "Verifica la tua email!"
-#: mediagoblin/templates/mediagoblin/base.html:75
+#: 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:89
+#: mediagoblin/templates/mediagoblin/base.html:87
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project."
msgstr "Realizzato con <a href=\"http://mediagoblin.org\">MediaGoblin</a>, un progetto <a href=\"http://gnu.org/\">GNU</a>."
-#: mediagoblin/templates/mediagoblin/base.html:92
+#: mediagoblin/templates/mediagoblin/base.html:90
#, python-format
msgid ""
"Released under the <a "
@@ -393,31 +379,56 @@ msgid ""
"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/root.html:24
+#: mediagoblin/templates/mediagoblin/error.html:24
+msgid "Image of goblin stressing out"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:25
+msgid "Actions"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr "Cambia le impostazioni dell'account"
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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 "Pannello di elaborazione files multimediali"
+
+#: mediagoblin/templates/mediagoblin/root.html:51
msgid "Explore"
msgstr "Esplora"
-#: mediagoblin/templates/mediagoblin/root.html:26
+#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Hi there, welcome to this MediaGoblin site!"
msgstr "Ciao, benvenuto in questo sito MediaGoblin!"
-#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/root.html:55
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:29
+#: mediagoblin/templates/mediagoblin/root.html:56
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:31
+#: mediagoblin/templates/mediagoblin/root.html:58
msgid "Don't have one yet? It's easy!"
msgstr "Non ne hai già uno? E' semplice!"
-#: mediagoblin/templates/mediagoblin/root.html:32
+#: mediagoblin/templates/mediagoblin/root.html:59
#, python-format
msgid ""
"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
@@ -425,17 +436,10 @@ msgid ""
" <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:40
+#: mediagoblin/templates/mediagoblin/root.html:67
msgid "Most recent media"
msgstr "Files multimediali più recenti"
-#: 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 "Pannello di elaborazione files multimediali"
-
#: mediagoblin/templates/mediagoblin/admin/panel.html:29
msgid ""
"Here you can track the state of media being processed on this instance."
@@ -544,30 +548,43 @@ msgstr "Ciao %(username)s,\n\nper attivare il tuo account GNU MediaGoblin, apri
msgid "Editing attachments for %(media_title)s"
msgstr "Stai modificando gli allegati di %(media_title)s"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:23
-#: mediagoblin/templates/mediagoblin/edit/edit.html:35
-#, python-format
-msgid "Editing %(media_title)s"
-msgstr "Stai modificando %(media_title)s"
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:43
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
+msgid "Attachments"
+msgstr "Allegati"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr "Aggiungi allegato"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:53
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
msgid "Cancel"
msgstr "Annulla"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:43
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
msgid "Save changes"
msgstr "Salva i cambiamenti"
+#: mediagoblin/templates/mediagoblin/edit/edit.html:23
+#: mediagoblin/templates/mediagoblin/edit/edit.html:35
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "Stai modificando %(media_title)s"
+
#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:41
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
#, python-format
msgid "Changing %(username)s's account settings"
msgstr "Stai cambiando le impostazioni dell'account di %(username)s"
@@ -593,13 +610,12 @@ 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/image.html:23
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
msgid "Download"
msgstr "Scarica"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:27
msgid "Original"
msgstr "Originale"
@@ -626,6 +642,56 @@ msgstr "File originario"
msgid "WebM file (Vorbis codec)"
msgstr "File WebM (codec Vorbis)"
+#: 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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr ""
+
+#: 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 ""
+
+#: 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:40
msgid ""
"Sorry, this video will not work because \n"
@@ -650,7 +716,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
#: mediagoblin/templates/mediagoblin/submit/start.html:34
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:83
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
msgid "Add"
msgstr "Aggiungi"
@@ -679,14 +745,6 @@ msgstr "Modifica"
msgid "Delete"
msgstr "Elimina"
-#: mediagoblin/templates/mediagoblin/user_pages/collection.html:59
-#, python-format
-msgid ""
-"<p>\n"
-" %(collection_description)s\n"
-" </p>"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
@@ -694,7 +752,7 @@ msgid "Really delete %(title)s?"
msgstr "Vuoi davvero eliminare %(title)s?"
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "Elimina definitivamente"
@@ -703,7 +761,7 @@ msgstr "Elimina definitivamente"
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
msgid "Remove"
msgstr ""
@@ -729,12 +787,6 @@ 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:67
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
-#, python-format
-msgid "Image for %(media_title)s"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
msgid "Add a comment"
msgstr "Aggiungi un commento"
@@ -761,25 +813,20 @@ msgid ""
" <p>%(date)s</p>"
msgstr "<h3>Aggiunto il</h3>\n <p>%(date)s</p>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
-msgid "Attachments"
-msgstr "Allegati"
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
-msgid "Add attachment"
-msgstr "Aggiungi allegato"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
+msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
#, python-format
msgid "Add %(title)s to collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
msgid "+"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
msgid "Add a new collection"
msgstr ""
@@ -850,41 +897,25 @@ msgstr "Modifica profilo"
msgid "This user hasn't filled in their profile (yet)."
msgstr "Questo utente non ha (ancora) compilato il proprio profilo."
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:125
-msgid "Change account settings"
-msgstr "Cambia le impostazioni dell'account"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:138
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
#, python-format
msgid "View all of %(username)s's media"
msgstr "Visualizza tutti i files multimediali di %(username)s"
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
msgid ""
"This is where your media will appear, but you don't seem to have added "
"anything yet."
msgstr "Qui è dove appariranno i tuoi files multimediali, ma sembra che tu non abbia ancora aggiunto niente."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:157
-msgid "Add media"
-msgstr "Aggiungi files multimediali"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:163
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:87
-#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:72
+#: 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 "Sembra che non ci sia ancora nessun file multimediale qui..."
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:39
-#, python-format
-msgid ""
-"<br />\n"
-" <a href=\"%(entry_url)s\">%(note)s</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:47
-#, python-format
-msgid "<br /><a href=\"%(remove_url)s\" class=\"remove\">(remove)</a>"
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
msgstr ""
#: mediagoblin/templates/mediagoblin/utils/collections.html:20
@@ -904,7 +935,7 @@ msgstr "Atom feed"
msgid "Location"
msgstr "Posizione"
-#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:38
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
#, python-format
msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
msgstr "Visualizza su <a href=\"%(osm_url)s\">OpenStreetMap</a>"
@@ -943,6 +974,32 @@ msgstr "Taggato con"
msgid "Could not read the image file."
msgstr "Impossibile leggere il file immagine."
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr "Oops!"
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr ""
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr ""
+
+#: mediagoblin/tools/response.py:47
+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:55
+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/user_pages/forms.py:28
msgid "I am sure I want to delete this"
msgstr "Sono sicuro di volerlo eliminare"
@@ -963,74 +1020,74 @@ msgstr ""
msgid "commented on your post"
msgstr "ha commentato il tuo post"
-#: mediagoblin/user_pages/views.py:161
+#: mediagoblin/user_pages/views.py:156
msgid "Oops, your comment was empty."
msgstr "Oops, il tuo commento era vuoto."
-#: mediagoblin/user_pages/views.py:167
+#: mediagoblin/user_pages/views.py:162
msgid "Your comment has been posted!"
msgstr "Il tuo commento è stato aggiunto!"
-#: mediagoblin/user_pages/views.py:235
+#: mediagoblin/user_pages/views.py:230
msgid "You have to select or add a collection"
msgstr ""
-#: mediagoblin/user_pages/views.py:243
+#: mediagoblin/user_pages/views.py:238
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:258
+#: mediagoblin/user_pages/views.py:253
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:266
+#: mediagoblin/user_pages/views.py:261
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:297
+#: mediagoblin/user_pages/views.py:292
msgid ""
"Some of the files with this entry seem to be missing. Deleting anyway."
msgstr ""
-#: mediagoblin/user_pages/views.py:302
+#: mediagoblin/user_pages/views.py:297
msgid "You deleted the media."
msgstr "Hai eliminato il file."
-#: mediagoblin/user_pages/views.py:309
+#: mediagoblin/user_pages/views.py:304
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:317
+#: mediagoblin/user_pages/views.py:312
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:379
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr ""
-#: mediagoblin/user_pages/views.py:383
+#: 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:393
+#: mediagoblin/user_pages/views.py:384
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:426
+#: mediagoblin/user_pages/views.py:417
#, python-format
msgid "You deleted the collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:433
+#: mediagoblin/user_pages/views.py:424
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:443
+#: mediagoblin/user_pages/views.py:434
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 fc0bba8f..1ebdba16 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 5fb16241..abbf5b26 100644
--- a/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.po
@@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2012-09-24 14:01-0500\n"
-"PO-Revision-Date: 2012-09-24 18:57+0000\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 15:14+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
@@ -92,7 +92,7 @@ msgstr ""
msgid "You can now log in using your new password."
msgstr ""
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:83
+#: 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:40
msgid "Title"
@@ -103,7 +103,7 @@ msgid "Description of this work"
msgstr ""
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:87 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:44
msgid ""
"You can use\n"
@@ -119,11 +119,11 @@ msgstr "ã‚¿ã‚°"
msgid "Separate tags by commas."
msgstr ""
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:91
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "スラグ"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:92
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "スラグã¯å¿…è¦ã§ã™ã€‚"
@@ -162,20 +162,20 @@ msgstr ""
msgid "New password"
msgstr ""
-#: mediagoblin/edit/forms.py:72
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr ""
-#: mediagoblin/edit/forms.py:84
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:43
msgid "Description of this collection"
msgstr ""
-#: mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
@@ -189,33 +189,38 @@ msgstr "ãã®ã‚¹ãƒ©ã‚°ã‚’æŒã¤ã‚¨ãƒ³ãƒˆãƒªã¯ã€ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯æ—¢ã«å­˜
msgid "You are editing another user's media. Proceed with caution."
msgstr "ã‚ãªãŸã¯ã€ä»–ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ¡ãƒ‡ã‚£ã‚¢ã‚’編集ã—ã¦ã„ã¾ã™ã€‚ã”æ³¨æ„ãã ã•ã„。"
-#: mediagoblin/edit/views.py:182
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr ""
+
+#: mediagoblin/edit/views.py:181
msgid "You are editing a user's profile. Proceed with caution."
msgstr "ã‚ãªãŸã¯ã€ä»–ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ—ロファイルを編集ã—ã¦ã„ã¾ã™ã€‚ã”æ³¨æ„ãã ã•ã„。"
-#: mediagoblin/edit/views.py:198
+#: mediagoblin/edit/views.py:197
msgid "Profile changes saved"
msgstr ""
-#: mediagoblin/edit/views.py:227 mediagoblin/edit/views.py:247
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
msgid "Account settings saved"
msgstr ""
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:251
msgid "Wrong password"
msgstr ""
-#: mediagoblin/edit/views.py:288 mediagoblin/submit/views.py:211
-#: mediagoblin/user_pages/views.py:215
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr ""
-#: mediagoblin/edit/views.py:292
+#: mediagoblin/edit/views.py:291
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:309
+#: mediagoblin/edit/views.py:308
msgid "You are editing another user's collection. Proceed with caution."
msgstr ""
@@ -232,7 +237,7 @@ msgid "However, old link directory symlink found; removed.\n"
msgstr ""
#: mediagoblin/media_types/__init__.py:60
-#: mediagoblin/media_types/__init__.py:120
+#: mediagoblin/media_types/__init__.py:101
msgid "Sorry, I don't support that file type :("
msgstr ""
@@ -302,7 +307,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:60
msgid "The client {0} has been registered!"
msgstr ""
@@ -327,62 +332,43 @@ msgstr "投稿終了ï¼"
msgid "Collection \"%s\" added!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/404.html:24
-msgid "Image of 404 goblin stressing out"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/404.html:25
-msgid "Oops!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/404.html:26
-msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/404.html:28
-msgid ""
-"If you're sure the address is correct, maybe the page you're looking for has"
-" been moved or deleted."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:50
+#: mediagoblin/templates/mediagoblin/base.html:48
msgid "MediaGoblin logo"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:60
-msgid "Verify your email!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:66
-msgid "+ Add media"
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:67
-msgid "+ Add collection"
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:69
-msgid "View your profile"
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:70
-msgid "Log out"
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:75
+#: 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:89
+#: mediagoblin/templates/mediagoblin/base.html:87
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project."
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:92
+#: mediagoblin/templates/mediagoblin/base.html:90
#, python-format
msgid ""
"Released under the <a "
@@ -390,31 +376,56 @@ msgid ""
"href=\"%(source_link)s\">Source code</a> available."
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:24
+#: mediagoblin/templates/mediagoblin/error.html:24
+msgid "Image of goblin stressing out"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:25
+msgid "Actions"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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/root.html:51
msgid "Explore"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:26
+#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Hi there, welcome to this MediaGoblin site!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/root.html:55
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:29
+#: mediagoblin/templates/mediagoblin/root.html:56
msgid ""
"To add your own media, place comments, and more, you can log in with your "
"MediaGoblin account."
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:31
+#: mediagoblin/templates/mediagoblin/root.html:58
msgid "Don't have one yet? It's easy!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:32
+#: mediagoblin/templates/mediagoblin/root.html:59
#, python-format
msgid ""
"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
@@ -422,17 +433,10 @@ msgid ""
" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:40
+#: mediagoblin/templates/mediagoblin/root.html:67
msgid "Most recent media"
msgstr ""
-#: 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/admin/panel.html:29
msgid ""
"Here you can track the state of media being processed on this instance."
@@ -541,30 +545,43 @@ msgstr "%(username)s様ã¸\n\nGNU MediaGoblinアカウントを検証ã«ã™ã‚‹ã
msgid "Editing attachments for %(media_title)s"
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/attachments.html:43
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
+msgid "Attachments"
+msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:53
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
msgid "Cancel"
msgstr "キャンセル"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:43
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
msgid "Save changes"
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:41
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
#, python-format
msgid "Changing %(username)s's account settings"
msgstr ""
@@ -590,13 +607,12 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:23
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
msgid "Download"
msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:27
msgid "Original"
msgstr ""
@@ -623,6 +639,56 @@ msgstr ""
msgid "WebM file (Vorbis codec)"
msgstr ""
+#: 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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr ""
+
+#: 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 ""
+
+#: 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:40
msgid ""
"Sorry, this video will not work because \n"
@@ -647,7 +713,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
#: mediagoblin/templates/mediagoblin/submit/start.html:34
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:83
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
msgid "Add"
msgstr ""
@@ -676,14 +742,6 @@ msgstr ""
msgid "Delete"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection.html:59
-#, python-format
-msgid ""
-"<p>\n"
-" %(collection_description)s\n"
-" </p>"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
@@ -691,7 +749,7 @@ msgid "Really delete %(title)s?"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr ""
@@ -700,7 +758,7 @@ msgstr ""
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
msgid "Remove"
msgstr ""
@@ -726,12 +784,6 @@ 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:67
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
-#, python-format
-msgid "Image for %(media_title)s"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
msgid "Add a comment"
msgstr ""
@@ -758,13 +810,8 @@ msgid ""
" <p>%(date)s</p>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
-msgid "Attachments"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
-msgid "Add attachment"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
@@ -772,11 +819,11 @@ msgstr ""
msgid "Add %(title)s to collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
msgid "+"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
msgid "Add a new collection"
msgstr ""
@@ -847,41 +894,25 @@ msgstr "プロフィールを編集"
msgid "This user hasn't filled in their profile (yet)."
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:125
-msgid "Change account settings"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:138
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
#, python-format
msgid "View all of %(username)s's media"
msgstr "%(username)sã•ã‚“ã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã‚’ã™ã¹ã¦è¦‹ã‚‹"
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
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:157
-msgid "Add media"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:163
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:87
-#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:72
+#: 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:39
-#, python-format
-msgid ""
-"<br />\n"
-" <a href=\"%(entry_url)s\">%(note)s</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:47
-#, python-format
-msgid "<br /><a href=\"%(remove_url)s\" class=\"remove\">(remove)</a>"
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
msgstr ""
#: mediagoblin/templates/mediagoblin/utils/collections.html:20
@@ -901,7 +932,7 @@ msgstr ""
msgid "Location"
msgstr ""
-#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:38
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
#, python-format
msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
msgstr ""
@@ -940,6 +971,32 @@ msgstr ""
msgid "Could not read the image file."
msgstr ""
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr ""
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr ""
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr ""
+
+#: mediagoblin/tools/response.py:47
+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:55
+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/user_pages/forms.py:28
msgid "I am sure I want to delete this"
msgstr ""
@@ -960,74 +1017,74 @@ msgstr ""
msgid "commented on your post"
msgstr ""
-#: mediagoblin/user_pages/views.py:161
+#: mediagoblin/user_pages/views.py:156
msgid "Oops, your comment was empty."
msgstr ""
-#: mediagoblin/user_pages/views.py:167
+#: mediagoblin/user_pages/views.py:162
msgid "Your comment has been posted!"
msgstr ""
-#: mediagoblin/user_pages/views.py:235
+#: mediagoblin/user_pages/views.py:230
msgid "You have to select or add a collection"
msgstr ""
-#: mediagoblin/user_pages/views.py:243
+#: mediagoblin/user_pages/views.py:238
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:258
+#: mediagoblin/user_pages/views.py:253
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:266
+#: mediagoblin/user_pages/views.py:261
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:297
+#: mediagoblin/user_pages/views.py:292
msgid ""
"Some of the files with this entry seem to be missing. Deleting anyway."
msgstr ""
-#: mediagoblin/user_pages/views.py:302
+#: mediagoblin/user_pages/views.py:297
msgid "You deleted the media."
msgstr ""
-#: mediagoblin/user_pages/views.py:309
+#: mediagoblin/user_pages/views.py:304
msgid "The media was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:317
+#: mediagoblin/user_pages/views.py:312
msgid "You are about to delete another user's media. Proceed with caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr ""
-#: mediagoblin/user_pages/views.py:383
+#: 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:393
+#: mediagoblin/user_pages/views.py:384
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:426
+#: mediagoblin/user_pages/views.py:417
#, python-format
msgid "You deleted the collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:433
+#: mediagoblin/user_pages/views.py:424
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:443
+#: mediagoblin/user_pages/views.py:434
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
new file mode 100644
index 00000000..e7602e15
--- /dev/null
+++ 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
new file mode 100644
index 00000000..6a35c0e0
--- /dev/null
+++ b/mediagoblin/i18n/ko_KR/LC_MESSAGES/mediagoblin.po
@@ -0,0 +1,1090 @@
+# Translations template for PROJECT.
+# Copyright (C) 2012 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+#
+# Translators:
+# <newvgund@gmail.com>, 2012.
+msgid ""
+msgstr ""
+"Project-Id-Version: GNU MediaGoblin\n"
+"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 15:14+0000\n"
+"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 0.9.6\n"
+"Language: ko_KR\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:41
+msgid "Username"
+msgstr "ì‚¬ìš©ìž ì´ë¦„"
+
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
+msgid "Password"
+msgstr "비밀번호"
+
+#: mediagoblin/auth/forms.py:34
+msgid "Email address"
+msgstr "email 주소"
+
+#: mediagoblin/auth/forms.py:51
+msgid "Username or email"
+msgstr "ì‚¬ìš©ìž ì´ë¦„ ë˜ëŠ” email"
+
+#: mediagoblin/auth/forms.py:58
+msgid "Incorrect input"
+msgstr "ìž˜ëª»ëœ ìž…ë ¥ 입니다."
+
+#: mediagoblin/auth/views.py:55
+msgid "Sorry, registration is disabled on this instance."
+msgstr "죄송합니다. ì§€ê¸ˆì€ ê°€ìž… 하실 수 없습니다."
+
+#: mediagoblin/auth/views.py:75
+msgid "Sorry, a user with that name already exists."
+msgstr "죄송합니다. 해당 ì‚¬ìš©ìž ì´ë¦„ì´ ì´ë¯¸ 존재 합니다."
+
+#: mediagoblin/auth/views.py:79
+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 "해당 email 주소가 ì´ë¯¸ ì¸ì¦ ë˜ì–´ 있습니다. 지금 로그ì¸í•˜ì‹œê³  계정 정보를 수정하고 ì‚¬ì§„ì„ ì „ì†¡í•´ 보세요!"
+
+#: 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 "ì´ë¯¸ ì¸ì¦ë°›ì€ email 주소를 가지고 있습니다!"
+
+#: mediagoblin/auth/views.py:227
+msgid "Resent your verification email."
+msgstr "ì¸ì¦ ë©”ì¼ì„ 다시 ë³´ë‚´ 주세요."
+
+#: mediagoblin/auth/views.py:263
+msgid ""
+"An email has been sent with instructions on how to change your password."
+msgstr "비밀번호를 변경하는 ë°©ë²•ì— ëŒ€í•œ 설명서가 ë©”ì¼ë¡œ 전송 ë˜ì—ˆìŠµë‹ˆë‹¤."
+
+#: mediagoblin/auth/views.py:273
+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:285
+msgid "Couldn't find someone with that username or email."
+msgstr "ì‚¬ìš©ìž ì´ë¦„ ë˜ëŠ” email로 ëœ ì‚¬ìš©ìžë¥¼ ì°¾ì„ ìˆ˜ 없습니다."
+
+#: mediagoblin/auth/views.py:333
+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:40
+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:44
+msgid ""
+"You can use\n"
+" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n"
+" Markdown</a> for formatting."
+msgstr "í¬ë©§íŒ…ì„ ì‚¬ìš©í•˜ë ¤ë©´\n <a href=\"http://daringfireball.net/projects/markdown/basics\">\n 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 "License"
+
+#: 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 "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: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:43
+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/views.py:65
+msgid "An entry with that slug already exists for this user."
+msgstr "해당 ìœ ì €ì— ëŒ€í•œ '슬러그'ê°€ ì´ë¯¸ 존재합니다."
+
+#: mediagoblin/edit/views.py:86
+msgid "You are editing another user's media. Proceed with caution."
+msgstr "다른 사용ìžì˜ 미디어를 수정하고 있습니다. 조심해서 수정하세요."
+
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr ""
+
+#: mediagoblin/edit/views.py:181
+msgid "You are editing a user's profile. Proceed with caution."
+msgstr "사용ìžì˜ 계정 정보를 수정하고 있습니다. 조심해서 수정하세요."
+
+#: mediagoblin/edit/views.py:197
+msgid "Profile changes saved"
+msgstr "계정 ì •ë³´ê°€ 저장 ë˜ì—ˆìŠµë‹ˆë‹¤."
+
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
+msgid "Account settings saved"
+msgstr "계정 ì„¤ì •ì´ ì €ìž¥ ë˜ì—ˆìŠµë‹ˆë‹¤."
+
+#: mediagoblin/edit/views.py:251
+msgid "Wrong password"
+msgstr "ìž˜ëª»ëœ ë¹„ë°€ë²ˆí˜¸"
+
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
+#, python-format
+msgid "You already have a collection called \"%s\"!"
+msgstr "\"%s\" 모ìŒì§‘ì„ ì´ë¯¸ 가지고 있습니다!"
+
+#: mediagoblin/edit/views.py:291
+msgid "A collection with that slug already exists for this user."
+msgstr ""
+
+#: mediagoblin/edit/views.py:308
+msgid "You are editing another user's collection. Proceed with caution."
+msgstr "다른 ìœ ì €ì˜ ëª¨ìŒì§‘ì„ ìˆ˜ì • 중 입니다. 주ì˜í•˜ì„¸ìš”."
+
+#: mediagoblin/gmg_commands/theme.py:58
+msgid "Cannot link theme... no theme set\n"
+msgstr "í…Œë§ˆì— ì—°ê²°í•  수 없습니다... 테마 ì…‹ì´ ì—†ìŠµë‹ˆë‹¤.\n"
+
+#: mediagoblin/gmg_commands/theme.py:71
+msgid "No asset directory for this theme\n"
+msgstr "ì´ í…Œë§ˆë¥¼ 위한 ì—ì…‹ 디렉토리가 없습니다.\n"
+
+#: mediagoblin/gmg_commands/theme.py:74
+msgid "However, old link directory symlink found; removed.\n"
+msgstr "그런ë°, ì˜¤ëž˜ëœ ë””ë ‰í† ë¦¬ 심볼릭 ë§í¬ë¥¼ 찾았습니다; 지워졌습니다.\n"
+
+#: mediagoblin/media_types/__init__.py:60
+#: mediagoblin/media_types/__init__.py:101
+msgid "Sorry, I don't support that file type :("
+msgstr "죄송합니다. 해당 íƒ€ìž…ì˜ íŒŒì¼ì€ ì§€ì›í•˜ì§€ 않아요 :("
+
+#: mediagoblin/media_types/video/processing.py:35
+msgid "Video transcoding failed"
+msgstr "비디오 ë³€í™˜ì— ì‹¤íŒ¨ 했습니다."
+
+#: mediagoblin/plugins/oauth/forms.py:26
+msgid "Client ID"
+msgstr "ì‚¬ìš©ìž ID"
+
+#: mediagoblin/plugins/oauth/forms.py:28
+msgid "Next URL"
+msgstr "ë‹¤ìŒ URL"
+
+#: mediagoblin/plugins/oauth/forms.py:30
+msgid "Allow"
+msgstr "허용"
+
+#: mediagoblin/plugins/oauth/forms.py:31
+msgid "Deny"
+msgstr "ê±°ë¶€"
+
+#: mediagoblin/plugins/oauth/forms.py:35
+msgid "Name"
+msgstr "ì´ë¦„"
+
+#: mediagoblin/plugins/oauth/forms.py:36
+msgid "The name of the OAuth client"
+msgstr ""
+
+#: mediagoblin/plugins/oauth/forms.py:37
+msgid "Description"
+msgstr "설명"
+
+#: mediagoblin/plugins/oauth/forms.py:39
+msgid ""
+"This will be visible to users allowing your\n"
+" application to authenticate as them."
+msgstr ""
+
+#: mediagoblin/plugins/oauth/forms.py:41
+msgid "Type"
+msgstr "종류"
+
+#: mediagoblin/plugins/oauth/forms.py:46
+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:53
+msgid "Redirect URI"
+msgstr "리다ì´ë ‰íЏ URI"
+
+#: mediagoblin/plugins/oauth/forms.py:55
+msgid ""
+"The redirect URI for the applications, this field\n"
+" is <strong>required</strong> for public clients."
+msgstr ""
+
+#: mediagoblin/plugins/oauth/forms.py:67
+msgid "This field is required for public clients"
+msgstr "ì´ í•­ëª©ì€ ê³µê°œ 사용ìžë“¤ì„ 위해 ê¼­ í•„ìš” 합니다."
+
+#: mediagoblin/plugins/oauth/views.py:60
+msgid "The client {0} has been registered!"
+msgstr "ì‚¬ìš©ìž {0}ë‹˜ì´ ë“±ë¡ ë˜ì—ˆìŠµë‹ˆë‹¤!"
+
+#: mediagoblin/processing/__init__.py:138
+msgid "Invalid file given for media type."
+msgstr "알수없는 미디어 íŒŒì¼ ìž…ë‹ˆë‹¤."
+
+#: mediagoblin/submit/forms.py:26
+msgid "File"
+msgstr "파ì¼"
+
+#: mediagoblin/submit/views.py:57
+msgid "You must provide a file."
+msgstr "파ì¼ì„ 등ë¡í•˜ì…”야 합니다."
+
+#: mediagoblin/submit/views.py:164
+msgid "Woohoo! Submitted!"
+msgstr "ì´í–!! 등ë¡í–ˆìŠµë‹ˆë‹¤!"
+
+#: mediagoblin/submit/views.py:215
+#, python-format
+msgid "Collection \"%s\" added!"
+msgstr "\"%s\" 모ìŒì§‘ì´ ì¶”ê°€ë˜ì—ˆìŠµë‹ˆë‹¤!"
+
+#: mediagoblin/templates/mediagoblin/base.html:48
+msgid "MediaGoblin logo"
+msgstr "MediaGoblin 로고"
+
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
+msgstr "미디어 추가"
+
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
+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:87
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
+"href=\"http://gnu.org/\">GNU</a> project."
+msgstr "Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a href=\"http://gnu.org/\">GNU</a> project."
+
+#: mediagoblin/templates/mediagoblin/base.html:90
+#, 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:25
+msgid "Actions"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr "계정 설정 변경"
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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/root.html:51
+msgid "Explore"
+msgstr "íƒìƒ‰"
+
+#: mediagoblin/templates/mediagoblin/root.html:53
+msgid "Hi there, welcome to this MediaGoblin site!"
+msgstr "안녕하세요! 미디어 고블린 사ì´íŠ¸ì— ì˜¨ê±¸ í™˜ì˜ í•©ë‹ˆë‹¤!"
+
+#: mediagoblin/templates/mediagoblin/root.html:55
+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:56
+msgid ""
+"To add your own media, place comments, and more, you can log in with your "
+"MediaGoblin account."
+msgstr "ìžì‹ ì˜ 미디어를 추가하고, ëŒ“ê¸€ì„ ë‚¨ê¸°ì„¸ìš”! 미디어 고블린 계정으로 ë‚´ì—­ì„ í™•ì¸ í•˜ì‹¤ 수 있습니다!"
+
+#: mediagoblin/templates/mediagoblin/root.html:58
+msgid "Don't have one yet? It's easy!"
+msgstr "ì•„ì§ ì•„ë¬´ê²ƒë„ ì—†ìœ¼ì‹œë‹¤êµ¬ìš”? 매우 쉽습니다!"
+
+#: mediagoblin/templates/mediagoblin/root.html:59
+#, 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:67
+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\nGNU MediaGoblinì˜ ì‚¬ìš©ìž ê³„ì • 비밀번호를 바꾸시려면, ì¸í„°ë„· ì°½ì„ ì—¬ì‹œê³  아래 URLì„ í†µí•´ ì ‘ì† í•˜ì„¸ìš”. :\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\nGNU MediaGoblin ê³„ì •ì„ í™œì„±í™” 하시려면, ì•„ëž˜ì˜ URL 주소를 브ë¼ìš°ì ¸ë¡œ ì ‘ì†í•˜ì„¸ìš”.\n\n%(verification_url)s"
+
+#: 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:43
+#: 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:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr "첨부 추가"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
+msgid "Cancel"
+msgstr "취소"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
+#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
+msgid "Save changes"
+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_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:35
+#, 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/stl.html:136
+#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
+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를 ì§€ì›í•˜ì§€ 않아\n\t오디오 파ì¼ì„ 재ìƒí•  수 없습니다.\n\t죄송합니다."
+
+#: 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 "사운드 파ì¼ì„ ìž¬ìƒ í•˜ì‹œë ¤ë©´\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/video.html:56
+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/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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr "%(media_title)s ì´ë¯¸ì§€"
+
+#: 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 ""
+
+#: 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:40
+msgid ""
+"Sorry, this video will not work because \n"
+"\t your web browser does not support HTML5 \n"
+"\t video."
+msgstr "죄송합니다. 사용하고 계신 브ë¼ìš°ì ¸ê°€ HTML5 video를\n\t ì§€ì›í•˜ì§€ 않습니다. 비디오를 재ìƒí•  수\n\t 없습니다."
+
+#: mediagoblin/templates/mediagoblin/media_displays/video.html:43
+msgid ""
+"You can get a modern web browser that \n"
+"\t can play this video 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>!"
+
+#: mediagoblin/templates/mediagoblin/media_displays/video.html:59
+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/collection.html:30
+#: mediagoblin/templates/mediagoblin/submit/start.html:34
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
+msgid "Add"
+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 "<a href=\"%(user_url)s\">%(username)s</a>ì˜ %(collection_title)s"
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:87
+msgid "Edit"
+msgstr "수정"
+
+#: mediagoblin/templates/mediagoblin/user_pages/collection.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:91
+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_confirm_delete.html:47
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+msgid "Delete permanently"
+msgstr "ì˜êµ¬ì ìœ¼ë¡œ ì‚­ì œ"
+
+#: 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:53
+msgid "Remove"
+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 "안녕하세요 %(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 "%(username)sì˜ ë¯¸ë””ì–´"
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:37
+#, 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:46
+#, 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:102
+msgid "Add a comment"
+msgstr "ë§ê¸€ 달기"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:109
+msgid ""
+"You can use <a "
+"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for"
+" formatting."
+msgstr "í¬ë©§íŒ…ì„ ìœ„í•´ <a href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> ì„ ì‚¬ìš©í•  수 있습니다.."
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:113
+msgid "Add this comment"
+msgstr "ë§ê¸€ 추가"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
+msgid "at"
+msgstr "ì—"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:152
+#, python-format
+msgid ""
+"<h3>Added on</h3>\n"
+" <p>%(date)s</p>"
+msgstr "<h3>부가 기능</h3>\n <p>%(date)s</p>"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
+#, python-format
+msgid "Add %(title)s to collection"
+msgstr "%(title)s ì˜ ëª¨ìŒì§‘ 추가"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
+msgid "+"
+msgstr "+"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
+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 "email ì¸ì¦ì´ 필요합니다."
+
+#: 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 "ê³§ email ì„ í†µí•´ 지침서가 ë„ì°©í•  ê²ë‹ˆë‹¤."
+
+#: 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:101
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:118
+msgid "Edit profile"
+msgstr "계정 정보 수정"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:106
+msgid "This user hasn't filled in their profile (yet)."
+msgstr "ì´ ì‚¬ìš©ìžëŠ” 계정 정보를 입력하지 않았습니다."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
+#, python-format
+msgid "View all of %(username)s's media"
+msgstr "%(username)sì˜ ëª¨ë“  미디어 보기"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
+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:157
+#: 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:20
+#, python-format
+msgid "In collections (%(collected)s)"
+msgstr "(%(collected)s) 모ìŒì§‘"
+
+#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
+msgid "feed icon"
+msgstr "피드 ì•„ì´ì½˜"
+
+#: mediagoblin/templates/mediagoblin/utils/feed_link.html:23
+msgid "Atom feed"
+msgstr "Atom 피드"
+
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:25
+msgid "Location"
+msgstr "장소"
+
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
+#, python-format
+msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
+msgstr " <a href=\"%(osm_url)s\">OpenStreetMap</a>으로 보기"
+
+#: mediagoblin/templates/mediagoblin/utils/license.html:25
+msgid "All rights reserved"
+msgstr "All rights reserved"
+
+#: 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:78
+msgid "Could not read the image file."
+msgstr "ì´ë¯¸ì§€ 파ì¼ì„ ì½ì„ 수 없습니다."
+
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr "ì›ìФ!"
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr ""
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr ""
+
+#: mediagoblin/tools/response.py:47
+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:55
+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/user_pages/forms.py:28
+msgid "I am sure I want to delete this"
+msgstr "ì´ê±¸ 지우고 싶습니다."
+
+#: mediagoblin/user_pages/forms.py:32
+msgid "I am sure I want to remove this item from the collection"
+msgstr "ì´ ëª¨ìŒì§‘ì˜ í•­ëª©ì„ ì‚­ì œí•˜ëŠ” ê²ƒì„ í™•ì¸ í–ˆìŠµë‹ˆë‹¤."
+
+#: mediagoblin/user_pages/forms.py:35
+msgid "-- Select --"
+msgstr "-- ì„ íƒ --"
+
+#: mediagoblin/user_pages/forms.py:37
+msgid "Include a note"
+msgstr "노트 추가"
+
+#: mediagoblin/user_pages/lib.py:56
+msgid "commented on your post"
+msgstr "ê²Œì‹œë¬¼ì— ë§ê¸€ì´ 달렸습니다."
+
+#: mediagoblin/user_pages/views.py:156
+msgid "Oops, your comment was empty."
+msgstr "오우, ëŒ“ê¸€ì´ ë¹„ì—ˆìŠµë‹ˆë‹¤."
+
+#: mediagoblin/user_pages/views.py:162
+msgid "Your comment has been posted!"
+msgstr "ëŒ“ê¸€ì´ ë“±ë¡ ë˜ì—ˆìŠµë‹ˆë‹¤!"
+
+#: mediagoblin/user_pages/views.py:230
+msgid "You have to select or add a collection"
+msgstr "모ìŒì§‘ì„ ì¶”ê°€í•˜ê±°ë‚˜ 기존 모ìŒì§‘ì„ ì„ íƒí•˜ì„¸ìš”."
+
+#: mediagoblin/user_pages/views.py:238
+#, python-format
+msgid "\"%s\" already in collection \"%s\""
+msgstr "\"%s\" 모ìŒì§‘ì´ ì´ë¯¸ 존재 합니다. \"%s\""
+
+#: mediagoblin/user_pages/views.py:253
+#, python-format
+msgid "\"%s\" added to collection \"%s\""
+msgstr "\"%s\" 모ìŒì§‘ì„ ì¶”ê°€í–ˆìŠµë‹ˆë‹¤. \"%s\""
+
+#: mediagoblin/user_pages/views.py:261
+msgid "Please check your entries and try again."
+msgstr "확ì¸ì„ 하시고 다시 시ë„하세요."
+
+#: mediagoblin/user_pages/views.py:292
+msgid ""
+"Some of the files with this entry seem to be missing. Deleting anyway."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:297
+msgid "You deleted the media."
+msgstr "미디어를 삭제 했습니다."
+
+#: mediagoblin/user_pages/views.py:304
+msgid "The media was not deleted because you didn't check that you were sure."
+msgstr "í™•ì¸ ì²´í¬ë¥¼ 하지 않았습니다. 미디어는 ì‚­ì œë˜ì§€ 않았습니다."
+
+#: mediagoblin/user_pages/views.py:312
+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:384
+msgid ""
+"You are about to delete an item from another user's collection. Proceed with"
+" caution."
+msgstr "다른 사용ìžì˜ 모ìŒì§‘ì— ìžˆëŠ” í•­ëª©ì„ ì‚­ì œí•˜ì˜€ìŠµë‹ˆë‹¤. 주ì˜í•˜ì„¸ìš”."
+
+#: mediagoblin/user_pages/views.py:417
+#, python-format
+msgid "You deleted the collection \"%s\""
+msgstr "\"%s\" 모ìŒì§‘ì„ ì‚­ì œí•˜ì…¨ìŠµë‹ˆë‹¤."
+
+#: mediagoblin/user_pages/views.py:424
+msgid ""
+"The collection was not deleted because you didn't check that you were sure."
+msgstr "확ì¸ì„ 하지 않았습니다. 모ìŒì§‘ì€ ì‚­ì œí•˜ì§€ 않았습니다."
+
+#: mediagoblin/user_pages/views.py:434
+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 c141e456..afa8849c 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 3b0cf98e..ba2907fb 100644
--- a/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.po
@@ -9,8 +9,8 @@ msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2012-09-24 14:01-0500\n"
-"PO-Revision-Date: 2012-09-24 18:57+0000\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 15:14+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
@@ -93,7 +93,7 @@ msgstr "Kon niemand vinden met die gebruikersnaam of dat e-mailadres."
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:83
+#: 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:40
msgid "Title"
@@ -104,7 +104,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:87 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:44
msgid ""
"You can use\n"
@@ -120,11 +120,11 @@ msgstr "Etiket"
msgid "Separate tags by commas."
msgstr "Hou labels gescheiden met komma's."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:91
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "Slug"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:92
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "De slug kan niet leeg zijn"
@@ -163,20 +163,20 @@ msgstr "Vul je oude wachtwoord in om te bewijzen dat dit jouw account is"
msgid "New password"
msgstr "Nieuw wachtwoord"
-#: mediagoblin/edit/forms.py:72
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr ""
-#: mediagoblin/edit/forms.py:84
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:43
msgid "Description of this collection"
msgstr ""
-#: mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
@@ -190,33 +190,38 @@ msgstr "Er bestaat al een met die slug voor deze gebruiker."
msgid "You are editing another user's media. Proceed with caution."
msgstr "U bent de media van een andere gebruiker aan het aanpassen. Ga voorzichtig te werk."
-#: mediagoblin/edit/views.py:182
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr ""
+
+#: mediagoblin/edit/views.py:181
msgid "You are editing a user's profile. Proceed with caution."
msgstr "U bent een gebruikersprofiel aan het aanpassen. Ga voorzichtig te werk."
-#: mediagoblin/edit/views.py:198
+#: mediagoblin/edit/views.py:197
msgid "Profile changes saved"
msgstr "Profielaanpassingen opgeslagen"
-#: mediagoblin/edit/views.py:227 mediagoblin/edit/views.py:247
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
msgid "Account settings saved"
msgstr "Accountinstellingen opgeslagen"
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:251
msgid "Wrong password"
msgstr "Verkeerd wachtwoord"
-#: mediagoblin/edit/views.py:288 mediagoblin/submit/views.py:211
-#: mediagoblin/user_pages/views.py:215
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr ""
-#: mediagoblin/edit/views.py:292
+#: mediagoblin/edit/views.py:291
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:309
+#: mediagoblin/edit/views.py:308
msgid "You are editing another user's collection. Proceed with caution."
msgstr ""
@@ -233,7 +238,7 @@ msgid "However, old link directory symlink found; removed.\n"
msgstr ""
#: mediagoblin/media_types/__init__.py:60
-#: mediagoblin/media_types/__init__.py:120
+#: mediagoblin/media_types/__init__.py:101
msgid "Sorry, I don't support that file type :("
msgstr "Sorry, dat bestandstype wordt niet ondersteunt."
@@ -303,7 +308,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:60
msgid "The client {0} has been registered!"
msgstr ""
@@ -328,62 +333,43 @@ msgstr "Mooizo! Toegevoegd!"
msgid "Collection \"%s\" added!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/404.html:24
-msgid "Image of 404 goblin stressing out"
-msgstr "Afbeelding van de 404 goblin onder stress"
-
-#: mediagoblin/templates/mediagoblin/404.html:25
-msgid "Oops!"
-msgstr "Oeps!"
-
-#: mediagoblin/templates/mediagoblin/404.html:26
-msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr "Het lijkt erop dat er geen pagina bestaat op dit adres. Sorry!"
-
-#: mediagoblin/templates/mediagoblin/404.html:28
-msgid ""
-"If you're sure the address is correct, maybe the page you're looking for has"
-" been moved or deleted."
-msgstr "Als je zeker weet dat het adres klopt is de pagina misschien verplaatst of verwijderd."
-
-#: mediagoblin/templates/mediagoblin/base.html:50
+#: mediagoblin/templates/mediagoblin/base.html:48
msgid "MediaGoblin logo"
msgstr "MediaGoblin logo"
-#: mediagoblin/templates/mediagoblin/base.html:60
-msgid "Verify your email!"
-msgstr "Verifieer je e-mailadres!"
-
-#: mediagoblin/templates/mediagoblin/base.html:66
-msgid "+ Add media"
-msgstr "+ Media toevoegen"
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
+msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:67
-msgid "+ Add collection"
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:69
-msgid "View your profile"
-msgstr "Profiel weergeven"
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
+msgstr "Voeg media toe"
-#: mediagoblin/templates/mediagoblin/base.html:70
-msgid "Log out"
-msgstr "Afmelden"
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
+msgstr "Verifieer je e-mailadres!"
-#: mediagoblin/templates/mediagoblin/base.html:75
+#: 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:89
+#: mediagoblin/templates/mediagoblin/base.html:87
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project."
msgstr "Hier draait <a href=\"http://mediagoblin.org\">MediaGoblin</a>, een <a href=\"http://gnu.org/\">GNU</a> project."
-#: mediagoblin/templates/mediagoblin/base.html:92
+#: mediagoblin/templates/mediagoblin/base.html:90
#, python-format
msgid ""
"Released under the <a "
@@ -391,31 +377,56 @@ msgid ""
"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/root.html:24
+#: mediagoblin/templates/mediagoblin/error.html:24
+msgid "Image of goblin stressing out"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:25
+msgid "Actions"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr "Accountinstellingen aanpassen"
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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 "Mediaverwerkingspaneel"
+
+#: mediagoblin/templates/mediagoblin/root.html:51
msgid "Explore"
msgstr "Verkennen"
-#: mediagoblin/templates/mediagoblin/root.html:26
+#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Hi there, welcome to this MediaGoblin site!"
msgstr "Hoi, welkom op deze MediaGoblin website!"
-#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/root.html:55
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:29
+#: mediagoblin/templates/mediagoblin/root.html:56
msgid ""
"To add your own media, place comments, and more, you can log in with your "
"MediaGoblin account."
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:31
+#: mediagoblin/templates/mediagoblin/root.html:58
msgid "Don't have one yet? It's easy!"
msgstr "Heb je er nog geen? Het is heel eenvoudig!"
-#: mediagoblin/templates/mediagoblin/root.html:32
+#: mediagoblin/templates/mediagoblin/root.html:59
#, python-format
msgid ""
"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
@@ -423,17 +434,10 @@ msgid ""
" <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:40
+#: mediagoblin/templates/mediagoblin/root.html:67
msgid "Most recent media"
msgstr "Nieuwste media"
-#: 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 "Mediaverwerkingspaneel"
-
#: mediagoblin/templates/mediagoblin/admin/panel.html:29
msgid ""
"Here you can track the state of media being processed on this instance."
@@ -542,30 +546,43 @@ msgstr "Hallo %(username)s , open de volgende URL in uw webbrowser om uw GNU Med
msgid "Editing attachments for %(media_title)s"
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 aanpassen"
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:43
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
+msgid "Attachments"
+msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:53
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
msgid "Cancel"
msgstr "Annuleren"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:43
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
msgid "Save changes"
msgstr "Wijzigingen opslaan"
+#: 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 aanpassen"
+
#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:41
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
#, python-format
msgid "Changing %(username)s's account settings"
msgstr "%(username)ss accountinstellingen aanpassen"
@@ -591,13 +608,12 @@ 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/image.html:23
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
msgid "Download"
msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:27
msgid "Original"
msgstr "Origineel"
@@ -624,6 +640,56 @@ msgstr ""
msgid "WebM file (Vorbis codec)"
msgstr ""
+#: 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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr "Afbeelding voor %(media_title)s"
+
+#: 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 ""
+
+#: 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:40
msgid ""
"Sorry, this video will not work because \n"
@@ -648,7 +714,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
#: mediagoblin/templates/mediagoblin/submit/start.html:34
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:83
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
msgid "Add"
msgstr "Voeg toe"
@@ -677,14 +743,6 @@ msgstr "Pas aan"
msgid "Delete"
msgstr "Verwijderen"
-#: mediagoblin/templates/mediagoblin/user_pages/collection.html:59
-#, python-format
-msgid ""
-"<p>\n"
-" %(collection_description)s\n"
-" </p>"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
@@ -692,7 +750,7 @@ msgid "Really delete %(title)s?"
msgstr "Zeker weten dat je %(title)s wil verwijderen?"
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "Permanent verwijderen"
@@ -701,7 +759,7 @@ msgstr "Permanent verwijderen"
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
msgid "Remove"
msgstr ""
@@ -727,12 +785,6 @@ 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:67
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
-#, python-format
-msgid "Image for %(media_title)s"
-msgstr "Afbeelding voor %(media_title)s"
-
#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
msgid "Add a comment"
msgstr "Geef een reactie"
@@ -759,13 +811,8 @@ msgid ""
" <p>%(date)s</p>"
msgstr "<h3>Toegevoegd op</h3>\n <p>%(date)s</p>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
-msgid "Attachments"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
-msgid "Add attachment"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
@@ -773,11 +820,11 @@ msgstr ""
msgid "Add %(title)s to collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
msgid "+"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
msgid "Add a new collection"
msgstr ""
@@ -848,41 +895,25 @@ msgstr "Profiel aanpassen."
msgid "This user hasn't filled in their profile (yet)."
msgstr "Deze gebruiker heeft zijn of haar profiel (nog) niet ingevuld."
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:125
-msgid "Change account settings"
-msgstr "Accountinstellingen aanpassen"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:138
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
#, python-format
msgid "View all of %(username)s's media"
msgstr "Bekijk alle media van %(username)s"
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
msgid ""
"This is where your media will appear, but you don't seem to have added "
"anything yet."
msgstr "Dit is waar je nieuwe media zal verschijnen, maar het lijkt erop dat je nog niets heb toegevoegd."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:157
-msgid "Add media"
-msgstr "Voeg media toe"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:163
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:87
-#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:72
+#: 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 "Het lijkt erop dat er nog geen media is."
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:39
-#, python-format
-msgid ""
-"<br />\n"
-" <a href=\"%(entry_url)s\">%(note)s</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:47
-#, python-format
-msgid "<br /><a href=\"%(remove_url)s\" class=\"remove\">(remove)</a>"
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
msgstr ""
#: mediagoblin/templates/mediagoblin/utils/collections.html:20
@@ -902,7 +933,7 @@ msgstr "Atom feed"
msgid "Location"
msgstr "Locatie"
-#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:38
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
#, python-format
msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
msgstr "Bekijken op <a href=\"%(osm_url)s\">OpenStreetMap</a>"
@@ -941,6 +972,32 @@ msgstr "Getagged met"
msgid "Could not read the image file."
msgstr "Kon het afbeeldingsbestand niet lezen."
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr "Oeps!"
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr ""
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr ""
+
+#: mediagoblin/tools/response.py:47
+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:55
+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/user_pages/forms.py:28
msgid "I am sure I want to delete this"
msgstr "Ik weet zeker dat ik dit wil verwijderen."
@@ -961,74 +1018,74 @@ msgstr ""
msgid "commented on your post"
msgstr ""
-#: mediagoblin/user_pages/views.py:161
+#: mediagoblin/user_pages/views.py:156
msgid "Oops, your comment was empty."
msgstr "Oeps, je bericht was leeg."
-#: mediagoblin/user_pages/views.py:167
+#: mediagoblin/user_pages/views.py:162
msgid "Your comment has been posted!"
msgstr "Je bericht is geplaatst!"
-#: mediagoblin/user_pages/views.py:235
+#: mediagoblin/user_pages/views.py:230
msgid "You have to select or add a collection"
msgstr ""
-#: mediagoblin/user_pages/views.py:243
+#: mediagoblin/user_pages/views.py:238
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:258
+#: mediagoblin/user_pages/views.py:253
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:266
+#: mediagoblin/user_pages/views.py:261
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:297
+#: mediagoblin/user_pages/views.py:292
msgid ""
"Some of the files with this entry seem to be missing. Deleting anyway."
msgstr ""
-#: mediagoblin/user_pages/views.py:302
+#: mediagoblin/user_pages/views.py:297
msgid "You deleted the media."
msgstr "Je hebt deze media verwijderd."
-#: mediagoblin/user_pages/views.py:309
+#: mediagoblin/user_pages/views.py:304
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:317
+#: mediagoblin/user_pages/views.py:312
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:379
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr ""
-#: mediagoblin/user_pages/views.py:383
+#: 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:393
+#: mediagoblin/user_pages/views.py:384
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:426
+#: mediagoblin/user_pages/views.py:417
#, python-format
msgid "You deleted the collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:433
+#: mediagoblin/user_pages/views.py:424
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:443
+#: mediagoblin/user_pages/views.py:434
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 986475ba..206c906c 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 4156c07b..2cfe7f61 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>, 2011, 2012.
+# <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: 2012-09-24 14:01-0500\n"
-"PO-Revision-Date: 2012-09-24 18:57+0000\n"
-"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 16:04+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"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -92,7 +92,7 @@ msgstr "Fann ingen med det brukarnamnet eller passordet."
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:83
+#: 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:40
msgid "Title"
@@ -100,10 +100,10 @@ msgstr "Tittel"
#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31
msgid "Description of this work"
-msgstr "Skildring av mediefila"
+msgstr "Skildring av verk"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:87 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:44
msgid ""
"You can use\n"
@@ -119,11 +119,11 @@ msgstr "Merkelappar"
msgid "Separate tags by commas."
msgstr "Separer merkelappar med komma."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:91
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "Nettnamn"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:92
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "Nettnamnet kan ikkje vera tomt"
@@ -131,7 +131,7 @@ msgstr "Nettnamnet kan ikkje vera tomt"
msgid ""
"The title part of this media's address. You usually don't need to change "
"this."
-msgstr "Nettnamnet (adressetittel) for mediefila di. Trengst ikkje endrast."
+msgstr "Nettnamnet (adressetittel) for verket di. Trengst ikkje endrast."
#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41
#: mediagoblin/templates/mediagoblin/utils/license.html:20
@@ -162,24 +162,24 @@ msgstr "Skriv inn det gamle passordet ditt for å stadfesta at du eig denne kont
msgid "New password"
msgstr "Nytt passord"
-#: mediagoblin/edit/forms.py:72
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
-msgstr ""
+msgstr "Send meg epost når andre kjem med innspel på verka mine."
-#: mediagoblin/edit/forms.py:84
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
-msgstr ""
+msgstr "Tittelen kjan ikkje vera tom"
-#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:43
msgid "Description of this collection"
-msgstr ""
+msgstr "Forklaringa til denne samlinga"
-#: mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
-msgstr ""
+msgstr "Tittel-delen av denne samlinga si adresse. Du treng normalt sett ikkje endra denne."
#: mediagoblin/edit/views.py:65
msgid "An entry with that slug already exists for this user."
@@ -187,96 +187,101 @@ msgstr "Eit innlegg med denne adressetittelen finst allereie."
#: mediagoblin/edit/views.py:86
msgid "You are editing another user's media. Proceed with caution."
-msgstr "Trå varsamt, du endrar nokon andre sine mediefiler."
+msgstr "Trå varsamt, du endrar nokon andre sine verk."
+
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr "La til vedlegg %s."
-#: mediagoblin/edit/views.py:182
+#: mediagoblin/edit/views.py:181
msgid "You are editing a user's profile. Proceed with caution."
msgstr "Trå varsamt, du endrar nokon andre sin profil."
-#: mediagoblin/edit/views.py:198
+#: mediagoblin/edit/views.py:197
msgid "Profile changes saved"
msgstr "Lagra endring av profilen"
-#: mediagoblin/edit/views.py:227 mediagoblin/edit/views.py:247
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
msgid "Account settings saved"
msgstr "Lagra kontoinstellingar"
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:251
msgid "Wrong password"
msgstr "Feil passord"
-#: mediagoblin/edit/views.py:288 mediagoblin/submit/views.py:211
-#: mediagoblin/user_pages/views.py:215
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
#, python-format
msgid "You already have a collection called \"%s\"!"
-msgstr ""
+msgstr "Du har allereie ei samling med namn «%s»."
-#: mediagoblin/edit/views.py:292
+#: mediagoblin/edit/views.py:291
msgid "A collection with that slug already exists for this user."
-msgstr ""
+msgstr "Ei samling med den nettadressa finst allereie for denne brukaren."
-#: mediagoblin/edit/views.py:309
+#: mediagoblin/edit/views.py:308
msgid "You are editing another user's collection. Proceed with caution."
-msgstr ""
+msgstr "Du endrar ein annan brukar si samling. Trå varsamt."
#: mediagoblin/gmg_commands/theme.py:58
msgid "Cannot link theme... no theme set\n"
-msgstr ""
+msgstr "Cannot link theme... no theme set\n"
#: mediagoblin/gmg_commands/theme.py:71
msgid "No asset directory for this theme\n"
-msgstr ""
+msgstr "No asset directory for this theme\n"
#: mediagoblin/gmg_commands/theme.py:74
msgid "However, old link directory symlink found; removed.\n"
-msgstr ""
+msgstr "However, old link directory symlink found; removed.\n"
#: mediagoblin/media_types/__init__.py:60
-#: mediagoblin/media_types/__init__.py:120
+#: mediagoblin/media_types/__init__.py:101
msgid "Sorry, I don't support that file type :("
msgstr "Orsak, stør ikkje den filtypen :("
#: mediagoblin/media_types/video/processing.py:35
msgid "Video transcoding failed"
-msgstr ""
+msgstr "Skjedde noko gale med video transkodinga"
#: mediagoblin/plugins/oauth/forms.py:26
msgid "Client ID"
-msgstr ""
+msgstr "Klient-ID (client ID)"
#: mediagoblin/plugins/oauth/forms.py:28
msgid "Next URL"
-msgstr ""
+msgstr "Neste adresse (next URL)"
#: mediagoblin/plugins/oauth/forms.py:30
msgid "Allow"
-msgstr ""
+msgstr "Godta"
#: mediagoblin/plugins/oauth/forms.py:31
msgid "Deny"
-msgstr ""
+msgstr "Nekt"
#: mediagoblin/plugins/oauth/forms.py:35
msgid "Name"
-msgstr ""
+msgstr "Namn"
#: mediagoblin/plugins/oauth/forms.py:36
msgid "The name of the OAuth client"
-msgstr ""
+msgstr "Namnet til OAuth-klienten"
#: mediagoblin/plugins/oauth/forms.py:37
msgid "Description"
-msgstr ""
+msgstr "Forklaring"
#: mediagoblin/plugins/oauth/forms.py:39
msgid ""
"This will be visible to users allowing your\n"
" application to authenticate as them."
-msgstr ""
+msgstr "Dette vil vera synleg for brukarar som godtek applikasjonen din til å autentisera dei."
#: mediagoblin/plugins/oauth/forms.py:41
msgid "Type"
-msgstr ""
+msgstr "Type"
#: mediagoblin/plugins/oauth/forms.py:46
msgid ""
@@ -286,29 +291,29 @@ 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>Confidential</strong> - Konfidensielt, på engelsk: 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> - Open, på engelsk: The client can't make confidential\n requests to the GNU MediaGoblin instance (e.g. client-side\n JavaScript client)."
#: mediagoblin/plugins/oauth/forms.py:53
msgid "Redirect URI"
-msgstr ""
+msgstr "Omdirigering URI"
#: mediagoblin/plugins/oauth/forms.py:55
msgid ""
"The redirect URI for the applications, this field\n"
" is <strong>required</strong> for public clients."
-msgstr ""
+msgstr "Omdirigerings-URI-en for programmene. Denne feltet <strong>krevst</strong> for opne (public) klientar."
#: mediagoblin/plugins/oauth/forms.py:67
msgid "This field is required for public clients"
-msgstr ""
+msgstr "Dette feltet krevst for opne (public) klientar"
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:60
msgid "The client {0} has been registered!"
-msgstr ""
+msgstr "Klienten {0} er registrert."
#: mediagoblin/processing/__init__.py:138
msgid "Invalid file given for media type."
-msgstr "Ugyldig fil for mediatypen."
+msgstr "Ugyldig fil for medietypen."
#: mediagoblin/submit/forms.py:26
msgid "File"
@@ -325,64 +330,45 @@ msgstr "Johoo! Opplasta!"
#: mediagoblin/submit/views.py:215
#, python-format
msgid "Collection \"%s\" added!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/404.html:24
-msgid "Image of 404 goblin stressing out"
-msgstr "Bilete av stressa 404-tusse."
-
-#: mediagoblin/templates/mediagoblin/404.html:25
-msgid "Oops!"
-msgstr "Oops."
-
-#: mediagoblin/templates/mediagoblin/404.html:26
-msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr "Det ser ikkje ut til å vera noko her... Orsak."
+msgstr "La til samlinga «%s»."
-#: mediagoblin/templates/mediagoblin/404.html:28
-msgid ""
-"If you're sure the address is correct, maybe the page you're looking for has"
-" been moved or deleted."
-msgstr "Er du sikker på at adressa er korrekt, so er sida truleg flytta eller sletta."
-
-#: mediagoblin/templates/mediagoblin/base.html:50
+#: mediagoblin/templates/mediagoblin/base.html:48
msgid "MediaGoblin logo"
msgstr "MediaGoblin"
-#: mediagoblin/templates/mediagoblin/base.html:60
-msgid "Verify your email!"
-msgstr "Verifiser epostadressa di."
-
-#: mediagoblin/templates/mediagoblin/base.html:66
-msgid "+ Add media"
-msgstr "+ Legg til medie"
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, 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:67
-msgid "+ Add collection"
-msgstr ""
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
+msgstr "Logg ut"
-#: mediagoblin/templates/mediagoblin/base.html:69
-msgid "View your profile"
-msgstr "Sjå profilen din"
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
+msgstr "Legg til verk"
-#: mediagoblin/templates/mediagoblin/base.html:70
-msgid "Log out"
-msgstr "Logg ut"
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
+msgstr "Verifiser epostadressa di."
-#: mediagoblin/templates/mediagoblin/base.html:75
+#: 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:89
+#: mediagoblin/templates/mediagoblin/base.html:87
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project."
msgstr "Drive av <a href=\"http://mediagoblin.org\">MediaGoblin</a>, eit <a href=\"http://gnu.org/\">GNU</a>-prosjekt."
-#: mediagoblin/templates/mediagoblin/base.html:92
+#: mediagoblin/templates/mediagoblin/base.html:90
#, python-format
msgid ""
"Released under the <a "
@@ -390,31 +376,56 @@ msgid ""
"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/root.html:24
+#: mediagoblin/templates/mediagoblin/error.html:24
+msgid "Image of goblin stressing out"
+msgstr "Bilete av stressa goblin"
+
+#: mediagoblin/templates/mediagoblin/root.html:25
+msgid "Actions"
+msgstr "Handlingar"
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr "Lag ny samling"
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr "Endra kontoinstellingar"
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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 "Verkprosesseringspanel"
+
+#: mediagoblin/templates/mediagoblin/root.html:51
msgid "Explore"
msgstr "Utforsk"
-#: mediagoblin/templates/mediagoblin/root.html:26
+#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Hi there, welcome to this MediaGoblin site!"
msgstr "Heihei, velkomen til denne MediaGoblin-sida."
-#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/root.html:55
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 mediefiler."
+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:29
+#: mediagoblin/templates/mediagoblin/root.html:56
msgid ""
"To add your own media, place comments, and more, you can log in with your "
"MediaGoblin account."
-msgstr ""
+msgstr "Vil du leggja til eigne verk og innpel, so må du logga inn."
-#: mediagoblin/templates/mediagoblin/root.html:31
+#: mediagoblin/templates/mediagoblin/root.html:58
msgid "Don't have one yet? It's easy!"
msgstr "Har du ikkje ein enno? Det er enkelt!"
-#: mediagoblin/templates/mediagoblin/root.html:32
+#: mediagoblin/templates/mediagoblin/root.html:59
#, python-format
msgid ""
"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
@@ -422,50 +433,43 @@ msgid ""
" <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:40
+#: mediagoblin/templates/mediagoblin/root.html:67
msgid "Most recent media"
-msgstr "Nyaste mediefiler"
-
-#: 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 "Mediehandsamingspanel"
+msgstr "Nyaste verk"
#: mediagoblin/templates/mediagoblin/admin/panel.html:29
msgid ""
"Here you can track the state of media being processed on this instance."
-msgstr ""
+msgstr "Hald oppsyn med statusen for prosessering av verka dine her."
#: mediagoblin/templates/mediagoblin/admin/panel.html:32
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32
msgid "Media in-processing"
-msgstr "Media under handsaming"
+msgstr "Verk under prosessesering"
#: mediagoblin/templates/mediagoblin/admin/panel.html:58
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:56
msgid "No media in-processing"
-msgstr "Ingen media under handsaming"
+msgstr "Ingen verk vert prosessert"
#: mediagoblin/templates/mediagoblin/admin/panel.html:61
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59
msgid "These uploads failed to process:"
-msgstr "Klarte ikkje handsama desse opplasta filene:"
+msgstr "Klarte ikkje prosessera desse opplasta filene:"
#: mediagoblin/templates/mediagoblin/admin/panel.html:90
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86
msgid "No failed entries!"
-msgstr ""
+msgstr "Ingen feila filer."
#: mediagoblin/templates/mediagoblin/admin/panel.html:92
msgid "Last 10 successful uploads"
-msgstr ""
+msgstr "Dei siste ti opplastningane"
#: mediagoblin/templates/mediagoblin/admin/panel.html:112
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107
msgid "No processed entries, yet!"
-msgstr ""
+msgstr "Ingenting prossesert, enno."
#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28
#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36
@@ -539,32 +543,45 @@ msgstr "Hei %(username)s,\n\nopna fylgjande netadresse i netlesaren din for å a
#: mediagoblin/templates/mediagoblin/edit/attachments.html:35
#, python-format
msgid "Editing attachments for %(media_title)s"
-msgstr ""
+msgstr "Endrar vedlegg for %(media_title)s"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:23
-#: mediagoblin/templates/mediagoblin/edit/edit.html:35
-#, python-format
-msgid "Editing %(media_title)s"
-msgstr "Endrar %(media_title)s"
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:43
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
+msgid "Attachments"
+msgstr "Vedlegg"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr "Legg ved vedlegg"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:53
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
msgid "Cancel"
msgstr "Bryt av"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:43
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
msgid "Save changes"
msgstr "Lagra"
+#: mediagoblin/templates/mediagoblin/edit/edit.html:23
+#: mediagoblin/templates/mediagoblin/edit/edit.html:35
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "Endrar %(media_title)s"
+
#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:41
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
#, python-format
msgid "Changing %(username)s's account settings"
msgstr "Endrar kontoinnstellingane til %(username)s"
@@ -572,7 +589,7 @@ msgstr "Endrar kontoinnstellingane til %(username)s"
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29
#, python-format
msgid "Editing %(collection_title)s"
-msgstr ""
+msgstr "Endrar %(collection_title)s"
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:23
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
@@ -586,17 +603,16 @@ msgstr "Endrar profilen til %(username)s"
#: mediagoblin/templates/mediagoblin/listings/tag.html:35
#, python-format
msgid "Media tagged with: %(tag_name)s"
-msgstr "Media merka med: %(tag_name)s"
+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/image.html:23
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
msgid "Download"
msgstr "Last ned"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:27
msgid "Original"
msgstr "Opphavleg"
@@ -617,12 +633,62 @@ msgstr "Du kan skaffa ein moderne netlesar som kan spela av dette lydklippet hjÃ
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
#: mediagoblin/templates/mediagoblin/media_displays/video.html:56
msgid "Original file"
-msgstr ""
+msgstr "Opphavleg fil"
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:63
msgid "WebM file (Vorbis codec)"
msgstr "WebM-fil (Vorbis-kodek)"
+#: 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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr "Bilete for %(media_title)s"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
+msgid "Toggle Rotate"
+msgstr "Slå av/på rotering"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113
+msgid "Perspective"
+msgstr "Perspektiv"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117
+msgid "Front"
+msgstr "Front"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121
+msgid "Top"
+msgstr "Topp"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125
+msgid "Side"
+msgstr "Side"
+
+#: 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 "Last ned modell"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146
+msgid "File Format"
+msgstr "Filformat"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148
+msgid "Object Height"
+msgstr "Objekthøgd"
+
#: mediagoblin/templates/mediagoblin/media_displays/video.html:40
msgid ""
"Sorry, this video will not work because \n"
@@ -639,32 +705,32 @@ msgstr "Du kan skaffa ein moderne netlesar som kan spela av denne videoen hjå <
#: mediagoblin/templates/mediagoblin/media_displays/video.html:59
msgid "WebM file (640p; VP8/Vorbis)"
-msgstr ""
+msgstr "WebM fil (640p; VP8/Vorbis)"
#: mediagoblin/templates/mediagoblin/submit/collection.html:26
msgid "Add a collection"
-msgstr ""
+msgstr "Legg til ei samling"
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
#: mediagoblin/templates/mediagoblin/submit/start.html:34
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:83
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
msgid "Add"
msgstr "Legg til"
#: mediagoblin/templates/mediagoblin/submit/start.html:23
#: mediagoblin/templates/mediagoblin/submit/start.html:30
msgid "Add your media"
-msgstr "Legg til mediefiler"
+msgstr "Legg til verk"
#: 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 si samling)"
#: 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 av <a href=\"%(user_url)s\">%(username)s</a>"
#: mediagoblin/templates/mediagoblin/user_pages/collection.html:52
#: mediagoblin/templates/mediagoblin/user_pages/media.html:87
@@ -676,14 +742,6 @@ msgstr "Endra"
msgid "Delete"
msgstr "Slett"
-#: mediagoblin/templates/mediagoblin/user_pages/collection.html:59
-#, python-format
-msgid ""
-"<p>\n"
-" %(collection_description)s\n"
-" </p>"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
@@ -691,46 +749,40 @@ msgid "Really delete %(title)s?"
msgstr "Vil du verkeleg sletta %(title)s?"
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "Slett permanent"
#: 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 "Fjerna %(media_title)s frå %(collection_title)s?"
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
msgid "Remove"
-msgstr ""
+msgstr "Fjern"
#: 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 "Hei %(username)s,\n%(comment_author)s kommenterte innlegget ditt (%(comment_url)s) hjå %(instance_name)s\n"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30
#, python-format
msgid "%(username)s's media"
-msgstr "Filene til %(username)s"
+msgstr "Verka til %(username)s"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:37
#, python-format
msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media"
-msgstr "<a href=\"%(user_url)s\">%(username)s</a> sine mediefiler"
+msgstr "<a href=\"%(user_url)s\">%(username)s</a> sine verk"
#: mediagoblin/templates/mediagoblin/user_pages/media.html:46
#, python-format
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
-msgstr "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:67
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
-#, python-format
-msgid "Image for %(media_title)s"
-msgstr "Bilete for %(media_title)s"
+msgstr "■Ser på <a href=\"%(user_url)s\">%(username)s</a> sine verk"
#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
msgid "Add a comment"
@@ -758,36 +810,31 @@ msgid ""
" <p>%(date)s</p>"
msgstr "<h3>Lagt til</h3>\n <p>%(date)s</p>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
-msgid "Attachments"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
-msgid "Add attachment"
-msgstr ""
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
+msgstr "Legg til verk til samling"
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
#, python-format
msgid "Add %(title)s to collection"
-msgstr ""
+msgstr "Putt %(title)s inn i samling"
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
msgid "+"
-msgstr ""
+msgstr "+"
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
msgid "Add a new collection"
-msgstr ""
+msgstr "Legg til ei ny samling"
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:29
msgid ""
"You can track the state of media being processed for your gallery here."
-msgstr "Sjå status for mediehandsaming av biletene dine her."
+msgstr "Sjå status for prosessering av verka dine her."
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:89
msgid "Your last 10 successful uploads"
-msgstr ""
+msgstr "Dine ti siste opplastningar."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:31
#: mediagoblin/templates/mediagoblin/user_pages/user.html:89
@@ -847,47 +894,31 @@ msgstr "Endra profil"
msgid "This user hasn't filled in their profile (yet)."
msgstr "Brukaren har ikkje fylt ut profilen sin (enno)."
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:125
-msgid "Change account settings"
-msgstr "Endra kontoinstellingar"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:138
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
#, python-format
msgid "View all of %(username)s's media"
-msgstr "Sjå alle %(username)s sine mediefiler"
+msgstr "Sjå alle %(username)s sine verk"
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
msgid ""
"This is where your media will appear, but you don't seem to have added "
"anything yet."
-msgstr "Her kjem mediefilene dine."
+msgstr "Her kjem verka dine."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:157
-msgid "Add media"
-msgstr "Legg til mediefiler"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:163
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:87
-#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:72
+#: 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 "Ser ikkje ut til at det finst nokon mediefiler her nett no."
+msgstr "Ser ikkje ut til at det finst nokon verk her nett no."
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:39
-#, python-format
-msgid ""
-"<br />\n"
-" <a href=\"%(entry_url)s\">%(note)s</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:47
-#, python-format
-msgid "<br /><a href=\"%(remove_url)s\" class=\"remove\">(remove)</a>"
-msgstr ""
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
+msgstr "(fjern)"
#: mediagoblin/templates/mediagoblin/utils/collections.html:20
#, python-format
msgid "In collections (%(collected)s)"
-msgstr ""
+msgstr "I samlingar (%(collected)s)"
#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
msgid "feed icon"
@@ -901,7 +932,7 @@ msgstr "Atom-kjelde"
msgid "Location"
msgstr "Stad"
-#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:38
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
#, python-format
msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
msgstr "Sjå på <a href=\"%(osm_url)s\">OpenStreetMap</a>"
@@ -940,94 +971,120 @@ msgstr "Merka med"
msgid "Could not read the image file."
msgstr "Klarte ikkje lesa biletefila."
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr "Oops."
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr "Noko gjekk gale"
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr "Ulovleg operasjon"
+
+#: mediagoblin/tools/response.py:47
+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 "Orsak Dave, eg kan ikkje la deg gjera det!&lt;HAL2000&gt;</p>\n<p>Du prøvde å gjera noko du ikkje har løyve til. Prøvar du å sletta alle brukarkonti no igjen?"
+
+#: mediagoblin/tools/response.py:55
+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 "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/user_pages/forms.py:28
msgid "I am sure I want to delete this"
msgstr "Eg er sikker eg vil sletta dette"
#: mediagoblin/user_pages/forms.py:32
msgid "I am sure I want to remove this item from the collection"
-msgstr ""
+msgstr "Eg er sikker på at eg vil fjerna dette frå samlinga"
#: mediagoblin/user_pages/forms.py:35
msgid "-- Select --"
-msgstr ""
+msgstr "-- Vel --"
#: mediagoblin/user_pages/forms.py:37
msgid "Include a note"
-msgstr ""
+msgstr "Legg ved eit notat"
#: mediagoblin/user_pages/lib.py:56
msgid "commented on your post"
-msgstr ""
+msgstr "kom med innspel på innlegget ditt"
-#: mediagoblin/user_pages/views.py:161
+#: mediagoblin/user_pages/views.py:156
msgid "Oops, your comment was empty."
msgstr "Vops, innspelet ditt var tomt."
-#: mediagoblin/user_pages/views.py:167
+#: mediagoblin/user_pages/views.py:162
msgid "Your comment has been posted!"
msgstr "Innspelet ditt er lagt til."
-#: mediagoblin/user_pages/views.py:235
+#: mediagoblin/user_pages/views.py:230
msgid "You have to select or add a collection"
-msgstr ""
+msgstr "Du må velja eller laga ei samling"
-#: mediagoblin/user_pages/views.py:243
+#: mediagoblin/user_pages/views.py:238
#, python-format
msgid "\"%s\" already in collection \"%s\""
-msgstr ""
+msgstr "«%s» er allereie i samling «%s»"
-#: mediagoblin/user_pages/views.py:258
+#: mediagoblin/user_pages/views.py:253
#, python-format
msgid "\"%s\" added to collection \"%s\""
-msgstr ""
+msgstr "«%s» lagt til samling «%s»"
-#: mediagoblin/user_pages/views.py:266
+#: mediagoblin/user_pages/views.py:261
msgid "Please check your entries and try again."
-msgstr ""
+msgstr "Sjekk filene dine og prøv omatt."
-#: mediagoblin/user_pages/views.py:297
+#: mediagoblin/user_pages/views.py:292
msgid ""
"Some of the files with this entry seem to be missing. Deleting anyway."
-msgstr ""
+msgstr "Nokre av filene ser ut til å mangla. Slettar likevel."
-#: mediagoblin/user_pages/views.py:302
+#: mediagoblin/user_pages/views.py:297
msgid "You deleted the media."
-msgstr "Du sletta fila."
+msgstr "Du sletta verket."
-#: mediagoblin/user_pages/views.py:309
+#: mediagoblin/user_pages/views.py:304
msgid "The media was not deleted because you didn't check that you were sure."
-msgstr "Sletta ikkje fila fordi du ikkje sa du var sikker."
+msgstr "Sletta ikkje verket."
-#: mediagoblin/user_pages/views.py:317
+#: mediagoblin/user_pages/views.py:312
msgid "You are about to delete another user's media. Proceed with caution."
-msgstr "Du er i ferd med å sletta ein annan brukar sine mediefiler. Trå varsamt."
+msgstr "Du er i ferd med å sletta ein annan brukar sine verk. Trå varsamt."
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
-msgstr ""
+msgstr "Du fjerna fila frå samlinga."
-#: mediagoblin/user_pages/views.py:383
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
-msgstr ""
+msgstr "Fila var ikkje fjerna fordi du ikkje var sikker."
-#: mediagoblin/user_pages/views.py:393
+#: mediagoblin/user_pages/views.py:384
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
-msgstr ""
+msgstr "Du er i ferd med å fjerna ei fil frå ein annan brukar si samling. Trå varsamt."
-#: mediagoblin/user_pages/views.py:426
+#: mediagoblin/user_pages/views.py:417
#, python-format
msgid "You deleted the collection \"%s\""
-msgstr ""
+msgstr "Samlinga «%s» sletta"
-#: mediagoblin/user_pages/views.py:433
+#: mediagoblin/user_pages/views.py:424
msgid ""
"The collection was not deleted because you didn't check that you were sure."
-msgstr ""
+msgstr "Sletta ikkje samlinga."
-#: mediagoblin/user_pages/views.py:443
+#: mediagoblin/user_pages/views.py:434
msgid ""
"You are about to delete another user's collection. Proceed with caution."
-msgstr ""
+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 77dcfe12..64a4d00f 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 7dea3837..b516065d 100644
--- a/mediagoblin/i18n/pl/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/pl/LC_MESSAGES/mediagoblin.po
@@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2012-09-24 14:01-0500\n"
-"PO-Revision-Date: 2012-09-24 18:57+0000\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 15:14+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
@@ -92,7 +92,7 @@ msgstr "Nie znaleziono nikogo o takiej nazwie użytkownika lub adresie e-mail."
msgid "You can now log in using your new password."
msgstr "Teraz możesz się zalogować używając nowe hasło."
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:83
+#: 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:40
msgid "Title"
@@ -103,7 +103,7 @@ msgid "Description of this work"
msgstr "Opis tej pracy"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:87 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:44
msgid ""
"You can use\n"
@@ -119,11 +119,11 @@ msgstr "Znaczniki"
msgid "Separate tags by commas."
msgstr "Rozdzielaj znaczniki przecinkami."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:91
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "Slug"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:92
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "Slug nie może być pusty"
@@ -162,20 +162,20 @@ msgstr "Wprowadź swoje stare hasło aby udowodnić, że to twoje konto."
msgid "New password"
msgstr "Nowe hasło"
-#: mediagoblin/edit/forms.py:72
+#: 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:84
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr "Tytuł nie może być pusty"
-#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:43
msgid "Description of this collection"
msgstr "Opis tej kolekcji"
-#: mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
@@ -189,33 +189,38 @@ msgstr "Adres z tym slugiem dla tego użytkownika już istnieje."
msgid "You are editing another user's media. Proceed with caution."
msgstr "Edytujesz media innego użytkownika. Zachowaj ostrożność."
-#: mediagoblin/edit/views.py:182
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr ""
+
+#: mediagoblin/edit/views.py:181
msgid "You are editing a user's profile. Proceed with caution."
msgstr "Edytujesz profil innego użytkownika. Zachowaj ostrożność."
-#: mediagoblin/edit/views.py:198
+#: mediagoblin/edit/views.py:197
msgid "Profile changes saved"
msgstr "Zapisano zmiany profilu"
-#: mediagoblin/edit/views.py:227 mediagoblin/edit/views.py:247
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
msgid "Account settings saved"
msgstr "Zapisano ustawienia konta"
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:251
msgid "Wrong password"
msgstr "Nieprawidłowe hasło"
-#: mediagoblin/edit/views.py:288 mediagoblin/submit/views.py:211
-#: mediagoblin/user_pages/views.py:215
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr "Kolekcja \"%s\" już istnieje!"
-#: mediagoblin/edit/views.py:292
+#: mediagoblin/edit/views.py:291
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:309
+#: mediagoblin/edit/views.py:308
msgid "You are editing another user's collection. Proceed with caution."
msgstr "Edytujesz kolekcję innego użytkownika. Zachowaj ostrożność."
@@ -232,7 +237,7 @@ msgid "However, old link directory symlink found; removed.\n"
msgstr "Znaleziono stary odnośnik symboliczny do katalogu; usunięto.\n"
#: mediagoblin/media_types/__init__.py:60
-#: mediagoblin/media_types/__init__.py:120
+#: mediagoblin/media_types/__init__.py:101
msgid "Sorry, I don't support that file type :("
msgstr "NIestety, nie obsługujemy tego typu plików :-("
@@ -302,7 +307,7 @@ 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:60
msgid "The client {0} has been registered!"
msgstr "Klient {0} został zarejestrowany!"
@@ -327,62 +332,43 @@ msgstr "Hura! Wysłano!"
msgid "Collection \"%s\" added!"
msgstr "Kolekcja \"%s\" została dodana!"
-#: mediagoblin/templates/mediagoblin/404.html:24
-msgid "Image of 404 goblin stressing out"
-msgstr "Grafika zestresowanego goblina 404."
-
-#: mediagoblin/templates/mediagoblin/404.html:25
-msgid "Oops!"
-msgstr "Ups!"
-
-#: mediagoblin/templates/mediagoblin/404.html:26
-msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr "Niestety, nie ma strony o takim adresie!"
-
-#: mediagoblin/templates/mediagoblin/404.html:28
-msgid ""
-"If you're sure the address is correct, maybe the page you're looking for has"
-" been moved or deleted."
-msgstr "Jeśli twoim zdaniem ten adres jest prawidłowy, to może poszukiwana strona została przeniesiona lub usunięta."
-
-#: mediagoblin/templates/mediagoblin/base.html:50
+#: mediagoblin/templates/mediagoblin/base.html:48
msgid "MediaGoblin logo"
msgstr "Logo MediaGoblin"
-#: mediagoblin/templates/mediagoblin/base.html:60
-msgid "Verify your email!"
-msgstr "Zweryfikuj swój adres e-mail!"
-
-#: mediagoblin/templates/mediagoblin/base.html:66
-msgid "+ Add media"
-msgstr "+ Dodaj media"
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
+msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:67
-msgid "+ Add collection"
-msgstr "+ Dodaj kolekcjÄ™"
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
+msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:69
-msgid "View your profile"
-msgstr "Zobacz swój profil"
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
+msgstr "Dodaj media"
-#: mediagoblin/templates/mediagoblin/base.html:70
-msgid "Log out"
-msgstr "Wyloguj siÄ™"
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
+msgstr "Zweryfikuj swój adres e-mail!"
-#: mediagoblin/templates/mediagoblin/base.html:75
+#: 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:89
+#: mediagoblin/templates/mediagoblin/base.html:87
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project."
msgstr "Obsługiwane przez <a href=\"http://mediagoblin.org\">MediaGoblin</a>, projekt <a href=\"http://gnu.org/\">GNU</a>."
-#: mediagoblin/templates/mediagoblin/base.html:92
+#: mediagoblin/templates/mediagoblin/base.html:90
#, python-format
msgid ""
"Released under the <a "
@@ -390,31 +376,56 @@ msgid ""
"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/root.html:24
+#: mediagoblin/templates/mediagoblin/error.html:24
+msgid "Image of goblin stressing out"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:25
+msgid "Actions"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr "Zmień ustawienia konta"
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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 "Panel przetwarzania mediów"
+
+#: mediagoblin/templates/mediagoblin/root.html:51
msgid "Explore"
msgstr "Odkrywaj"
-#: mediagoblin/templates/mediagoblin/root.html:26
+#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Hi there, welcome to this MediaGoblin site!"
msgstr "Cześć, witaj na stronie MediaGoblin!"
-#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/root.html:55
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:29
+#: mediagoblin/templates/mediagoblin/root.html:56
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:31
+#: mediagoblin/templates/mediagoblin/root.html:58
msgid "Don't have one yet? It's easy!"
msgstr "Jeszcze go nie masz? To proste!"
-#: mediagoblin/templates/mediagoblin/root.html:32
+#: mediagoblin/templates/mediagoblin/root.html:59
#, python-format
msgid ""
"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
@@ -422,17 +433,10 @@ msgid ""
" <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:40
+#: mediagoblin/templates/mediagoblin/root.html:67
msgid "Most recent media"
msgstr "Najnowsze media"
-#: 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 "Panel przetwarzania mediów"
-
#: mediagoblin/templates/mediagoblin/admin/panel.html:29
msgid ""
"Here you can track the state of media being processed on this instance."
@@ -541,30 +545,43 @@ msgstr "Cześć %(username)s,\n\naby aktywować twoje konto GNU MediaGoblin, otw
msgid "Editing attachments for %(media_title)s"
msgstr "Edycja załączników do %(media_title)s"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:23
-#: mediagoblin/templates/mediagoblin/edit/edit.html:35
-#, python-format
-msgid "Editing %(media_title)s"
-msgstr "Edytowanie %(media_title)s"
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:43
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
+msgid "Attachments"
+msgstr "Załączniki"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr "Dodaj załącznik"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:53
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
msgid "Cancel"
msgstr "Anuluj"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:43
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
msgid "Save changes"
msgstr "Zapisz zmiany"
+#: mediagoblin/templates/mediagoblin/edit/edit.html:23
+#: mediagoblin/templates/mediagoblin/edit/edit.html:35
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "Edytowanie %(media_title)s"
+
#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:41
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
#, python-format
msgid "Changing %(username)s's account settings"
msgstr "Zmiana ustawień konta %(username)s"
@@ -590,13 +607,12 @@ 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/image.html:23
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
msgid "Download"
msgstr "Pobierz"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:27
msgid "Original"
msgstr "Oryginał"
@@ -623,6 +639,56 @@ msgstr "Oryginalny plik"
msgid "WebM file (Vorbis codec)"
msgstr "plik WebM (kodek Vorbis)"
+#: 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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr "Grafika dla %(media_title)s"
+
+#: 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 ""
+
+#: 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:40
msgid ""
"Sorry, this video will not work because \n"
@@ -647,7 +713,7 @@ msgstr "Dodaj kolekcjÄ™"
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
#: mediagoblin/templates/mediagoblin/submit/start.html:34
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:83
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
msgid "Add"
msgstr "Dodaj"
@@ -676,14 +742,6 @@ msgstr "Edytuj"
msgid "Delete"
msgstr "Usuń"
-#: mediagoblin/templates/mediagoblin/user_pages/collection.html:59
-#, python-format
-msgid ""
-"<p>\n"
-" %(collection_description)s\n"
-" </p>"
-msgstr "<p>\n %(collection_description)s\n </p>"
-
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
@@ -691,7 +749,7 @@ msgid "Really delete %(title)s?"
msgstr "Na pewno usunąć %(title)s?"
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "Usuń na stałe"
@@ -700,7 +758,7 @@ msgstr "Usuń na stałe"
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:54
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
msgid "Remove"
msgstr "Usuń"
@@ -726,12 +784,6 @@ 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:67
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
-#, python-format
-msgid "Image for %(media_title)s"
-msgstr "Grafika dla %(media_title)s"
-
#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
msgid "Add a comment"
msgstr "Dodaj komentarz"
@@ -758,25 +810,20 @@ msgid ""
" <p>%(date)s</p>"
msgstr "<h3>Dodane</h3>\n <p>%(date)s</p>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
-msgid "Attachments"
-msgstr "Załączniki"
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
-msgid "Add attachment"
-msgstr "Dodaj załącznik"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
+msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
#, python-format
msgid "Add %(title)s to collection"
msgstr "Dodaj %(title)s do kolekcji"
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
msgid "+"
msgstr "+"
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
msgid "Add a new collection"
msgstr "Dodaj nowÄ… kolekcjÄ™"
@@ -847,42 +894,26 @@ msgstr "Edytuj profil"
msgid "This user hasn't filled in their profile (yet)."
msgstr "Ten użytkownik nie wypełnił (jeszcze) opisu swojego profilu."
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:125
-msgid "Change account settings"
-msgstr "Zmień ustawienia konta"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:138
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
#, python-format
msgid "View all of %(username)s's media"
msgstr "Zobacz wszystkie media użytkownika %(username)s"
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
msgid ""
"This is where your media will appear, but you don't seem to have added "
"anything yet."
msgstr "Tu będą widoczne twoje media, ale na razie niczego tu jeszcze nie ma."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:157
-msgid "Add media"
-msgstr "Dodaj media"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:163
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:87
-#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:72
+#: 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 "Tu nie ma jeszcze żadnych mediów..."
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:39
-#, python-format
-msgid ""
-"<br />\n"
-" <a href=\"%(entry_url)s\">%(note)s</a>"
-msgstr "<br />\n <a href=\"%(entry_url)s\">%(note)s</a>"
-
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:47
-#, python-format
-msgid "<br /><a href=\"%(remove_url)s\" class=\"remove\">(remove)</a>"
-msgstr "<br /><a href=\"%(remove_url)s\" class=\"remove\">(usuń)</a>"
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
+msgstr ""
#: mediagoblin/templates/mediagoblin/utils/collections.html:20
#, python-format
@@ -901,7 +932,7 @@ msgstr "Kanał Atom"
msgid "Location"
msgstr "Położenie"
-#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:38
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
#, python-format
msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
msgstr "Zobacz na <a href=\"%(osm_url)s\">OpenStreetMap</a>"
@@ -940,6 +971,32 @@ msgstr "Znaczniki:"
msgid "Could not read the image file."
msgstr "Nie udało się odczytać pliku grafiki."
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr "Ups!"
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr ""
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr ""
+
+#: mediagoblin/tools/response.py:47
+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:55
+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/user_pages/forms.py:28
msgid "I am sure I want to delete this"
msgstr "Na pewno chcę to usunąć"
@@ -960,74 +1017,74 @@ msgstr "Dodaj notatkÄ™"
msgid "commented on your post"
msgstr "komentarze do twojego wpisu"
-#: mediagoblin/user_pages/views.py:161
+#: mediagoblin/user_pages/views.py:156
msgid "Oops, your comment was empty."
msgstr "Ups, twój komentarz nie zawierał treści."
-#: mediagoblin/user_pages/views.py:167
+#: mediagoblin/user_pages/views.py:162
msgid "Your comment has been posted!"
msgstr "Twój komentarz został opublikowany!"
-#: mediagoblin/user_pages/views.py:235
+#: mediagoblin/user_pages/views.py:230
msgid "You have to select or add a collection"
msgstr "Musisz wybrać lub dodać kolekcję"
-#: mediagoblin/user_pages/views.py:243
+#: mediagoblin/user_pages/views.py:238
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr "\"%s\" już obecne w kolekcji \"%s\""
-#: mediagoblin/user_pages/views.py:258
+#: mediagoblin/user_pages/views.py:253
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr "\"%s\" dodano do kolekcji \"%s\""
-#: mediagoblin/user_pages/views.py:266
+#: mediagoblin/user_pages/views.py:261
msgid "Please check your entries and try again."
msgstr "Sprawdź swoje wpisy i spróbuj ponownie."
-#: mediagoblin/user_pages/views.py:297
+#: mediagoblin/user_pages/views.py:292
msgid ""
"Some of the files with this entry seem to be missing. Deleting anyway."
msgstr "Część plików z tego wpisu wygląda na nieistniejące. Trwa usuwanie."
-#: mediagoblin/user_pages/views.py:302
+#: mediagoblin/user_pages/views.py:297
msgid "You deleted the media."
msgstr "Media zostały usunięte."
-#: mediagoblin/user_pages/views.py:309
+#: mediagoblin/user_pages/views.py:304
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:317
+#: mediagoblin/user_pages/views.py:312
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:379
+#: 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:383
+#: 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:393
+#: mediagoblin/user_pages/views.py:384
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:426
+#: mediagoblin/user_pages/views.py:417
#, python-format
msgid "You deleted the collection \"%s\""
msgstr "Usunięto kolekcję \"%s\""
-#: mediagoblin/user_pages/views.py:433
+#: mediagoblin/user_pages/views.py:424
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:443
+#: mediagoblin/user_pages/views.py:434
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 1552ce78..2cad018a 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 ff431932..66a28516 100644
--- a/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.po
@@ -9,8 +9,8 @@ msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2012-09-24 14:01-0500\n"
-"PO-Revision-Date: 2012-09-24 18:57+0000\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 15:14+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"
@@ -93,7 +93,7 @@ msgstr ""
msgid "You can now log in using your new password."
msgstr ""
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:83
+#: 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:40
msgid "Title"
@@ -104,7 +104,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:87 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:44
msgid ""
"You can use\n"
@@ -120,11 +120,11 @@ msgstr "Etiquetas"
msgid "Separate tags by commas."
msgstr ""
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:91
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "Arquivo"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:92
+#: 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"
@@ -163,20 +163,20 @@ msgstr ""
msgid "New password"
msgstr ""
-#: mediagoblin/edit/forms.py:72
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr ""
-#: mediagoblin/edit/forms.py:84
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:43
msgid "Description of this collection"
msgstr ""
-#: mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
@@ -190,33 +190,38 @@ msgstr "Uma entrada com esse arquivo já existe para esse usuário"
msgid "You are editing another user's media. Proceed with caution."
msgstr "Você está editando a mídia de outro usuário. Tenha cuidado."
-#: mediagoblin/edit/views.py:182
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr ""
+
+#: mediagoblin/edit/views.py:181
msgid "You are editing a user's profile. Proceed with caution."
msgstr "Você está editando um perfil de usuário. Tenha cuidado."
-#: mediagoblin/edit/views.py:198
+#: mediagoblin/edit/views.py:197
msgid "Profile changes saved"
msgstr ""
-#: mediagoblin/edit/views.py:227 mediagoblin/edit/views.py:247
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
msgid "Account settings saved"
msgstr ""
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:251
msgid "Wrong password"
msgstr "Senha errada"
-#: mediagoblin/edit/views.py:288 mediagoblin/submit/views.py:211
-#: mediagoblin/user_pages/views.py:215
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr ""
-#: mediagoblin/edit/views.py:292
+#: mediagoblin/edit/views.py:291
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:309
+#: mediagoblin/edit/views.py:308
msgid "You are editing another user's collection. Proceed with caution."
msgstr ""
@@ -233,7 +238,7 @@ msgid "However, old link directory symlink found; removed.\n"
msgstr ""
#: mediagoblin/media_types/__init__.py:60
-#: mediagoblin/media_types/__init__.py:120
+#: mediagoblin/media_types/__init__.py:101
msgid "Sorry, I don't support that file type :("
msgstr ""
@@ -303,7 +308,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:60
msgid "The client {0} has been registered!"
msgstr ""
@@ -328,62 +333,43 @@ msgstr "Eba! Enviado!"
msgid "Collection \"%s\" added!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/404.html:24
-msgid "Image of 404 goblin stressing out"
-msgstr "Imagem do goblin 404 aparecendo"
-
-#: mediagoblin/templates/mediagoblin/404.html:25
-msgid "Oops!"
-msgstr "Oops"
-
-#: mediagoblin/templates/mediagoblin/404.html:26
-msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr "Aparentemente não existe uma página com esse endereço. Desculpe!"
-
-#: mediagoblin/templates/mediagoblin/404.html:28
-msgid ""
-"If you're sure the address is correct, maybe the page you're looking for has"
-" been moved or deleted."
-msgstr "Se você está certo de que o endereço está correto, talvez a página que esteja procurando tenha sido apagada ou mudou de endereço"
-
-#: mediagoblin/templates/mediagoblin/base.html:50
+#: mediagoblin/templates/mediagoblin/base.html:48
msgid "MediaGoblin logo"
msgstr "Logo MediaGoblin"
-#: mediagoblin/templates/mediagoblin/base.html:60
-msgid "Verify your email!"
-msgstr "Verifique seu email!"
-
-#: mediagoblin/templates/mediagoblin/base.html:66
-msgid "+ Add media"
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:67
-msgid "+ Add collection"
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:69
-msgid "View your profile"
-msgstr ""
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
+msgstr "Adicionar mídia"
-#: mediagoblin/templates/mediagoblin/base.html:70
-msgid "Log out"
-msgstr ""
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
+msgstr "Verifique seu email!"
-#: mediagoblin/templates/mediagoblin/base.html:75
+#: 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:89
+#: mediagoblin/templates/mediagoblin/base.html:87
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project."
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:92
+#: mediagoblin/templates/mediagoblin/base.html:90
#, python-format
msgid ""
"Released under the <a "
@@ -391,31 +377,56 @@ msgid ""
"href=\"%(source_link)s\">Source code</a> available."
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:24
+#: mediagoblin/templates/mediagoblin/error.html:24
+msgid "Image of goblin stressing out"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:25
+msgid "Actions"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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 "Painel de processamento de mídia"
+
+#: mediagoblin/templates/mediagoblin/root.html:51
msgid "Explore"
msgstr "Explorar"
-#: mediagoblin/templates/mediagoblin/root.html:26
+#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Hi there, welcome to this MediaGoblin site!"
msgstr "Olá, bemvindo ao site de MediaGoblin."
-#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/root.html:55
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:29
+#: mediagoblin/templates/mediagoblin/root.html:56
msgid ""
"To add your own media, place comments, and more, you can log in with your "
"MediaGoblin account."
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:31
+#: mediagoblin/templates/mediagoblin/root.html:58
msgid "Don't have one yet? It's easy!"
msgstr " "
-#: mediagoblin/templates/mediagoblin/root.html:32
+#: mediagoblin/templates/mediagoblin/root.html:59
#, python-format
msgid ""
"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
@@ -423,17 +434,10 @@ msgid ""
" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:40
+#: mediagoblin/templates/mediagoblin/root.html:67
msgid "Most recent media"
msgstr "Mídia mais recente"
-#: 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 "Painel de processamento de mídia"
-
#: mediagoblin/templates/mediagoblin/admin/panel.html:29
msgid ""
"Here you can track the state of media being processed on this instance."
@@ -542,30 +546,43 @@ msgstr "Olá %(username)s,\n\nPara ativar sua conta GNU MediaGoblin, visite este
msgid "Editing attachments for %(media_title)s"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit.html:23
-#: mediagoblin/templates/mediagoblin/edit/edit.html:35
-#, python-format
-msgid "Editing %(media_title)s"
-msgstr "Editando %(media_title)s"
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:43
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
+msgid "Attachments"
+msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:53
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
msgid "Cancel"
msgstr "Cancelar"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:43
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
msgid "Save changes"
msgstr "Salvar mudanças"
+#: mediagoblin/templates/mediagoblin/edit/edit.html:23
+#: mediagoblin/templates/mediagoblin/edit/edit.html:35
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "Editando %(media_title)s"
+
#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:41
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
#, python-format
msgid "Changing %(username)s's account settings"
msgstr ""
@@ -591,13 +608,12 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:23
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
msgid "Download"
msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:27
msgid "Original"
msgstr "Original"
@@ -624,6 +640,56 @@ msgstr ""
msgid "WebM file (Vorbis codec)"
msgstr ""
+#: 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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr ""
+
+#: 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 ""
+
+#: 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:40
msgid ""
"Sorry, this video will not work because \n"
@@ -648,7 +714,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
#: mediagoblin/templates/mediagoblin/submit/start.html:34
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:83
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
msgid "Add"
msgstr ""
@@ -677,14 +743,6 @@ msgstr "Editar"
msgid "Delete"
msgstr "Apagar"
-#: mediagoblin/templates/mediagoblin/user_pages/collection.html:59
-#, python-format
-msgid ""
-"<p>\n"
-" %(collection_description)s\n"
-" </p>"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
@@ -692,7 +750,7 @@ msgid "Really delete %(title)s?"
msgstr "Realmente apagar %(title)s ?"
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr ""
@@ -701,7 +759,7 @@ msgstr ""
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
msgid "Remove"
msgstr ""
@@ -727,12 +785,6 @@ 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 ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:67
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
-#, python-format
-msgid "Image for %(media_title)s"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
msgid "Add a comment"
msgstr ""
@@ -759,13 +811,8 @@ msgid ""
" <p>%(date)s</p>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
-msgid "Attachments"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
-msgid "Add attachment"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
@@ -773,11 +820,11 @@ msgstr ""
msgid "Add %(title)s to collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
msgid "+"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
msgid "Add a new collection"
msgstr ""
@@ -848,41 +895,25 @@ msgstr "Editar perfil"
msgid "This user hasn't filled in their profile (yet)."
msgstr "Esse usuário não preencheu seu perfil (ainda)."
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:125
-msgid "Change account settings"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:138
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
#, python-format
msgid "View all of %(username)s's media"
msgstr "Ver todas as mídias de %(username)s"
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
msgid ""
"This is where your media will appear, but you don't seem to have added "
"anything yet."
msgstr "Aqui é onde sua mídia vai aparecer, mas parece que você não adicionou nada ainda."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:157
-msgid "Add media"
-msgstr "Adicionar mídia"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:163
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:87
-#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:72
+#: 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..."
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:39
-#, python-format
-msgid ""
-"<br />\n"
-" <a href=\"%(entry_url)s\">%(note)s</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:47
-#, python-format
-msgid "<br /><a href=\"%(remove_url)s\" class=\"remove\">(remove)</a>"
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
msgstr ""
#: mediagoblin/templates/mediagoblin/utils/collections.html:20
@@ -902,7 +933,7 @@ msgstr "Atom feed"
msgid "Location"
msgstr ""
-#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:38
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
#, python-format
msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
msgstr ""
@@ -941,6 +972,32 @@ msgstr ""
msgid "Could not read the image file."
msgstr ""
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr "Oops"
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr ""
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr ""
+
+#: mediagoblin/tools/response.py:47
+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:55
+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/user_pages/forms.py:28
msgid "I am sure I want to delete this"
msgstr "Eu tenho certeza de que quero pagar isso"
@@ -961,74 +1018,74 @@ msgstr ""
msgid "commented on your post"
msgstr ""
-#: mediagoblin/user_pages/views.py:161
+#: mediagoblin/user_pages/views.py:156
msgid "Oops, your comment was empty."
msgstr "Opa, seu comentáio estava vazio."
-#: mediagoblin/user_pages/views.py:167
+#: mediagoblin/user_pages/views.py:162
msgid "Your comment has been posted!"
msgstr "Seu comentário foi postado!"
-#: mediagoblin/user_pages/views.py:235
+#: mediagoblin/user_pages/views.py:230
msgid "You have to select or add a collection"
msgstr ""
-#: mediagoblin/user_pages/views.py:243
+#: mediagoblin/user_pages/views.py:238
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:258
+#: mediagoblin/user_pages/views.py:253
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:266
+#: mediagoblin/user_pages/views.py:261
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:297
+#: mediagoblin/user_pages/views.py:292
msgid ""
"Some of the files with this entry seem to be missing. Deleting anyway."
msgstr ""
-#: mediagoblin/user_pages/views.py:302
+#: mediagoblin/user_pages/views.py:297
msgid "You deleted the media."
msgstr "Você deletou a mídia."
-#: mediagoblin/user_pages/views.py:309
+#: mediagoblin/user_pages/views.py:304
msgid "The media was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:317
+#: mediagoblin/user_pages/views.py:312
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:379
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr ""
-#: mediagoblin/user_pages/views.py:383
+#: 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:393
+#: mediagoblin/user_pages/views.py:384
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:426
+#: mediagoblin/user_pages/views.py:417
#, python-format
msgid "You deleted the collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:433
+#: mediagoblin/user_pages/views.py:424
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:443
+#: mediagoblin/user_pages/views.py:434
msgid ""
"You are about to delete another user's collection. Proceed with caution."
msgstr ""
diff --git a/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.mo
index 8a759873..dc64a04b 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 e391869b..4929de7a 100644
--- a/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.po
@@ -9,8 +9,8 @@ msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2012-09-24 14:01-0500\n"
-"PO-Revision-Date: 2012-09-24 18:57+0000\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 15:14+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: Romanian (http://www.transifex.com/projects/p/mediagoblin/language/ro/)\n"
"MIME-Version: 1.0\n"
@@ -93,7 +93,7 @@ msgstr "Nu s-a găsit nicio persoană cu acel nume de utilizator sau adresă de
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:83
+#: 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:40
msgid "Title"
@@ -104,7 +104,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:87 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:44
msgid ""
"You can use\n"
@@ -120,11 +120,11 @@ msgstr "Tag-uri"
msgid "Separate tags by commas."
msgstr "Desparte tag-urile prin virgulă."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:91
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "Identificator"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:92
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "Identificatorul nu poate să lipsească"
@@ -163,20 +163,20 @@ msgstr "Introdu vechea parolă pentru a demonstra că ești titularul acestui co
msgid "New password"
msgstr "Noua parolă"
-#: mediagoblin/edit/forms.py:72
+#: 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:84
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr "Titlul nu poate să fie gol"
-#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:43
msgid "Description of this collection"
msgstr "Descriere pentru această colecție"
-#: mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
@@ -190,33 +190,38 @@ msgstr "Există deja un entry cu același identificator pentru acest utilizator.
msgid "You are editing another user's media. Proceed with caution."
msgstr "Editezi fișierul unui alt utilizator. Se recomandă prudență."
-#: mediagoblin/edit/views.py:182
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr "Ai anexat %s!"
+
+#: mediagoblin/edit/views.py:181
msgid "You are editing a user's profile. Proceed with caution."
msgstr "Editezi profilul unui utilizator. Se recomandă prudență."
-#: mediagoblin/edit/views.py:198
+#: mediagoblin/edit/views.py:197
msgid "Profile changes saved"
msgstr "Modificările profilului au fost salvate"
-#: mediagoblin/edit/views.py:227 mediagoblin/edit/views.py:247
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
msgid "Account settings saved"
msgstr "Setările pentru acest cont au fost salvate"
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:251
msgid "Wrong password"
msgstr "Parolă incorectă"
-#: mediagoblin/edit/views.py:288 mediagoblin/submit/views.py:211
-#: mediagoblin/user_pages/views.py:215
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr "Ai deja o colecție numită \"%s\"!"
-#: mediagoblin/edit/views.py:292
+#: mediagoblin/edit/views.py:291
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:309
+#: mediagoblin/edit/views.py:308
msgid "You are editing another user's collection. Proceed with caution."
msgstr "Lucrezi pe colecția unui alt utilizator. Se recomandă prudență."
@@ -233,7 +238,7 @@ 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/media_types/__init__.py:60
-#: mediagoblin/media_types/__init__.py:120
+#: mediagoblin/media_types/__init__.py:101
msgid "Sorry, I don't support that file type :("
msgstr "Scuze, nu recunosc acest tip de fișier :("
@@ -273,7 +278,7 @@ msgstr "Descriere"
msgid ""
"This will be visible to users allowing your\n"
" application to authenticate as them."
-msgstr ""
+msgstr "Aceste informații vor fi vizibile pentru utilizatorii\n care permit aplicației tale să se autentifice în numele lor."
#: mediagoblin/plugins/oauth/forms.py:41
msgid "Type"
@@ -303,7 +308,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:60
msgid "The client {0} has been registered!"
msgstr "Clientul {0} a fost înregistrat!"
@@ -328,62 +333,43 @@ msgstr "Ura! Trimis!"
msgid "Collection \"%s\" added!"
msgstr "Colecția \"%s\" a fost creată!"
-#: mediagoblin/templates/mediagoblin/404.html:24
-msgid "Image of 404 goblin stressing out"
-msgstr "Imagine cu elful 404 stresat."
-
-#: mediagoblin/templates/mediagoblin/404.html:25
-msgid "Oops!"
-msgstr "Hopa!"
-
-#: mediagoblin/templates/mediagoblin/404.html:26
-msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr "Nu există nicio pagină la această adresă. Ne pare rău!"
-
-#: mediagoblin/templates/mediagoblin/404.html:28
-msgid ""
-"If you're sure the address is correct, maybe the page you're looking for has"
-" been moved or deleted."
-msgstr "Dacă ești sigur că adresa e corectă, poate că pagina pe care o cauți a fost mutată sau ștearsă."
-
-#: mediagoblin/templates/mediagoblin/base.html:50
+#: mediagoblin/templates/mediagoblin/base.html:48
msgid "MediaGoblin logo"
msgstr "logo MediaGoblin"
-#: mediagoblin/templates/mediagoblin/base.html:60
-msgid "Verify your email!"
-msgstr "Verifică adresa de e-mail!"
-
-#: mediagoblin/templates/mediagoblin/base.html:66
-msgid "+ Add media"
-msgstr "+ Adaugă fișier media"
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, 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:67
-msgid "+ Add collection"
-msgstr "+ Creează colecție"
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
+msgstr "Ieșire"
-#: mediagoblin/templates/mediagoblin/base.html:69
-msgid "View your profile"
-msgstr "Vezi profilul tău"
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
+msgstr "Trimite fișier"
-#: mediagoblin/templates/mediagoblin/base.html:70
-msgid "Log out"
-msgstr "Ieșire"
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
+msgstr "Verifică adresa de e-mail!"
-#: mediagoblin/templates/mediagoblin/base.html:75
+#: 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:89
+#: mediagoblin/templates/mediagoblin/base.html:87
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project."
msgstr "Construit cu <a href=\"http://mediagoblin.org\">MediaGoblin</a>, un proiect <a href=\"http://gnu.org/\">GNU</a>."
-#: mediagoblin/templates/mediagoblin/base.html:92
+#: mediagoblin/templates/mediagoblin/base.html:90
#, python-format
msgid ""
"Released under the <a "
@@ -391,31 +377,56 @@ msgid ""
"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/root.html:24
+#: mediagoblin/templates/mediagoblin/error.html:24
+msgid "Image of goblin stressing out"
+msgstr "Imagine cu un goblin stresat"
+
+#: mediagoblin/templates/mediagoblin/root.html:25
+msgid "Actions"
+msgstr "Acțiuni"
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr "Creează colecție nouă"
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr "Modifică setările contului"
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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 "Panou de procesare media"
+
+#: mediagoblin/templates/mediagoblin/root.html:51
msgid "Explore"
msgstr "Explorează"
-#: mediagoblin/templates/mediagoblin/root.html:26
+#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Hi there, welcome to this MediaGoblin site!"
msgstr "Salut, bine ai venit pe acest site MediaGoblin!"
-#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/root.html:55
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:29
+#: mediagoblin/templates/mediagoblin/root.html:56
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:31
+#: mediagoblin/templates/mediagoblin/root.html:58
msgid "Don't have one yet? It's easy!"
msgstr "Încă nu ai unul? E simplu!"
-#: mediagoblin/templates/mediagoblin/root.html:32
+#: mediagoblin/templates/mediagoblin/root.html:59
#, python-format
msgid ""
"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
@@ -423,17 +434,10 @@ msgid ""
" <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:40
+#: mediagoblin/templates/mediagoblin/root.html:67
msgid "Most recent media"
msgstr "Cele mai recente fișiere"
-#: 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 "Panou de procesare media"
-
#: mediagoblin/templates/mediagoblin/admin/panel.html:29
msgid ""
"Here you can track the state of media being processed on this instance."
@@ -498,7 +502,7 @@ msgid ""
"\n"
"If you think this is an error, just ignore this email and continue being\n"
"a happy goblin!"
-msgstr "Bună, %(username)s\n\nPentru a schimba parola ta la GNU MediaGoblin, accesează adresa următoare:\n\n%(verification_url)s\n\nDacă ai primit acest mesaj din greșeală, ignoră-l și fii mai departe un elf fericit!"
+msgstr "Bună, %(username)s\n\nPentru a schimba parola ta la GNU MediaGoblin, accesează adresa următoare:\n\n%(verification_url)s\n\nDacă ai primit acest mesaj din greșeală, ignoră-l și fii mai departe un goblin fericit!"
#: mediagoblin/templates/mediagoblin/auth/login.html:39
msgid "Logging in failed!"
@@ -542,30 +546,43 @@ msgstr "Bună, %(username)s,\n\npentru activarea contului tău la GNU MediaGobli
msgid "Editing attachments for %(media_title)s"
msgstr "Editare anexe la %(media_title)s"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:23
-#: mediagoblin/templates/mediagoblin/edit/edit.html:35
-#, python-format
-msgid "Editing %(media_title)s"
-msgstr "Editare %(media_title)s"
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:43
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
+msgid "Attachments"
+msgstr "Anexe"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr "Atașează"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:53
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
msgid "Cancel"
msgstr "Anulare"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:43
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
msgid "Save changes"
msgstr "Salvează modificările"
+#: mediagoblin/templates/mediagoblin/edit/edit.html:23
+#: mediagoblin/templates/mediagoblin/edit/edit.html:35
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "Editare %(media_title)s"
+
#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:41
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
#, python-format
msgid "Changing %(username)s's account settings"
msgstr "Se modifică setările contului pentru userul %(username)s"
@@ -591,13 +608,12 @@ msgstr "Fișier etichetat cu tag-urile: %(tag_name)s"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:23
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
msgid "Download"
msgstr "Download"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:27
msgid "Original"
msgstr "Original"
@@ -624,6 +640,56 @@ msgstr "Fișierul original"
msgid "WebM file (Vorbis codec)"
msgstr "Fișier WebM (codec Vorbis)"
+#: 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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr "Imagine pentru %(media_title)s"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
+msgid "Toggle Rotate"
+msgstr "Rotire"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113
+msgid "Perspective"
+msgstr "Perspectivă"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117
+msgid "Front"
+msgstr "Din față"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121
+msgid "Top"
+msgstr "De sus"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125
+msgid "Side"
+msgstr "Lateral"
+
+#: 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 "Descarcă modelul"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146
+msgid "File Format"
+msgstr "Formatul fișierului"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148
+msgid "Object Height"
+msgstr "Înălțimea obiectului"
+
#: mediagoblin/templates/mediagoblin/media_displays/video.html:40
msgid ""
"Sorry, this video will not work because \n"
@@ -648,7 +714,7 @@ msgstr "Creează o colecție"
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
#: mediagoblin/templates/mediagoblin/submit/start.html:34
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:83
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
msgid "Add"
msgstr "Adaugă"
@@ -677,14 +743,6 @@ msgstr "Editare"
msgid "Delete"
msgstr "Șterge"
-#: mediagoblin/templates/mediagoblin/user_pages/collection.html:59
-#, python-format
-msgid ""
-"<p>\n"
-" %(collection_description)s\n"
-" </p>"
-msgstr "<p>\n %(collection_description)s\n </p>"
-
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
@@ -692,7 +750,7 @@ msgid "Really delete %(title)s?"
msgstr "Sigur dorești să ștergi %(title)s?"
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "Șterge definitiv"
@@ -701,7 +759,7 @@ msgstr "Șterge definitiv"
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:54
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
msgid "Remove"
msgstr "Șterge"
@@ -727,12 +785,6 @@ 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:67
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
-#, python-format
-msgid "Image for %(media_title)s"
-msgstr "Imagine pentru %(media_title)s"
-
#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
msgid "Add a comment"
msgstr "Adaugă un comentariu"
@@ -759,25 +811,20 @@ msgid ""
" <p>%(date)s</p>"
msgstr "<h3>Adăugat la</h3>\n <p>%(date)s</p>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
-msgid "Attachments"
-msgstr "Anexe"
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
-msgid "Add attachment"
-msgstr "Atașează"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
+msgstr "Adaugă un fișier la colecție"
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
#, python-format
msgid "Add %(title)s to collection"
msgstr "Adaugă %(title)s la colecție"
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
msgid "+"
msgstr "+"
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
msgid "Add a new collection"
msgstr "Creează o nouă colecție"
@@ -848,42 +895,26 @@ msgstr "Editare profil"
msgid "This user hasn't filled in their profile (yet)."
msgstr "Acest utilizator nu și-a completat (încă) profilul."
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:125
-msgid "Change account settings"
-msgstr "Modifică setările contului"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:138
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
#, python-format
msgid "View all of %(username)s's media"
msgstr "Vezi toate fișierele media ale lui %(username)s"
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
msgid ""
"This is where your media will appear, but you don't seem to have added "
"anything yet."
msgstr "Aici vor apărea fișierele tale media, dar se pare că încă nu ai trimis nimic."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:157
-msgid "Add media"
-msgstr "Trimite fișier"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:163
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:87
-#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:72
+#: 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 "Nu pare să existe niciun fișier media deocamdată..."
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:39
-#, python-format
-msgid ""
-"<br />\n"
-" <a href=\"%(entry_url)s\">%(note)s</a>"
-msgstr "<br />\n <a href=\"%(entry_url)s\">%(note)s</a>"
-
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:47
-#, python-format
-msgid "<br /><a href=\"%(remove_url)s\" class=\"remove\">(remove)</a>"
-msgstr "<br /><a href=\"%(remove_url)s\" class=\"remove\">(șterge)</a>"
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
+msgstr "(șterge)"
#: mediagoblin/templates/mediagoblin/utils/collections.html:20
#, python-format
@@ -902,7 +933,7 @@ msgstr "feed Atom"
msgid "Location"
msgstr "Locul"
-#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:38
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
#, python-format
msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
msgstr "Vezi pe <a href=\"%(osm_url)s\">OpenStreetMap</a>"
@@ -941,6 +972,32 @@ msgstr "Etichete"
msgid "Could not read the image file."
msgstr "Fișierul cu imaginea nu a putut fi citit."
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr "Hopa!"
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr "S-a produs o eroare"
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr "Operația nu este permisă"
+
+#: mediagoblin/tools/response.py:47
+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 "Îmi pare rău, Dave, nu te pot lăsa să faci asta!</p><p>Ai încercat să faci o operație nepermisă. Ai încercat iar să ștergi toate conturile utilizatorilor?"
+
+#: mediagoblin/tools/response.py:55
+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 "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/user_pages/forms.py:28
msgid "I am sure I want to delete this"
msgstr "Sunt sigur că doresc să șterg"
@@ -961,74 +1018,74 @@ msgstr "Adaugă o notiță"
msgid "commented on your post"
msgstr "a făcut un comentariu la postarea ta"
-#: mediagoblin/user_pages/views.py:161
+#: mediagoblin/user_pages/views.py:156
msgid "Oops, your comment was empty."
msgstr "Hopa, ai uitat să scrii comentariul."
-#: mediagoblin/user_pages/views.py:167
+#: mediagoblin/user_pages/views.py:162
msgid "Your comment has been posted!"
msgstr "Comentariul tău a fost trimis!"
-#: mediagoblin/user_pages/views.py:235
+#: mediagoblin/user_pages/views.py:230
msgid "You have to select or add a collection"
msgstr "Trebuie să alegi sau să creezi o colecție"
-#: mediagoblin/user_pages/views.py:243
+#: mediagoblin/user_pages/views.py:238
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr "\"%s\" este deja în colecția \"%s\""
-#: mediagoblin/user_pages/views.py:258
+#: mediagoblin/user_pages/views.py:253
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr "\"%s\" a fost adăugat la colecția \"%s\""
-#: mediagoblin/user_pages/views.py:266
+#: mediagoblin/user_pages/views.py:261
msgid "Please check your entries and try again."
msgstr "Verifică datele și încearcă din nou."
-#: mediagoblin/user_pages/views.py:297
+#: mediagoblin/user_pages/views.py:292
msgid ""
"Some of the files with this entry seem to be missing. Deleting anyway."
msgstr "Unele fișiere din acest entry par să lipsească. Ștergem, totuși."
-#: mediagoblin/user_pages/views.py:302
+#: mediagoblin/user_pages/views.py:297
msgid "You deleted the media."
msgstr "Ai șters acest fișier"
-#: mediagoblin/user_pages/views.py:309
+#: mediagoblin/user_pages/views.py:304
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:317
+#: mediagoblin/user_pages/views.py:312
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:379
+#: 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:383
+#: 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:393
+#: mediagoblin/user_pages/views.py:384
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:426
+#: mediagoblin/user_pages/views.py:417
#, python-format
msgid "You deleted the collection \"%s\""
msgstr "Ai șters colecția \"%s\""
-#: mediagoblin/user_pages/views.py:433
+#: mediagoblin/user_pages/views.py:424
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:443
+#: mediagoblin/user_pages/views.py:434
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 d8967294..5cb985ec 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 8785e8ac..f7ae7d29 100644
--- a/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.po
@@ -8,9 +8,9 @@ msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2012-09-24 11:41-0500\n"
-"PO-Revision-Date: 2012-09-24 18:15+0000\n"
-"Last-Translator: aleksejrs <deletesoftware@yandex.ru>\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 15:14+0000\n"
+"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -92,7 +92,7 @@ msgstr "Ðе найдено никого Ñ Ñ‚Ð°ÐºÐ¸Ð¼ именем пользо
msgid "You can now log in using your new password."
msgstr "Теперь вы можете войти, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð²Ð°Ñˆ новый пароль."
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:83
+#: 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:40
msgid "Title"
@@ -103,7 +103,7 @@ msgid "Description of this work"
msgstr "ОпиÑание Ñтого произведениÑ"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:87 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:44
msgid ""
"You can use\n"
@@ -119,11 +119,11 @@ msgstr "Метки"
msgid "Separate tags by commas."
msgstr "(через запÑтую)"
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:91
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "ÐžÑ‚Ð»Ð¸Ñ‡Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ñ‡Ð°Ñть адреÑа"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:92
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "ÐžÑ‚Ð»Ð¸Ñ‡Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ñ‡Ð°Ñть адреÑа необходима"
@@ -162,20 +162,20 @@ msgstr "Введите Ñвой Ñтарый пароль в качеÑтве д
msgid "New password"
msgstr "Ðовый пароль"
-#: mediagoblin/edit/forms.py:72
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr "УведомлÑть Ð¼ÐµÐ½Ñ Ð¿Ð¾ e-mail о комментариÑÑ… к моим файлам"
-#: mediagoblin/edit/forms.py:84
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
-msgstr ""
+msgstr "Ðазвание не может быть пуÑтым"
-#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:43
msgid "Description of this collection"
msgstr "ОпиÑание Ñтой коллекции"
-#: mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
@@ -189,32 +189,38 @@ msgstr "У Ñтого Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ ÑƒÐ¶Ðµ еÑть файл Ñ Ñ‚Ð°Ð
msgid "You are editing another user's media. Proceed with caution."
msgstr "Ð’Ñ‹ редактируете файлы другого пользователÑ. Будьте оÑторожны."
-#: mediagoblin/edit/views.py:182
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr "Ð’Ñ‹ добавили ÑопутÑтвующий файл %s!"
+
+#: mediagoblin/edit/views.py:181
msgid "You are editing a user's profile. Proceed with caution."
msgstr "Ð’Ñ‹ редактируете профиль пользователÑ. Будьте оÑторожны."
-#: mediagoblin/edit/views.py:198
+#: mediagoblin/edit/views.py:197
msgid "Profile changes saved"
msgstr "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ñ„Ð¸Ð»Ñ Ñохранены"
-#: mediagoblin/edit/views.py:227 mediagoblin/edit/views.py:247
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
msgid "Account settings saved"
msgstr "ÐаÑтройки учётной запиÑи запиÑаны"
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:251
msgid "Wrong password"
msgstr "Ðеправильный пароль"
-#: mediagoblin/edit/views.py:287
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
#, python-format
-msgid "You already have a collection called \"%s\"!title"
-msgstr "У Ð²Ð°Ñ ÑƒÐ¶Ðµ еÑть ÐºÐ¾Ð»Ð»ÐµÐºÑ†Ð¸Ñ Â«%s»!title"
+msgid "You already have a collection called \"%s\"!"
+msgstr "У Ð²Ð°Ñ ÑƒÐ¶Ðµ еÑть ÐºÐ¾Ð»Ð»ÐµÐºÑ†Ð¸Ñ Ñ Ð½Ð°Ð·Ð²Ð°Ð½Ð¸ÐµÐ¼ «%s»!"
-#: mediagoblin/edit/views.py:290
+#: mediagoblin/edit/views.py:291
msgid "A collection with that slug already exists for this user."
msgstr "У Ñтого Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ ÑƒÐ¶Ðµ еÑть ÐºÐ¾Ð»Ð»ÐµÐºÑ†Ð¸Ñ Ñ Ñ‚Ð°ÐºÐ¾Ð¹ отличительной чаÑтью адреÑа."
-#: mediagoblin/edit/views.py:307
+#: mediagoblin/edit/views.py:308
msgid "You are editing another user's collection. Proceed with caution."
msgstr "Ð’Ñ‹ редактируете коллекцию другого пользователÑ. Будьте оÑторожны."
@@ -231,7 +237,7 @@ msgid "However, old link directory symlink found; removed.\n"
msgstr "Однако найдена (и удалена) ÑÑ‚Ð°Ñ€Ð°Ñ ÑимволичеÑÐºÐ°Ñ ÑÑылка на каталог.\n"
#: mediagoblin/media_types/__init__.py:60
-#: mediagoblin/media_types/__init__.py:120
+#: mediagoblin/media_types/__init__.py:101
msgid "Sorry, I don't support that file type :("
msgstr "Увы, Ñ Ð½Ðµ поддерживаю Ñтот тип файлов :("
@@ -265,7 +271,7 @@ msgstr ""
#: mediagoblin/plugins/oauth/forms.py:37
msgid "Description"
-msgstr ""
+msgstr "ОпиÑание"
#: mediagoblin/plugins/oauth/forms.py:39
msgid ""
@@ -301,7 +307,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:60
msgid "The client {0} has been registered!"
msgstr ""
@@ -321,72 +327,48 @@ msgstr "Вы должны загрузить файл."
msgid "Woohoo! Submitted!"
msgstr "Ура! Файл загружен!"
-#: mediagoblin/submit/views.py:211 mediagoblin/user_pages/views.py:215
-#, python-format
-msgid "You already have a collection called \"%s\"!"
-msgstr "У Ð²Ð°Ñ ÑƒÐ¶Ðµ еÑть ÐºÐ¾Ð»Ð»ÐµÐºÑ†Ð¸Ñ Ñ Ð½Ð°Ð·Ð²Ð°Ð½Ð¸ÐµÐ¼ «%s»!"
-
#: mediagoblin/submit/views.py:215
#, python-format
msgid "Collection \"%s\" added!"
msgstr "ÐšÐ¾Ð»Ð»ÐµÐºÑ†Ð¸Ñ Â«%s» добавлена!"
-#: mediagoblin/templates/mediagoblin/404.html:24
-msgid "Image of 404 goblin stressing out"
-msgstr "Изображение 404 нервничающего гоблина"
-
-#: mediagoblin/templates/mediagoblin/404.html:25
-msgid "Oops!"
-msgstr "Ой!"
-
-#: mediagoblin/templates/mediagoblin/404.html:26
-msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr "КажетÑÑ, такой Ñтраницы не ÑущеÑтвует. Уж извините!"
-
-#: mediagoblin/templates/mediagoblin/404.html:28
-msgid ""
-"If you're sure the address is correct, maybe the page you're looking for has"
-" been moved or deleted."
-msgstr "Возможно, Ñтраница, которую вы ищете, была удалена или переехала."
-
-#: mediagoblin/templates/mediagoblin/base.html:50
+#: mediagoblin/templates/mediagoblin/base.html:48
msgid "MediaGoblin logo"
msgstr "Символ MediaGoblin"
-#: mediagoblin/templates/mediagoblin/base.html:60
-msgid "Verify your email!"
-msgstr "Подтвердите ваш Ð°Ð´Ñ€ÐµÑ Ñлектронной почты!"
-
-#: mediagoblin/templates/mediagoblin/base.html:66
-msgid "+ Add media"
-msgstr "+ Добавить файл"
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, 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:67
-msgid "+ Add collection"
-msgstr "+ Добавить коллекцию"
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
+msgstr "завершение ÑеанÑа"
-#: mediagoblin/templates/mediagoblin/base.html:69
-msgid "View your profile"
-msgstr "ПоÑмотреть Ñвой профиль"
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
+msgstr "Добавить файлы"
-#: mediagoblin/templates/mediagoblin/base.html:70
-msgid "Log out"
-msgstr "Завершение ÑеанÑа"
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
+msgstr "Подтвердите ваш Ð°Ð´Ñ€ÐµÑ Ñлектронной почты!"
-#: mediagoblin/templates/mediagoblin/base.html:75
+#: 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:89
+#: mediagoblin/templates/mediagoblin/base.html:87
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project."
msgstr "Работает на <a href=\"http://mediagoblin.org\">MediaGoblin</a>, проекте <a href=\"http://gnu.org/\">GNU</a>."
-#: mediagoblin/templates/mediagoblin/base.html:92
+#: mediagoblin/templates/mediagoblin/base.html:90
#, python-format
msgid ""
"Released under the <a "
@@ -394,31 +376,56 @@ msgid ""
"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/root.html:24
+#: mediagoblin/templates/mediagoblin/error.html:24
+msgid "Image of goblin stressing out"
+msgstr "Изображение нервничающего гоблина"
+
+#: mediagoblin/templates/mediagoblin/root.html:25
+msgid "Actions"
+msgstr "ДейÑтвиÑ"
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr "Создать новую коллекцию"
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr "Изменить наÑтройки учётной запиÑи"
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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/root.html:51
msgid "Explore"
msgstr "Смотреть"
-#: mediagoblin/templates/mediagoblin/root.html:26
+#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Hi there, welcome to this MediaGoblin site!"
msgstr "Привет! Добро пожаловать на наш MediaGoblin’овый Ñайт!"
-#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/root.html:55
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:29
+#: mediagoblin/templates/mediagoblin/root.html:56
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:31
+#: mediagoblin/templates/mediagoblin/root.html:58
msgid "Don't have one yet? It's easy!"
msgstr "У Ð²Ð°Ñ ÐµÑ‘ ещё нет? Ðе проблема!"
-#: mediagoblin/templates/mediagoblin/root.html:32
+#: mediagoblin/templates/mediagoblin/root.html:59
#, python-format
msgid ""
"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
@@ -426,17 +433,10 @@ msgid ""
" <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:40
+#: mediagoblin/templates/mediagoblin/root.html:67
msgid "Most recent media"
msgstr "Самые новые файлы"
-#: 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/admin/panel.html:29
msgid ""
"Here you can track the state of media being processed on this instance."
@@ -545,30 +545,43 @@ msgstr "Привет, %(username)s!\n\nЧтобы активировать ÑвÐ
msgid "Editing attachments for %(media_title)s"
msgstr "Добавление ÑопутÑтвующего файла Ð´Ð»Ñ %(media_title)s"
-#: 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/attachments.html:43
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
+msgid "Attachments"
+msgstr "СопутÑтвующие файлы"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr "Добавить ÑопутÑтвующий файл"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:53
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
msgid "Cancel"
msgstr "Отмена"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:43
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
msgid "Save changes"
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:41
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
#, python-format
msgid "Changing %(username)s's account settings"
msgstr "ÐаÑтройка учётной запиÑи %(username)s"
@@ -594,13 +607,12 @@ 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/image.html:23
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
msgid "Download"
msgstr "Скачать"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:27
msgid "Original"
msgstr "Оригинал"
@@ -627,6 +639,56 @@ msgstr "ИÑходный файл"
msgid "WebM file (Vorbis codec)"
msgstr "WebMâ€Ñ„айл (кодек — Vorbis)"
+#: 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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr "Изображение «%(media_title)s»"
+
+#: 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 ""
+
+#: 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:40
msgid ""
"Sorry, this video will not work because \n"
@@ -651,7 +713,7 @@ msgstr "Добавление коллекции"
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
#: mediagoblin/templates/mediagoblin/submit/start.html:34
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:83
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
msgid "Add"
msgstr "Добавить"
@@ -680,14 +742,6 @@ msgstr "Изменить"
msgid "Delete"
msgstr "Удалить"
-#: mediagoblin/templates/mediagoblin/user_pages/collection.html:59
-#, python-format
-msgid ""
-"<p>\n"
-" %(collection_description)s\n"
-" </p>"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
@@ -695,7 +749,7 @@ msgid "Really delete %(title)s?"
msgstr "Удалить %(title)s?"
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "Удалить безвозвратно"
@@ -704,7 +758,7 @@ msgstr "Удалить безвозвратно"
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:54
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
msgid "Remove"
msgstr "ИÑключить"
@@ -730,12 +784,6 @@ 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:67
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
-#, python-format
-msgid "Image for %(media_title)s"
-msgstr "Изображение «%(media_title)s»"
-
#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
msgid "Add a comment"
msgstr "Добавить комментарий"
@@ -762,25 +810,20 @@ msgid ""
" <p>%(date)s</p>"
msgstr "<h3>Добавлено</h3>\n <p>%(date)s</p>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
-msgid "Attachments"
-msgstr "СопутÑтвующие файлы"
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
-msgid "Add attachment"
-msgstr "Добавить ÑопутÑтвующий файл"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
+msgstr "Добавить файл к коллекции"
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
#, python-format
msgid "Add %(title)s to collection"
msgstr "Добавить %(title)s в коллекцию"
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
msgid "+"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
msgid "Add a new collection"
msgstr "Добавление новой коллекции"
@@ -851,42 +894,26 @@ msgstr "Редактировать профиль"
msgid "This user hasn't filled in their profile (yet)."
msgstr "Этот пользователь не заполнил Ñвой профайл (пока)."
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:125
-msgid "Change account settings"
-msgstr "Изменить наÑтройки учётной запиÑи"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:138
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
#, python-format
msgid "View all of %(username)s's media"
msgstr "Смотреть вÑе файлы %(username)s"
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
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:157
-msgid "Add media"
-msgstr "Добавить файлы"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:163
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:87
-#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:72
+#: 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:39
-#, python-format
-msgid ""
-"<br />\n"
-" <a href=\"%(entry_url)s\">%(note)s</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:47
-#, python-format
-msgid "<br /><a href=\"%(remove_url)s\" class=\"remove\">(remove)</a>"
-msgstr ""
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
+msgstr "(иÑключить)"
#: mediagoblin/templates/mediagoblin/utils/collections.html:20
#, python-format
@@ -905,7 +932,7 @@ msgstr "лента в формате Atom"
msgid "Location"
msgstr "Ðа карте"
-#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:38
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
#, python-format
msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
msgstr "ПоÑмотреть на <a href=\"%(osm_url)s\">OpenStreetMap</a>"
@@ -944,6 +971,32 @@ msgstr "Метки"
msgid "Could not read the image file."
msgstr "Ðе удалоÑÑŒ прочитать файл Ñ Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸ÐµÐ¼."
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr "Ой!"
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr "Произошла ошибка"
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr "ÐžÐ¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð½Ðµ позволÑетÑÑ"
+
+#: mediagoblin/tools/response.py:47
+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:55
+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/user_pages/forms.py:28
msgid "I am sure I want to delete this"
msgstr "Я уверен, что хочу удалить Ñто"
@@ -964,74 +1017,74 @@ msgstr "Примечание"
msgid "commented on your post"
msgstr "оÑтавил комментарий к вашему файлу"
-#: mediagoblin/user_pages/views.py:161
+#: mediagoblin/user_pages/views.py:156
msgid "Oops, your comment was empty."
msgstr "Ой, ваш комментарий был пуÑÑ‚."
-#: mediagoblin/user_pages/views.py:167
+#: mediagoblin/user_pages/views.py:162
msgid "Your comment has been posted!"
msgstr "Ваш комментарий размещён!"
-#: mediagoblin/user_pages/views.py:235
+#: mediagoblin/user_pages/views.py:230
msgid "You have to select or add a collection"
msgstr "Ðеобходимо выбрать или добавить коллекцию"
-#: mediagoblin/user_pages/views.py:243
+#: mediagoblin/user_pages/views.py:238
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr "«%s» — уже в коллекции «%s»"
-#: mediagoblin/user_pages/views.py:258
+#: mediagoblin/user_pages/views.py:253
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr "«%s» добавлено в коллекцию «%s»"
-#: mediagoblin/user_pages/views.py:266
+#: mediagoblin/user_pages/views.py:261
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:297
+#: mediagoblin/user_pages/views.py:292
msgid ""
"Some of the files with this entry seem to be missing. Deleting anyway."
msgstr "Ðекоторые файлы от Ñтой запиÑи не обнаружены. Ð’ÑÑ‘ равно удалÑем."
-#: mediagoblin/user_pages/views.py:302
+#: mediagoblin/user_pages/views.py:297
msgid "You deleted the media."
msgstr "Вы удалили файл."
-#: mediagoblin/user_pages/views.py:309
+#: mediagoblin/user_pages/views.py:304
msgid "The media was not deleted because you didn't check that you were sure."
msgstr "Файл не удалён, так как вы не подтвердили Ñвою уверенноÑть галочкой."
-#: mediagoblin/user_pages/views.py:317
+#: mediagoblin/user_pages/views.py:312
msgid "You are about to delete another user's media. Proceed with caution."
msgstr "Ð’Ñ‹ на пороге ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° другого пользователÑ. Будьте оÑторожны."
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr "Ð’Ñ‹ иÑключили файл из коллекции."
-#: mediagoblin/user_pages/views.py:383
+#: 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:393
+#: mediagoblin/user_pages/views.py:384
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr "Ð’Ñ‹ на пороге иÑÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° из коллекции другого пользователÑ. Будьте оÑторожны."
-#: mediagoblin/user_pages/views.py:426
+#: mediagoblin/user_pages/views.py:417
#, python-format
msgid "You deleted the collection \"%s\""
msgstr "Вы удалили коллекцию «%s»"
-#: mediagoblin/user_pages/views.py:433
+#: mediagoblin/user_pages/views.py:424
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr "ÐšÐ¾Ð»Ð»ÐµÐºÑ†Ð¸Ñ Ð½Ðµ удалена, так как вы не подтвердили Ñвоё намерение отметкой."
-#: mediagoblin/user_pages/views.py:443
+#: mediagoblin/user_pages/views.py:434
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 48a3873f..d84b09c4 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 4d59ccd5..b866501e 100644
--- a/mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.po
@@ -4,13 +4,16 @@
#
# Translators:
# 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.
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2012-09-24 14:01-0500\n"
-"PO-Revision-Date: 2012-09-24 18:57+0000\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 15:14+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
@@ -22,109 +25,109 @@ msgstr ""
#: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:41
msgid "Username"
-msgstr "Prihlasovacie meno"
+msgstr "Brugernavn"
#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:45
msgid "Password"
-msgstr "Heslo"
+msgstr "Kodeord"
#: mediagoblin/auth/forms.py:34
msgid "Email address"
-msgstr "E-mailová adresa"
+msgstr "Email adresse"
#: mediagoblin/auth/forms.py:51
msgid "Username or email"
-msgstr "Používateľské meno alebo e-mailová adresa"
+msgstr "Brugernavn eller email"
#: mediagoblin/auth/forms.py:58
msgid "Incorrect input"
-msgstr "Nesprávny vstup"
+msgstr "Forkert input"
#: mediagoblin/auth/views.py:55
msgid "Sorry, registration is disabled on this instance."
-msgstr "PrepáÄ, registrácia na tejto inÅ¡tancii nie je povolená."
+msgstr "Desværre, registrering er ikke muligt på denne instans"
#: mediagoblin/auth/views.py:75
msgid "Sorry, a user with that name already exists."
-msgstr "PrepáÄ, rovnaké prihlasovacie meno už niekto používa."
+msgstr "Desværre, det brugernavn er allerede brugt"
#: mediagoblin/auth/views.py:79
msgid "Sorry, a user with that email address already exists."
-msgstr "PrepáÄ, používateľ s rovnakou e-mailovou adresou už existuje."
+msgstr "Desværre, en bruger er allerede oprettet for den email"
#: 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 úspeÅ¡ne overená. MôžeÅ¡ sa hneÄ prihlásiÅ¥, upraviÅ¥ svoj profil a vkladaÅ¥ výtvory! "
+msgstr "Din email adresse er blevet bekræftet. Du kan nu logge på, ændre din profil, og indsende billeder!"
#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
-msgstr "Nesprávny overovací kÄ¾ÃºÄ alebo používateľský identifikátor"
+msgstr "Bekræftelsesnøglen eller brugerid er forkert"
#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
-msgstr "Aby sme ti mohli zaslať e-mailovú správu, je potrebné byť prihláseným!"
+msgstr "Du er nødt til at være logget ind, så vi ved hvem vi skal emaile!"
#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
-msgstr "Tvoja e-mailová adresa už bola raz overená!"
+msgstr "Du har allerede bekræftet din email adresse!"
#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
-msgstr "Opätovne zaslať overovaciu správu na e-mail."
+msgstr "Email til godkendelse sendt igen."
#: mediagoblin/auth/views.py:263
msgid ""
"An email has been sent with instructions on how to change your password."
-msgstr "E-mailová správa s inštrukciami pre zmenu tvojho hesla bola odoslaná."
+msgstr "En email er blevet sendt med instruktioner til at ændre dit kodeord."
#: mediagoblin/auth/views.py:273
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
-msgstr "Nebolo ti možné zaslaÅ¥ e-mailovú správu ohľadom obnovy hesla, nakoľko je tvoje používateľské meno buÄ neaktívne alebo e-mailová adresa úÄtu neoverená."
+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:285
msgid "Couldn't find someone with that username or email."
-msgstr "Nebolo možné nájsť nikoho s týmto používateľským menom alebo e-mailovou adresou."
+msgstr "Vi kunne ikke dit brugernavn eller email."
#: mediagoblin/auth/views.py:333
msgid "You can now log in using your new password."
-msgstr "Teraz sa môžeš prihlásiť so svojim novým heslom."
+msgstr "Du kan nu logge ind med dit nye kodeord."
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:83
+#: 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:40
msgid "Title"
-msgstr "Nadpis"
+msgstr "Titel"
#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:31
msgid "Description of this work"
-msgstr "Charakteristika tohto diela"
+msgstr "Beskrivelse af arbejdet"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:87 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:44
msgid ""
"You can use\n"
" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n"
" Markdown</a> for formatting."
-msgstr "Môžeš využiť\n <a href=\"http://daringfireball.net/projects/markdown/basics\">\n Markdown</a> pri formátovaní."
+msgstr "Du kan bruge\n <a href=\"http://daringfireball.net/projects/markdown/basics\">\n Markdown</a> til formattering."
#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36
msgid "Tags"
-msgstr "ZnaÄky"
+msgstr "Tags"
#: mediagoblin/edit/forms.py:35 mediagoblin/submit/forms.py:38
msgid "Separate tags by commas."
-msgstr "Oddeľ jednotlivé Å¡títky Äiarkami."
+msgstr "Separer tags med kommaer."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:91
+#: 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:92
+#: 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"
@@ -132,12 +135,12 @@ msgstr "Unikátna ÄasÅ¥ adresy nesmie byÅ¥ prázdna"
msgid ""
"The title part of this media's address. You usually don't need to change "
"this."
-msgstr "Titulná ÄasÅ¥ adresy tohto výtvoru. VäÄÅ¡inou nie je potrebná zmena."
+msgstr "Titeldelen af dette medie's adresse. Du behøver normalt ikke ændre dette."
#: mediagoblin/edit/forms.py:44 mediagoblin/submit/forms.py:41
#: mediagoblin/templates/mediagoblin/utils/license.html:20
msgid "License"
-msgstr "Licencia"
+msgstr "Licens"
#: mediagoblin/edit/forms.py:50
msgid "Bio"
@@ -145,42 +148,42 @@ msgstr "Bio"
#: mediagoblin/edit/forms.py:56
msgid "Website"
-msgstr "Webstránka"
+msgstr "Websted"
#: mediagoblin/edit/forms.py:58
msgid "This address contains errors"
-msgstr "Adresa obsahuje chyby"
+msgstr "Denne adresse indeholder fejl"
#: mediagoblin/edit/forms.py:63
msgid "Old password"
-msgstr "Staré heslo"
+msgstr "Gammelt kodeord"
#: mediagoblin/edit/forms.py:64
msgid "Enter your old password to prove you own this account."
-msgstr "PotvrÄ, že vlastníš tento úÄet zadaním svojho starého hesla."
+msgstr "Skriv dit gamle kodeord for at bevise det er din konto."
#: mediagoblin/edit/forms.py:67
msgid "New password"
-msgstr "Nové heslo"
+msgstr "Ny kodeord"
-#: mediagoblin/edit/forms.py:72
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
-msgstr "ZaslaÅ¥ mi e-mail, keÄ ostatní pridajú komentár k médiu"
+msgstr "Email mig når andre kommenterer på mine medier"
-#: mediagoblin/edit/forms.py:84
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
-msgstr ""
+msgstr "Titlen kan ikke være tom"
-#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:43
msgid "Description of this collection"
-msgstr ""
+msgstr "Beskrivelse af denne samling"
-#: mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
-msgstr ""
+msgstr "Titeldelen af denne samlings's adresse. Du behøver normalt ikke ændre dette."
#: mediagoblin/edit/views.py:65
msgid "An entry with that slug already exists for this user."
@@ -188,41 +191,46 @@ msgstr "Položku s rovnakou unikátnou ÄasÅ¥ou adresy už niekde máš."
#: mediagoblin/edit/views.py:86
msgid "You are editing another user's media. Proceed with caution."
-msgstr "Upravuješ médiá niekoho iného. Dbaj na to."
+msgstr "Du er ved at ændre en anden brugers' medier. Pas på."
-#: mediagoblin/edit/views.py:182
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr "Príloha %s pridaná!"
+
+#: mediagoblin/edit/views.py:181
msgid "You are editing a user's profile. Proceed with caution."
-msgstr "Upravuješ používateľský profil. Dbaj na to."
+msgstr "Du er ved at ændre en bruger's profil. Pas på."
-#: mediagoblin/edit/views.py:198
+#: mediagoblin/edit/views.py:197
msgid "Profile changes saved"
-msgstr "Úpravy profilu uložené"
+msgstr "Profilændringer gemt"
-#: mediagoblin/edit/views.py:227 mediagoblin/edit/views.py:247
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
msgid "Account settings saved"
-msgstr "Nastavenia úÄtu uložené"
+msgstr "Kontoindstillinger gemt"
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:251
msgid "Wrong password"
-msgstr "Nesprávne heslo"
+msgstr "Forkert kodeord"
-#: mediagoblin/edit/views.py:288 mediagoblin/submit/views.py:211
-#: mediagoblin/user_pages/views.py:215
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
#, python-format
msgid "You already have a collection called \"%s\"!"
-msgstr ""
+msgstr "Du har allerede en samling ved navn \"%s\"!"
-#: mediagoblin/edit/views.py:292
+#: mediagoblin/edit/views.py:291
msgid "A collection with that slug already exists for this user."
-msgstr ""
+msgstr "Kolekcia s týmto štítkom sa už u teba vyskytuje."
-#: mediagoblin/edit/views.py:309
+#: mediagoblin/edit/views.py:308
msgid "You are editing another user's collection. Proceed with caution."
-msgstr ""
+msgstr "Du er ved at ændre en anden bruger's samling. Pas på."
#: mediagoblin/gmg_commands/theme.py:58
msgid "Cannot link theme... no theme set\n"
-msgstr "Nemôžem priradiť tému.. žiadny set témy\n"
+msgstr "Kan ikke linke til tema... intet tema sat\n"
#: mediagoblin/gmg_commands/theme.py:71
msgid "No asset directory for this theme\n"
@@ -233,9 +241,9 @@ msgid "However, old link directory symlink found; removed.\n"
msgstr "Hoci, starý symbolický odkaz na prieÄinok nájdený; odstránený.\n"
#: mediagoblin/media_types/__init__.py:60
-#: mediagoblin/media_types/__init__.py:120
+#: mediagoblin/media_types/__init__.py:101
msgid "Sorry, I don't support that file type :("
-msgstr "PrepáÄ, nepodporujem tento súborový typ =("
+msgstr "Desværre, jeg understøtter ikke den filtype :("
#: mediagoblin/media_types/video/processing.py:35
msgid "Video transcoding failed"
@@ -243,41 +251,41 @@ msgstr "Konvertovanie videa zlyhalo"
#: mediagoblin/plugins/oauth/forms.py:26
msgid "Client ID"
-msgstr ""
+msgstr "Klientské ID"
#: mediagoblin/plugins/oauth/forms.py:28
msgid "Next URL"
-msgstr ""
+msgstr "Næste URL"
#: mediagoblin/plugins/oauth/forms.py:30
msgid "Allow"
-msgstr ""
+msgstr "Tillad"
#: mediagoblin/plugins/oauth/forms.py:31
msgid "Deny"
-msgstr ""
+msgstr "Forbyd"
#: mediagoblin/plugins/oauth/forms.py:35
msgid "Name"
-msgstr ""
+msgstr "Navn"
#: mediagoblin/plugins/oauth/forms.py:36
msgid "The name of the OAuth client"
-msgstr ""
+msgstr "Navnet af OAuth klienten"
#: mediagoblin/plugins/oauth/forms.py:37
msgid "Description"
-msgstr ""
+msgstr "Beskrivelse"
#: mediagoblin/plugins/oauth/forms.py:39
msgid ""
"This will be visible to users allowing your\n"
" application to authenticate as them."
-msgstr ""
+msgstr "Toto bude viditeľné pre používateľov,\n ktorí sa identifikujú sami cez tvoju aplikáciu."
#: mediagoblin/plugins/oauth/forms.py:41
msgid "Type"
-msgstr ""
+msgstr "Type"
#: mediagoblin/plugins/oauth/forms.py:46
msgid ""
@@ -287,103 +295,84 @@ 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>Dôverné</strong> - Klient môže\nvytváraÅ¥ požiadavky na inÅ¡tanciu GNU MediaGoblin, ktoré nemôžu byÅ¥\nzachytené používateľským agentom (napr. klient na strane servera).<br />\n<strong>Verejné</strong> - Klient nemôže vytváraÅ¥ dôverné\npožiadavky voÄi GNU MediaGoblin inÅ¡tancii (napr. JavaScript-ový klient\n na klientskej strane)."
#: mediagoblin/plugins/oauth/forms.py:53
msgid "Redirect URI"
-msgstr ""
+msgstr "Presmerovacie URI"
#: mediagoblin/plugins/oauth/forms.py:55
msgid ""
"The redirect URI for the applications, this field\n"
" is <strong>required</strong> for public clients."
-msgstr ""
+msgstr "Presmerovacie URI pre aplikácie, toto pole\nj <strong>požadované</strong> pre verejných klientov."
#: mediagoblin/plugins/oauth/forms.py:67
msgid "This field is required for public clients"
-msgstr ""
+msgstr "Dette felt er nødvendigt for offentlige klienter"
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:60
msgid "The client {0} has been registered!"
-msgstr ""
+msgstr "Klienten {0} er blevet registreret!"
#: mediagoblin/processing/__init__.py:138
msgid "Invalid file given for media type."
-msgstr "Odovzdaný nesprávny súbor pre daný typ média."
+msgstr "Forkert fil for medietypen."
#: mediagoblin/submit/forms.py:26
msgid "File"
-msgstr "Súbor"
+msgstr "Fil"
#: mediagoblin/submit/views.py:57
msgid "You must provide a file."
-msgstr "Musíš poskytnúť súbor."
+msgstr "Du må give mig en fil"
#: mediagoblin/submit/views.py:164
msgid "Woohoo! Submitted!"
-msgstr "Juchú! Úspešne vložené!"
+msgstr "Juhuu! Delt!"
#: mediagoblin/submit/views.py:215
#, python-format
msgid "Collection \"%s\" added!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/404.html:24
-msgid "Image of 404 goblin stressing out"
-msgstr "Obrázok stresujúceho goblina pri chybovom kóde Ä. 404"
-
-#: mediagoblin/templates/mediagoblin/404.html:25
-msgid "Oops!"
-msgstr "Ajaj!"
-
-#: mediagoblin/templates/mediagoblin/404.html:26
-msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr "Na danej adrese sa stránka zrejme nenachádza. PrepáÄ!"
+msgstr "Kolekcia \"%s\" pridaná!"
-#: mediagoblin/templates/mediagoblin/404.html:28
-msgid ""
-"If you're sure the address is correct, maybe the page you're looking for has"
-" been moved or deleted."
-msgstr "Ak vieš s istotou, že adresa je správna, tak najskôr bola hľadaná stánka presunutá alebo zmazaná."
-
-#: mediagoblin/templates/mediagoblin/base.html:50
+#: mediagoblin/templates/mediagoblin/base.html:48
msgid "MediaGoblin logo"
msgstr "MediaGoblin logo"
-#: mediagoblin/templates/mediagoblin/base.html:60
-msgid "Verify your email!"
-msgstr "Over si e-mailovú adresu!"
-
-#: mediagoblin/templates/mediagoblin/base.html:66
-msgid "+ Add media"
-msgstr "+ Pridať výtvor"
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, 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:67
-msgid "+ Add collection"
-msgstr ""
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
+msgstr "odhlásiť sa"
-#: mediagoblin/templates/mediagoblin/base.html:69
-msgid "View your profile"
-msgstr "Zobraziť svoj profil"
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
+msgstr "Pridať výtvor"
-#: mediagoblin/templates/mediagoblin/base.html:70
-msgid "Log out"
-msgstr "Odhlásiť sa"
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
+msgstr "Bekræft din email!"
-#: mediagoblin/templates/mediagoblin/base.html:75
+#: 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ásenie"
+msgstr "Log ind"
-#: mediagoblin/templates/mediagoblin/base.html:89
+#: mediagoblin/templates/mediagoblin/base.html:87
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project."
msgstr "Poháňa nás <a href=\"http://mediagoblin.org\">MediaGoblin</a>, súÄasÅ¥ projektu <a href=\"http://gnu.org/\">GNU</a>."
-#: mediagoblin/templates/mediagoblin/base.html:92
+#: mediagoblin/templates/mediagoblin/base.html:90
#, python-format
msgid ""
"Released under the <a "
@@ -391,31 +380,56 @@ msgid ""
"href=\"%(source_link)s\">Source code</a> available."
msgstr "Vydané pod <a href=\"http://www.fsf.org/licensing/licenses/agpl-3.0.html\">AGPL</a>. <a href=\"%(source_link)s\">Zdrojový kód</a> dostupný."
-#: mediagoblin/templates/mediagoblin/root.html:24
+#: mediagoblin/templates/mediagoblin/error.html:24
+msgid "Image of goblin stressing out"
+msgstr "Obrázok hysterického goblina"
+
+#: mediagoblin/templates/mediagoblin/root.html:25
+msgid "Actions"
+msgstr "Úkony"
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr "Vytvoriť novú zbierku"
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr "ZmeniÅ¥ nastavenia úÄtu"
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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 "Sekcia spracovania výtvorov"
+
+#: mediagoblin/templates/mediagoblin/root.html:51
msgid "Explore"
-msgstr "Preskúmať"
+msgstr "Udforsk"
-#: mediagoblin/templates/mediagoblin/root.html:26
+#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr "Ahoj, vitaj na tejto MediaGoblin stránke!"
+msgstr "Hey, velkommen til denne MediaGoblin side!"
-#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/root.html:55
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:29
+#: mediagoblin/templates/mediagoblin/root.html:56
msgid ""
"To add your own media, place comments, and more, you can log in with your "
"MediaGoblin account."
-msgstr "Pre umiestnenie vlastných médií, pridanie komentárov a viac, sa môžeÅ¡ prihlásiÅ¥ so svojim MediaGoblin úÄtom."
+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:31
+#: mediagoblin/templates/mediagoblin/root.html:58
msgid "Don't have one yet? It's easy!"
-msgstr "Ešte žiaden nemáš? Je to jednoduché!"
+msgstr "Har du ikke en endnu? Det er let!"
-#: mediagoblin/templates/mediagoblin/root.html:32
+#: mediagoblin/templates/mediagoblin/root.html:59
#, python-format
msgid ""
"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
@@ -423,17 +437,10 @@ msgid ""
" <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:40
+#: mediagoblin/templates/mediagoblin/root.html:67
msgid "Most recent media"
msgstr "NajÄerstvejÅ¡ie výtvory"
-#: 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 "Sekcia spracovania výtvorov"
-
#: mediagoblin/templates/mediagoblin/admin/panel.html:29
msgid ""
"Here you can track the state of media being processed on this instance."
@@ -506,11 +513,11 @@ msgstr "Prihlásenie zlyhalo!"
#: mediagoblin/templates/mediagoblin/auth/login.html:44
msgid "Don't have an account yet?"
-msgstr "EÅ¡te nemáš úÄet?"
+msgstr "Har du endnu ikke en konto?"
#: mediagoblin/templates/mediagoblin/auth/login.html:45
msgid "Create one here!"
-msgstr "Vytvor si jeden tu!"
+msgstr "Opret en her!"
#: mediagoblin/templates/mediagoblin/auth/login.html:51
msgid "Forgot your password?"
@@ -519,7 +526,7 @@ msgstr "Zabudnuté heslo?"
#: mediagoblin/templates/mediagoblin/auth/register.html:28
#: mediagoblin/templates/mediagoblin/auth/register.html:36
msgid "Create an account!"
-msgstr "VytvoriÅ¥ úÄet!"
+msgstr "Opret en konto!"
#: mediagoblin/templates/mediagoblin/auth/register.html:40
msgid "Create"
@@ -542,30 +549,43 @@ msgstr "Ahoj %(username)s,\n\npre aktiváciu tvojho GNU MediaGoblin úÄtu, otvo
msgid "Editing attachments for %(media_title)s"
msgstr "Úprava príloh pre %(media_title)s"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:23
-#: mediagoblin/templates/mediagoblin/edit/edit.html:35
-#, python-format
-msgid "Editing %(media_title)s"
-msgstr "Úprava %(media_title)s"
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:43
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
+msgid "Attachments"
+msgstr "Prílohy"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr "Pridať prílohu"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:53
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
msgid "Cancel"
-msgstr "Zrušiť"
+msgstr "Afbryd"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:43
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
msgid "Save changes"
-msgstr "Uložiť zmeny"
+msgstr "Gem ændringer"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:23
+#: mediagoblin/templates/mediagoblin/edit/edit.html:35
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "Úprava %(media_title)s"
#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:41
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
#, python-format
msgid "Changing %(username)s's account settings"
msgstr "Mením nastavenia úÄtu používateľa %(username)s"
@@ -573,13 +593,13 @@ msgstr "Mením nastavenia úÄtu používateľa %(username)s"
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29
#, python-format
msgid "Editing %(collection_title)s"
-msgstr ""
+msgstr "Úprava %(collection_title)s"
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:23
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
#, python-format
msgid "Editing %(username)s's profile"
-msgstr "Úprava profilu, ktorý vlastní %(username)s"
+msgstr "Redigerer %(username)s profil"
#: mediagoblin/templates/mediagoblin/listings/collection.html:30
#: mediagoblin/templates/mediagoblin/listings/collection.html:35
@@ -591,13 +611,12 @@ 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/image.html:23
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
msgid "Download"
msgstr "Stiahnuť"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:27
msgid "Original"
msgstr "Originál"
@@ -624,6 +643,56 @@ msgstr "Originálny súbor"
msgid "WebM file (Vorbis codec)"
msgstr "WebM súbor (Vorbis kodek)"
+#: 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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr "Obrázok pre %(media_title)s"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
+msgid "Toggle Rotate"
+msgstr "Zapnúť rotáciu"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113
+msgid "Perspective"
+msgstr "Perspektíva"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117
+msgid "Front"
+msgstr "ÄŒelo"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121
+msgid "Top"
+msgstr "Vrch"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125
+msgid "Side"
+msgstr "Strana"
+
+#: 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 "Stiahnuť model"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146
+msgid "File Format"
+msgstr "Súborový formát"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148
+msgid "Object Height"
+msgstr "Výška objektu"
+
#: mediagoblin/templates/mediagoblin/media_displays/video.html:40
msgid ""
"Sorry, this video will not work because \n"
@@ -644,11 +713,11 @@ msgstr "WebM súbor (640p; VP8/Vorbis)"
#: mediagoblin/templates/mediagoblin/submit/collection.html:26
msgid "Add a collection"
-msgstr ""
+msgstr "Pridať kolekciu"
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
#: mediagoblin/templates/mediagoblin/submit/start.html:34
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:83
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
msgid "Add"
msgstr "Pridať"
@@ -660,12 +729,12 @@ msgstr "Pridaj svoj výtvor"
#: mediagoblin/templates/mediagoblin/user_pages/collection.html:30
#, python-format
msgid "%(collection_title)s (%(username)s's collection)"
-msgstr ""
+msgstr "%(collection_title)s (kolekcia používateľa %(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 ""
+msgstr "%(collection_title)s od <a href=\"%(user_url)s\">%(username)s</a>"
#: mediagoblin/templates/mediagoblin/user_pages/collection.html:52
#: mediagoblin/templates/mediagoblin/user_pages/media.html:87
@@ -677,14 +746,6 @@ msgstr "Upraviť"
msgid "Delete"
msgstr "Odstrániť"
-#: mediagoblin/templates/mediagoblin/user_pages/collection.html:59
-#, python-format
-msgid ""
-"<p>\n"
-" %(collection_description)s\n"
-" </p>"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
@@ -692,18 +753,18 @@ msgid "Really delete %(title)s?"
msgstr "SkutoÄne odstrániÅ¥ %(title)s?"
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "Odstráň permanentne"
#: 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 "UrÄite odstrániÅ¥ %(media_title)s z %(collection_title)s?"
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
msgid "Remove"
-msgstr ""
+msgstr "Odstrániť"
#: mediagoblin/templates/mediagoblin/user_pages/comment_email.txt:19
#, python-format
@@ -727,12 +788,6 @@ 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 "■Prezeranie výtvorov podľa <a href=\"%(user_url)s\">%(username)s</a>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:67
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
-#, python-format
-msgid "Image for %(media_title)s"
-msgstr "Obrázok pre %(media_title)s"
-
#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
msgid "Add a comment"
msgstr "Pridaj komentár"
@@ -759,27 +814,22 @@ msgid ""
" <p>%(date)s</p>"
msgstr "<h3>Pridané</h3>\n <p>%(date)s</p>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
-msgid "Attachments"
-msgstr "Prílohy"
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
-msgid "Add attachment"
-msgstr "Pridať prílohu"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
+msgstr "Pridať výtvory do zbierky"
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
#, python-format
msgid "Add %(title)s to collection"
-msgstr ""
+msgstr "Pridať %(title)s do kolekcie"
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
msgid "+"
-msgstr ""
+msgstr "+"
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
msgid "Add a new collection"
-msgstr ""
+msgstr "Pridať novú kolekciu"
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:29
msgid ""
@@ -798,7 +848,7 @@ msgstr "Profil, ktorý vlastní %(username)s"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:43
msgid "Sorry, no such user found."
-msgstr "PrepáÄ, zadané používateľské meno nenájdené."
+msgstr "Desværre, fandt ikke den bruger."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:50
#: mediagoblin/templates/mediagoblin/user_pages/user.html:70
@@ -807,20 +857,20 @@ msgstr "Potrebné overenie e-mailovej adresy"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:53
msgid "Almost done! Your account still needs to be activated."
-msgstr "Takmer hotovo! EÅ¡te ti musí byÅ¥ aktivovaný úÄet."
+msgstr "Næsten færdig! Din konto skal stadig aktiveres."
#: 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 "E-mailová správa s popisom ako to spraviť, by mal zanedlho doraziť."
+msgstr "Der skulle komme email om et par øjeblikke med instrukser om hvordan."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:62
msgid "In case it doesn't:"
-msgstr "V prípade, že sa tak nestalo:"
+msgstr "Hvis det ikke gør:"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:65
msgid "Resend verification email"
-msgstr "Opätovne zaslať overovaciu správu na e-mail"
+msgstr "Gensend verificeringsemail"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:73
msgid ""
@@ -837,58 +887,42 @@ msgstr "Pokiaľ si to ty, ale už nemáš overovaciu e-mailovú správu, tak sa
#: mediagoblin/templates/mediagoblin/user_pages/user.html:96
msgid "Here's a spot to tell others about yourself."
-msgstr "Miesto, kde smieÅ¡ povedaÅ¥ Äo to o sebe ostatným."
+msgstr "Her kan du fortælle andre om dig selv."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:101
#: mediagoblin/templates/mediagoblin/user_pages/user.html:118
msgid "Edit profile"
-msgstr "Upraviť profil"
+msgstr "Ret profil"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:106
msgid "This user hasn't filled in their profile (yet)."
msgstr "DotyÄný používateľ eÅ¡te nevyplnil svoj profil (zatiaľ)."
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:125
-msgid "Change account settings"
-msgstr "ZmeniÅ¥ nastavenia úÄtu"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:138
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
#, python-format
msgid "View all of %(username)s's media"
msgstr "Zhliadnuť všetky výtvory, ktoré vlastní %(username)s"
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
msgid ""
"This is where your media will appear, but you don't seem to have added "
"anything yet."
msgstr "VÅ¡etky tvoje výtvory sa objavia práve tu, ale zatiaľ nemáš niÄ pridané."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:157
-msgid "Add media"
-msgstr "Pridať výtvor"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:163
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:87
-#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:72
+#: 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 "Najskôr sa tu ešte nenachádzajú žiadne výtvory..."
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:39
-#, python-format
-msgid ""
-"<br />\n"
-" <a href=\"%(entry_url)s\">%(note)s</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:47
-#, python-format
-msgid "<br /><a href=\"%(remove_url)s\" class=\"remove\">(remove)</a>"
-msgstr ""
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
+msgstr "(odstrániť)"
#: mediagoblin/templates/mediagoblin/utils/collections.html:20
#, python-format
msgid "In collections (%(collected)s)"
-msgstr ""
+msgstr "V kolekciách (%(collected)s)"
#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
msgid "feed icon"
@@ -902,7 +936,7 @@ msgstr "ČítaÄka Atom"
msgid "Location"
msgstr "Poloha"
-#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:38
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
#, python-format
msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
msgstr "Zobraziť na <a href=\"%(osm_url)s\">OpenStreetMap</a>"
@@ -941,94 +975,120 @@ msgstr "OznaÄené ako"
msgid "Could not read the image file."
msgstr "Nebolo možné preÄítaÅ¥ obrazový súbor."
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr "Hovsa!"
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr "Výskyt chyby"
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr "Nepovolená operácia"
+
+#: mediagoblin/tools/response.py:47
+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 "PrepÃ¡Ä Hocikto, toto nesmieÅ¡!</p><p>Práve si chcel vykonaÅ¥ funkciu, na ktorú nemáš oprávnenie. Opäť si chcel skúsiÅ¥ odstrániÅ¥ vÅ¡etky používateľské úÄty?"
+
+#: mediagoblin/tools/response.py:55
+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 "Zdá sa, že na tejto adrese sa niÄ nenachádza. PrepáÄ!</p><p>Pokiaľ si si istý, že adresa je správna, možno sa hľadaná stránka presunula inam, prípadne zmazala."
+
#: mediagoblin/user_pages/forms.py:28
msgid "I am sure I want to delete this"
msgstr "JednoznaÄne to chcem odstrániÅ¥"
#: mediagoblin/user_pages/forms.py:32
msgid "I am sure I want to remove this item from the collection"
-msgstr ""
+msgstr "Rozhodne chcem odstrániť danú položku z kolekcie"
#: mediagoblin/user_pages/forms.py:35
msgid "-- Select --"
-msgstr ""
+msgstr "-- Vybrať --"
#: mediagoblin/user_pages/forms.py:37
msgid "Include a note"
-msgstr ""
+msgstr "Pridať poznámku"
#: mediagoblin/user_pages/lib.py:56
msgid "commented on your post"
msgstr "skomentoval tvoj príspevok"
-#: mediagoblin/user_pages/views.py:161
+#: mediagoblin/user_pages/views.py:156
msgid "Oops, your comment was empty."
msgstr "Ajaj, tvoj komentár bol prázdny."
-#: mediagoblin/user_pages/views.py:167
+#: mediagoblin/user_pages/views.py:162
msgid "Your comment has been posted!"
msgstr "Tvoj komentár bol zaslaný!"
-#: mediagoblin/user_pages/views.py:235
+#: mediagoblin/user_pages/views.py:230
msgid "You have to select or add a collection"
-msgstr ""
+msgstr "Musíš vybrať alebo pridať kolekciu"
-#: mediagoblin/user_pages/views.py:243
+#: mediagoblin/user_pages/views.py:238
#, python-format
msgid "\"%s\" already in collection \"%s\""
-msgstr ""
+msgstr "\"%s\" sa už nachádza v kolekcie \"%s\""
-#: mediagoblin/user_pages/views.py:258
+#: mediagoblin/user_pages/views.py:253
#, python-format
msgid "\"%s\" added to collection \"%s\""
-msgstr ""
+msgstr "\"%s pridané do kolekcie \"%s\""
-#: mediagoblin/user_pages/views.py:266
+#: mediagoblin/user_pages/views.py:261
msgid "Please check your entries and try again."
-msgstr ""
+msgstr "Prosím skontroluj svoje položky a skús znova."
-#: mediagoblin/user_pages/views.py:297
+#: mediagoblin/user_pages/views.py:292
msgid ""
"Some of the files with this entry seem to be missing. Deleting anyway."
msgstr "Niektoré súbory s danou položkou zrejme chýbajú.. Odstraňujem napriek tomu."
-#: mediagoblin/user_pages/views.py:302
+#: mediagoblin/user_pages/views.py:297
msgid "You deleted the media."
msgstr "Výtvor bol tebou odstránený."
-#: mediagoblin/user_pages/views.py:309
+#: mediagoblin/user_pages/views.py:304
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:317
+#: mediagoblin/user_pages/views.py:312
msgid "You are about to delete another user's media. Proceed with caution."
msgstr "Chystáš sa odstrániť výtvory niekoho iného. Dbaj na to."
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
-msgstr ""
+msgstr "Položka bola z kolekcie odstránená."
-#: mediagoblin/user_pages/views.py:383
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
-msgstr ""
+msgstr "Položka nebola odstránená, nakoľko políÄko potvrdenia nebolo oznaÄné."
-#: mediagoblin/user_pages/views.py:393
+#: mediagoblin/user_pages/views.py:384
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
-msgstr ""
+msgstr "Chystáš sa odstrániť položku z kolekcie iného používateľa. Pristupuj opatrne."
-#: mediagoblin/user_pages/views.py:426
+#: mediagoblin/user_pages/views.py:417
#, python-format
msgid "You deleted the collection \"%s\""
-msgstr ""
+msgstr "Kolekcia \"%s\" úspešne odstránená."
-#: mediagoblin/user_pages/views.py:433
+#: mediagoblin/user_pages/views.py:424
msgid ""
"The collection was not deleted because you didn't check that you were sure."
-msgstr ""
+msgstr "Kolekcia nebola odstránená, nakoľko políÄko potrvdenia nebolo oznaÄené."
-#: mediagoblin/user_pages/views.py:443
+#: mediagoblin/user_pages/views.py:434
msgid ""
"You are about to delete another user's collection. Proceed with caution."
-msgstr ""
+msgstr "Chystáš sa odstrániť kolekciu iného používateľa. Pristupuj opatrne."
diff --git a/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.mo
index 38a19ef6..1599b039 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 d05f1ebc..aa482e0c 100644
--- a/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.po
@@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2012-09-24 14:01-0500\n"
-"PO-Revision-Date: 2012-09-24 18:57+0000\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 15:14+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
@@ -92,7 +92,7 @@ msgstr ""
msgid "You can now log in using your new password."
msgstr ""
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:83
+#: 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:40
msgid "Title"
@@ -103,7 +103,7 @@ msgid "Description of this work"
msgstr ""
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:87 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:44
msgid ""
"You can use\n"
@@ -119,11 +119,11 @@ msgstr "Oznake"
msgid "Separate tags by commas."
msgstr ""
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:91
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "Oznaka"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:92
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr "Oznaka ne sme biti prazna"
@@ -162,20 +162,20 @@ msgstr ""
msgid "New password"
msgstr ""
-#: mediagoblin/edit/forms.py:72
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr ""
-#: mediagoblin/edit/forms.py:84
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:43
msgid "Description of this collection"
msgstr ""
-#: mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
@@ -189,33 +189,38 @@ msgstr "Vnos s to oznako za tega uporabnika že obstaja."
msgid "You are editing another user's media. Proceed with caution."
msgstr "Urejate vsebino drugega uporabnika. Nadaljujte pazljivo."
-#: mediagoblin/edit/views.py:182
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr ""
+
+#: mediagoblin/edit/views.py:181
msgid "You are editing a user's profile. Proceed with caution."
msgstr "Urejate uporabniški profil. Nadaljujte pazljivo."
-#: mediagoblin/edit/views.py:198
+#: mediagoblin/edit/views.py:197
msgid "Profile changes saved"
msgstr ""
-#: mediagoblin/edit/views.py:227 mediagoblin/edit/views.py:247
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
msgid "Account settings saved"
msgstr ""
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:251
msgid "Wrong password"
msgstr ""
-#: mediagoblin/edit/views.py:288 mediagoblin/submit/views.py:211
-#: mediagoblin/user_pages/views.py:215
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr ""
-#: mediagoblin/edit/views.py:292
+#: mediagoblin/edit/views.py:291
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:309
+#: mediagoblin/edit/views.py:308
msgid "You are editing another user's collection. Proceed with caution."
msgstr ""
@@ -232,7 +237,7 @@ msgid "However, old link directory symlink found; removed.\n"
msgstr ""
#: mediagoblin/media_types/__init__.py:60
-#: mediagoblin/media_types/__init__.py:120
+#: mediagoblin/media_types/__init__.py:101
msgid "Sorry, I don't support that file type :("
msgstr ""
@@ -302,7 +307,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:60
msgid "The client {0} has been registered!"
msgstr ""
@@ -327,62 +332,43 @@ msgstr "Juhej! Poslano."
msgid "Collection \"%s\" added!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/404.html:24
-msgid "Image of 404 goblin stressing out"
-msgstr "Slika napake 404 s paniÄnim Å¡kratom"
-
-#: mediagoblin/templates/mediagoblin/404.html:25
-msgid "Oops!"
-msgstr "Opa!"
-
-#: mediagoblin/templates/mediagoblin/404.html:26
-msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr "Oprostite. Videti je, da na tem naslovu ni nobene strani."
-
-#: mediagoblin/templates/mediagoblin/404.html:28
-msgid ""
-"If you're sure the address is correct, maybe the page you're looking for has"
-" been moved or deleted."
-msgstr "ÄŒe ste v toÄnost naslova prepriÄani, je bila iskana stran morda premaknjena ali pa izbrisana."
-
-#: mediagoblin/templates/mediagoblin/base.html:50
+#: mediagoblin/templates/mediagoblin/base.html:48
msgid "MediaGoblin logo"
msgstr "Logotip MediaGoblin"
-#: mediagoblin/templates/mediagoblin/base.html:60
-msgid "Verify your email!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:66
-msgid "+ Add media"
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:67
-msgid "+ Add collection"
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:69
-msgid "View your profile"
-msgstr ""
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
+msgstr "Dodaj vsebino"
-#: mediagoblin/templates/mediagoblin/base.html:70
-msgid "Log out"
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:75
+#: 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:89
+#: mediagoblin/templates/mediagoblin/base.html:87
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project."
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:92
+#: mediagoblin/templates/mediagoblin/base.html:90
#, python-format
msgid ""
"Released under the <a "
@@ -390,31 +376,56 @@ msgid ""
"href=\"%(source_link)s\">Source code</a> available."
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:24
+#: mediagoblin/templates/mediagoblin/error.html:24
+msgid "Image of goblin stressing out"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:25
+msgid "Actions"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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 "Podokno obdelovanja vsebine"
+
+#: mediagoblin/templates/mediagoblin/root.html:51
msgid "Explore"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:26
+#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Hi there, welcome to this MediaGoblin site!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/root.html:55
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:29
+#: mediagoblin/templates/mediagoblin/root.html:56
msgid ""
"To add your own media, place comments, and more, you can log in with your "
"MediaGoblin account."
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:31
+#: mediagoblin/templates/mediagoblin/root.html:58
msgid "Don't have one yet? It's easy!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:32
+#: mediagoblin/templates/mediagoblin/root.html:59
#, python-format
msgid ""
"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
@@ -422,17 +433,10 @@ msgid ""
" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:40
+#: mediagoblin/templates/mediagoblin/root.html:67
msgid "Most recent media"
msgstr ""
-#: 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 "Podokno obdelovanja vsebine"
-
#: mediagoblin/templates/mediagoblin/admin/panel.html:29
msgid ""
"Here you can track the state of media being processed on this instance."
@@ -541,30 +545,43 @@ msgstr "Pozdravljeni, %(username)s\n\nZa aktivacijo svojega raÄuna GNU MediaGob
msgid "Editing attachments for %(media_title)s"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit.html:23
-#: mediagoblin/templates/mediagoblin/edit/edit.html:35
-#, python-format
-msgid "Editing %(media_title)s"
-msgstr "Urejanje %(media_title)s"
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:43
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
+msgid "Attachments"
+msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:53
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
msgid "Cancel"
msgstr "PrekliÄi"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:43
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
msgid "Save changes"
msgstr "Shrani spremembe"
+#: mediagoblin/templates/mediagoblin/edit/edit.html:23
+#: mediagoblin/templates/mediagoblin/edit/edit.html:35
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "Urejanje %(media_title)s"
+
#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:41
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
#, python-format
msgid "Changing %(username)s's account settings"
msgstr ""
@@ -590,13 +607,12 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:23
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
msgid "Download"
msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:27
msgid "Original"
msgstr ""
@@ -623,6 +639,56 @@ msgstr ""
msgid "WebM file (Vorbis codec)"
msgstr ""
+#: 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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr ""
+
+#: 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 ""
+
+#: 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:40
msgid ""
"Sorry, this video will not work because \n"
@@ -647,7 +713,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
#: mediagoblin/templates/mediagoblin/submit/start.html:34
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:83
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
msgid "Add"
msgstr ""
@@ -676,14 +742,6 @@ msgstr ""
msgid "Delete"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection.html:59
-#, python-format
-msgid ""
-"<p>\n"
-" %(collection_description)s\n"
-" </p>"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
@@ -691,7 +749,7 @@ msgid "Really delete %(title)s?"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr ""
@@ -700,7 +758,7 @@ msgstr ""
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
msgid "Remove"
msgstr ""
@@ -726,12 +784,6 @@ 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:67
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
-#, python-format
-msgid "Image for %(media_title)s"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
msgid "Add a comment"
msgstr ""
@@ -758,13 +810,8 @@ msgid ""
" <p>%(date)s</p>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
-msgid "Attachments"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
-msgid "Add attachment"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
@@ -772,11 +819,11 @@ msgstr ""
msgid "Add %(title)s to collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
msgid "+"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
msgid "Add a new collection"
msgstr ""
@@ -847,41 +894,25 @@ msgstr "Uredi profil"
msgid "This user hasn't filled in their profile (yet)."
msgstr "Ta uporabnik še ni izpolnil svojega profila."
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:125
-msgid "Change account settings"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:138
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
#, python-format
msgid "View all of %(username)s's media"
msgstr "Prikaži vso vsebino uporabnika %(username)s"
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
msgid ""
"This is where your media will appear, but you don't seem to have added "
"anything yet."
msgstr "Tu bo prikazana vaÅ¡a vsebina, a trenutno Å¡e niste dodali niÄ."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:157
-msgid "Add media"
-msgstr "Dodaj vsebino"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:163
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:87
-#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:72
+#: 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 "Videti je, da tu še ni nobene vsebine ..."
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:39
-#, python-format
-msgid ""
-"<br />\n"
-" <a href=\"%(entry_url)s\">%(note)s</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:47
-#, python-format
-msgid "<br /><a href=\"%(remove_url)s\" class=\"remove\">(remove)</a>"
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
msgstr ""
#: mediagoblin/templates/mediagoblin/utils/collections.html:20
@@ -901,7 +932,7 @@ msgstr "Ikona Atom"
msgid "Location"
msgstr ""
-#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:38
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
#, python-format
msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
msgstr ""
@@ -940,6 +971,32 @@ msgstr ""
msgid "Could not read the image file."
msgstr ""
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr "Opa!"
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr ""
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr ""
+
+#: mediagoblin/tools/response.py:47
+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:55
+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/user_pages/forms.py:28
msgid "I am sure I want to delete this"
msgstr ""
@@ -960,74 +1017,74 @@ msgstr ""
msgid "commented on your post"
msgstr ""
-#: mediagoblin/user_pages/views.py:161
+#: mediagoblin/user_pages/views.py:156
msgid "Oops, your comment was empty."
msgstr ""
-#: mediagoblin/user_pages/views.py:167
+#: mediagoblin/user_pages/views.py:162
msgid "Your comment has been posted!"
msgstr ""
-#: mediagoblin/user_pages/views.py:235
+#: mediagoblin/user_pages/views.py:230
msgid "You have to select or add a collection"
msgstr ""
-#: mediagoblin/user_pages/views.py:243
+#: mediagoblin/user_pages/views.py:238
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:258
+#: mediagoblin/user_pages/views.py:253
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:266
+#: mediagoblin/user_pages/views.py:261
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:297
+#: mediagoblin/user_pages/views.py:292
msgid ""
"Some of the files with this entry seem to be missing. Deleting anyway."
msgstr ""
-#: mediagoblin/user_pages/views.py:302
+#: mediagoblin/user_pages/views.py:297
msgid "You deleted the media."
msgstr ""
-#: mediagoblin/user_pages/views.py:309
+#: mediagoblin/user_pages/views.py:304
msgid "The media was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:317
+#: mediagoblin/user_pages/views.py:312
msgid "You are about to delete another user's media. Proceed with caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr ""
-#: mediagoblin/user_pages/views.py:383
+#: 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:393
+#: mediagoblin/user_pages/views.py:384
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:426
+#: mediagoblin/user_pages/views.py:417
#, python-format
msgid "You deleted the collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:433
+#: mediagoblin/user_pages/views.py:424
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:443
+#: mediagoblin/user_pages/views.py:434
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 be3b75db..64880aed 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 5147dcc3..2911f34e 100644
--- a/mediagoblin/i18n/sq/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/sq/LC_MESSAGES/mediagoblin.po
@@ -3,13 +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.
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2012-09-24 14:01-0500\n"
-"PO-Revision-Date: 2012-09-24 18:57+0000\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 15:14+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"
@@ -92,7 +93,7 @@ msgstr "Nuk u gjet dot dikush me atë emër përdoruesi ose email."
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:83
+#: 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:40
msgid "Title"
@@ -103,7 +104,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:87 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:44
msgid ""
"You can use\n"
@@ -119,11 +120,11 @@ msgstr "Etiketa"
msgid "Separate tags by commas."
msgstr "Ndajini etiketat me presje."
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:91
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr "Identifikues"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:92
+#: 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"
@@ -162,24 +163,24 @@ msgstr "Jepni fjalëkalimin tuaj të vjetër që të provohet se këtë llogari
msgid "New password"
msgstr "Fjalëkalimi i ri"
-#: mediagoblin/edit/forms.py:72
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
-msgstr ""
+msgstr "Dërgomë email kur të tjerët komentojnë te media ime"
-#: mediagoblin/edit/forms.py:84
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
-msgstr ""
+msgstr "Titulli s'mund të jetë i zbrazët"
-#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:43
msgid "Description of this collection"
-msgstr ""
+msgstr "Përshkrim i këtij koleksioni"
-#: mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
-msgstr ""
+msgstr "Pjesa titull e adresës së këtij koleksioni. Zakonisht nuk keni pse e ndryshoni këtë."
#: mediagoblin/edit/views.py:65
msgid "An entry with that slug already exists for this user."
@@ -187,96 +188,101 @@ msgstr "Ka tashmë një zë me atë identifikues për këtë përdorues."
#: mediagoblin/edit/views.py:86
msgid "You are editing another user's media. Proceed with caution."
-msgstr "Po përpunoni media të një tjetër përdoruesi. Bëni kujdes."
+msgstr "Po përpunoni media të një tjetër përdoruesi. Hapni sytë."
+
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr "Shtuat bashkangjitjen %s!"
-#: mediagoblin/edit/views.py:182
+#: mediagoblin/edit/views.py:181
msgid "You are editing a user's profile. Proceed with caution."
-msgstr "Po përpunoni profilin e një përdoruesi. Bëni kujdes."
+msgstr "Po përpunoni profilin e një përdoruesi. Hapni sytë."
-#: mediagoblin/edit/views.py:198
+#: mediagoblin/edit/views.py:197
msgid "Profile changes saved"
msgstr "Ndryshimet e profilit u ruajtën"
-#: mediagoblin/edit/views.py:227 mediagoblin/edit/views.py:247
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
msgid "Account settings saved"
msgstr "Rregullimet e llogarisë u ruajtën"
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:251
msgid "Wrong password"
msgstr "Fjalëkalim i gabuar"
-#: mediagoblin/edit/views.py:288 mediagoblin/submit/views.py:211
-#: mediagoblin/user_pages/views.py:215
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
#, python-format
msgid "You already have a collection called \"%s\"!"
-msgstr ""
+msgstr "Keni tashmë një koleksion të quajtur \"%s\"!"
-#: mediagoblin/edit/views.py:292
+#: mediagoblin/edit/views.py:291
msgid "A collection with that slug already exists for this user."
-msgstr ""
+msgstr "Ka tashmë një koleksion me atë identifikues për këtë përdorues."
-#: mediagoblin/edit/views.py:309
+#: mediagoblin/edit/views.py:308
msgid "You are editing another user's collection. Proceed with caution."
-msgstr ""
+msgstr "Po përpunoni koleksionin e një tjetër përdoruesi. Hapni sytë."
#: mediagoblin/gmg_commands/theme.py:58
msgid "Cannot link theme... no theme set\n"
-msgstr ""
+msgstr "Nuk krijohet dot lidhje për te tema... nuk ka temë të caktuar\n"
#: mediagoblin/gmg_commands/theme.py:71
msgid "No asset directory for this theme\n"
-msgstr ""
+msgstr "Nuk ka drejtori asetesh për këtë temë\n"
#: mediagoblin/gmg_commands/theme.py:74
msgid "However, old link directory symlink found; removed.\n"
-msgstr ""
+msgstr "Sidoqoftë, u gjet simlidhje e vjetër drejtorie lidhjesh; u hoq.\n"
#: mediagoblin/media_types/__init__.py:60
-#: mediagoblin/media_types/__init__.py:120
+#: mediagoblin/media_types/__init__.py:101
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:35
msgid "Video transcoding failed"
-msgstr ""
+msgstr "Ndërkodimi i videos dështoi"
#: mediagoblin/plugins/oauth/forms.py:26
msgid "Client ID"
-msgstr ""
+msgstr "ID klienti"
#: mediagoblin/plugins/oauth/forms.py:28
msgid "Next URL"
-msgstr ""
+msgstr "URL-ja Pasuese"
#: mediagoblin/plugins/oauth/forms.py:30
msgid "Allow"
-msgstr ""
+msgstr "Lejoje"
#: mediagoblin/plugins/oauth/forms.py:31
msgid "Deny"
-msgstr ""
+msgstr "Mohoje"
#: mediagoblin/plugins/oauth/forms.py:35
msgid "Name"
-msgstr ""
+msgstr "Emër"
#: mediagoblin/plugins/oauth/forms.py:36
msgid "The name of the OAuth client"
-msgstr ""
+msgstr "Emri i klientit OAuth"
#: mediagoblin/plugins/oauth/forms.py:37
msgid "Description"
-msgstr ""
+msgstr "Përshkrim"
#: mediagoblin/plugins/oauth/forms.py:39
msgid ""
"This will be visible to users allowing your\n"
" application to authenticate as them."
-msgstr ""
+msgstr "Kjo do të jetë e dukshme për përdoruesit,\n duke i lejuar kështu zbatimit tuaj\n të kryejë mirëfilltësim si të qe njëri prej tyre."
#: mediagoblin/plugins/oauth/forms.py:41
msgid "Type"
-msgstr ""
+msgstr "Lloj"
#: mediagoblin/plugins/oauth/forms.py:46
msgid ""
@@ -286,25 +292,25 @@ 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>Konfidenciale</strong> - Kklienti mund\n të bëjë kërkesa te instanca GNU MediaGoblin që nuk mund\n të përgjohen nga agjenti i përdoruesit (p.sh. klient te shërbyesi).<br />\n <strong>Publike</strong> - Klienti nuk mund të bëjë kërkesa\n konfidenciale te instanca GNU MediaGoblin (p.sh. klient\n JavaScript i vetë klientit)."
#: mediagoblin/plugins/oauth/forms.py:53
msgid "Redirect URI"
-msgstr ""
+msgstr "URI Ridrejtimi"
#: mediagoblin/plugins/oauth/forms.py:55
msgid ""
"The redirect URI for the applications, this field\n"
" is <strong>required</strong> for public clients."
-msgstr ""
+msgstr "URI ridrejtimi për zbatimin, kjo fushë\n është <strong>e domosdoshme</strong> për klientë publikë."
#: mediagoblin/plugins/oauth/forms.py:67
msgid "This field is required for public clients"
-msgstr ""
+msgstr "Kjo fushë është e domosdoshme për klientë publikë"
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:60
msgid "The client {0} has been registered!"
-msgstr ""
+msgstr "Klienti {0} u regjistrua!"
#: mediagoblin/processing/__init__.py:138
msgid "Invalid file given for media type."
@@ -325,64 +331,45 @@ msgstr "Yhaaaaaa! U parashtrua!"
#: mediagoblin/submit/views.py:215
#, python-format
msgid "Collection \"%s\" added!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/404.html:24
-msgid "Image of 404 goblin stressing out"
-msgstr "Figurë 404 e djallushit në siklet"
-
-#: mediagoblin/templates/mediagoblin/404.html:25
-msgid "Oops!"
-msgstr "Oooh!"
-
-#: mediagoblin/templates/mediagoblin/404.html:26
-msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr "Nuk duket të ketë ndonjë faqe te kjo adresë. Na ndjeni!"
+msgstr "U shtua koleksioni \"%s\"!"
-#: mediagoblin/templates/mediagoblin/404.html:28
-msgid ""
-"If you're sure the address is correct, maybe the page you're looking for has"
-" been moved or deleted."
-msgstr "Nëse jeni i sigurt se adresa është e saktë, ndoshta faqja që po kërkoni është fshirë ose kaluar gjetkë."
-
-#: mediagoblin/templates/mediagoblin/base.html:50
+#: mediagoblin/templates/mediagoblin/base.html:48
msgid "MediaGoblin logo"
msgstr "Logoja e MediaGoblin-it"
-#: mediagoblin/templates/mediagoblin/base.html:60
-msgid "Verify your email!"
-msgstr "Verifikoni email-in tuaj!"
-
-#: mediagoblin/templates/mediagoblin/base.html:66
-msgid "+ Add media"
-msgstr "+ Shtoni media"
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, 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:67
-msgid "+ Add collection"
-msgstr ""
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
+msgstr "dilni"
-#: mediagoblin/templates/mediagoblin/base.html:69
-msgid "View your profile"
-msgstr "Shihni profilin tuaj"
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
+msgstr "Shtoni media"
-#: mediagoblin/templates/mediagoblin/base.html:70
-msgid "Log out"
-msgstr "Dilni"
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
+msgstr "Verifikoni email-in tuaj!"
-#: mediagoblin/templates/mediagoblin/base.html:75
+#: 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:89
+#: mediagoblin/templates/mediagoblin/base.html:87
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project."
msgstr "Bazuar në <a href=\"http://mediagoblin.org\">MediaGoblin</a>, një projekt <a href=\"http://gnu.org/\">GNU</a>."
-#: mediagoblin/templates/mediagoblin/base.html:92
+#: mediagoblin/templates/mediagoblin/base.html:90
#, python-format
msgid ""
"Released under the <a "
@@ -390,31 +377,56 @@ msgid ""
"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/root.html:24
+#: mediagoblin/templates/mediagoblin/error.html:24
+msgid "Image of goblin stressing out"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:25
+msgid "Actions"
+msgstr "Veprime"
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr "Krijoni koleksion të ri"
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr "Ndryshoni rregullime llogarie"
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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"
+
+#: mediagoblin/templates/mediagoblin/root.html:51
msgid "Explore"
msgstr "Eksploroni"
-#: mediagoblin/templates/mediagoblin/root.html:26
+#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Hi there, welcome to this MediaGoblin site!"
msgstr "Tungjatjeta juaj, mirë se vini te ky site MediaGoblin!"
-#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/root.html:55
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:29
+#: mediagoblin/templates/mediagoblin/root.html:56
msgid ""
"To add your own media, place comments, and more, you can log in with your "
"MediaGoblin account."
-msgstr ""
+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:31
+#: mediagoblin/templates/mediagoblin/root.html:58
msgid "Don't have one yet? It's easy!"
msgstr "Nuk keni ende një të tillë? Është e lehtë!"
-#: mediagoblin/templates/mediagoblin/root.html:32
+#: mediagoblin/templates/mediagoblin/root.html:59
#, python-format
msgid ""
"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
@@ -422,21 +434,14 @@ msgid ""
" <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>"
-#: mediagoblin/templates/mediagoblin/root.html:40
+#: mediagoblin/templates/mediagoblin/root.html:67
msgid "Most recent media"
msgstr "Mediat më të reja"
-#: 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"
-
#: mediagoblin/templates/mediagoblin/admin/panel.html:29
msgid ""
"Here you can track the state of media being processed on this instance."
-msgstr ""
+msgstr "Këtu mund të ndiqni gjendjen e medias që po përpunohet në këtë instancë."
#: mediagoblin/templates/mediagoblin/admin/panel.html:32
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:32
@@ -456,16 +461,16 @@ msgstr "Nuk arritën të kryheshin këto ngarkime:"
#: mediagoblin/templates/mediagoblin/admin/panel.html:90
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:86
msgid "No failed entries!"
-msgstr ""
+msgstr "Pa zëra të dështuar!"
#: mediagoblin/templates/mediagoblin/admin/panel.html:92
msgid "Last 10 successful uploads"
-msgstr ""
+msgstr "10 Ngarkimet e Fundit të Suksesshme"
#: mediagoblin/templates/mediagoblin/admin/panel.html:112
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:107
msgid "No processed entries, yet!"
-msgstr ""
+msgstr "Ende pa zëra të përpunuar!"
#: mediagoblin/templates/mediagoblin/auth/change_fp.html:28
#: mediagoblin/templates/mediagoblin/auth/change_fp.html:36
@@ -539,32 +544,45 @@ msgstr "Njatjeta %(username)s,\n\nqë të aktivizoni llogarinë tuaj te GNU Medi
#: mediagoblin/templates/mediagoblin/edit/attachments.html:35
#, python-format
msgid "Editing attachments for %(media_title)s"
-msgstr ""
+msgstr "Po përpunohen bashkangjitjet për %(media_title)s"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:23
-#: mediagoblin/templates/mediagoblin/edit/edit.html:35
-#, python-format
-msgid "Editing %(media_title)s"
-msgstr "Po përpunohet %(media_title)s"
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:43
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
+msgid "Attachments"
+msgstr "Bashkangjitje"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr "Shtoni bashkangjitje"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:53
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
msgid "Cancel"
msgstr "Anuloje"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:43
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
msgid "Save changes"
msgstr "Ruaji ndryshimet"
+#: mediagoblin/templates/mediagoblin/edit/edit.html:23
+#: mediagoblin/templates/mediagoblin/edit/edit.html:35
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "Po përpunohet %(media_title)s"
+
#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:41
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
#, python-format
msgid "Changing %(username)s's account settings"
msgstr "Po ndryshohen rregullimet e llogarisë %(username)s"
@@ -572,7 +590,7 @@ msgstr "Po ndryshohen rregullimet e llogarisë %(username)s"
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29
#, python-format
msgid "Editing %(collection_title)s"
-msgstr ""
+msgstr "Po përpunohet %(collection_title)s"
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:23
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
@@ -590,13 +608,12 @@ 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/image.html:23
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
msgid "Download"
msgstr "Shkarkojeni"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:27
msgid "Original"
msgstr "Origjinal"
@@ -617,12 +634,62 @@ msgstr "Një shfletues web modern që mund të luajë \n\taudion mund ta merrni
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:60
#: mediagoblin/templates/mediagoblin/media_displays/video.html:56
msgid "Original file"
-msgstr ""
+msgstr "Kartela origjinale"
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:63
msgid "WebM file (Vorbis codec)"
msgstr "Kartelë WebM (kodek Vorbis)"
+#: 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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr "Figurë për %(media_title)s"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:112
+msgid "Toggle Rotate"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:113
+msgid "Perspective"
+msgstr "Perspektivë"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:116
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:117
+msgid "Front"
+msgstr "Ball"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:120
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:121
+msgid "Top"
+msgstr "Krye"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:124
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:125
+msgid "Side"
+msgstr "Anë"
+
+#: 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 "Shkarkojeni modelin"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:146
+msgid "File Format"
+msgstr "Format Kartele"
+
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:148
+msgid "Object Height"
+msgstr "Lartësi Objekti"
+
#: mediagoblin/templates/mediagoblin/media_displays/video.html:40
msgid ""
"Sorry, this video will not work because \n"
@@ -639,15 +706,15 @@ msgstr "Një shfletues web modern që \n\t mund ta luajë këtë video mund t
#: mediagoblin/templates/mediagoblin/media_displays/video.html:59
msgid "WebM file (640p; VP8/Vorbis)"
-msgstr ""
+msgstr "Kartelë WebM (640p; VP8/Vorbis)"
#: mediagoblin/templates/mediagoblin/submit/collection.html:26
msgid "Add a collection"
-msgstr ""
+msgstr "Shtoni një koleksion"
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
#: mediagoblin/templates/mediagoblin/submit/start.html:34
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:83
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
msgid "Add"
msgstr "Shtoni"
@@ -659,12 +726,12 @@ msgstr "Shtoni media tuajën"
#: mediagoblin/templates/mediagoblin/user_pages/collection.html:30
#, python-format
msgid "%(collection_title)s (%(username)s's collection)"
-msgstr ""
+msgstr "%(collection_title)s (koleksione nga %(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 ""
+msgstr "%(collection_title)s nga <a href=\"%(user_url)s\">%(username)s</a>"
#: mediagoblin/templates/mediagoblin/user_pages/collection.html:52
#: mediagoblin/templates/mediagoblin/user_pages/media.html:87
@@ -676,14 +743,6 @@ msgstr "Përpunoni"
msgid "Delete"
msgstr "Fshije"
-#: mediagoblin/templates/mediagoblin/user_pages/collection.html:59
-#, python-format
-msgid ""
-"<p>\n"
-" %(collection_description)s\n"
-" </p>"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
@@ -691,25 +750,25 @@ msgid "Really delete %(title)s?"
msgstr "Të fshihet vërtet %(title)s?"
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr "Fshije përgjithmonë"
#: 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 "Të hiqet vërtet %(media_title)s nga %(collection_title)s?"
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
msgid "Remove"
-msgstr ""
+msgstr "Hiqe"
#: 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 "Tungjatjeta %(username)s,\n%(comment_author)s ka komentuar te postimi juaj (%(comment_url)s) në %(instance_name)s\n"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30
#, python-format
@@ -726,12 +785,6 @@ 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:67
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
-#, python-format
-msgid "Image for %(media_title)s"
-msgstr "Figurë për %(media_title)s"
-
#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
msgid "Add a comment"
msgstr "Shtoni një koment"
@@ -758,27 +811,22 @@ msgid ""
" <p>%(date)s</p>"
msgstr "<h3>Shtuar më</h3>\n <p>%(date)s</p>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
-msgid "Attachments"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
-msgid "Add attachment"
-msgstr ""
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
+msgstr "Shtoni koleksion media"
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
#, python-format
msgid "Add %(title)s to collection"
-msgstr ""
+msgstr "Shtoni %(title)s te koleksioni juaj"
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
msgid "+"
-msgstr ""
+msgstr "+"
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
msgid "Add a new collection"
-msgstr ""
+msgstr "Shtoni një koleksion të ri"
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:29
msgid ""
@@ -787,7 +835,7 @@ msgstr "Gjendjen e medias që po përpunohet për galerinë tuaj mund ta ndiqni
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:89
msgid "Your last 10 successful uploads"
-msgstr ""
+msgstr "10 ngarkimet tuaja më të suksesshme"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:31
#: mediagoblin/templates/mediagoblin/user_pages/user.html:89
@@ -847,47 +895,31 @@ msgstr "Përpunoni profil"
msgid "This user hasn't filled in their profile (yet)."
msgstr "Ky përdorues nuk e ka plotësuar (ende) profilin e vet."
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:125
-msgid "Change account settings"
-msgstr "Ndryshoni rregullime llogarie"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:138
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
#, python-format
msgid "View all of %(username)s's media"
msgstr "Shihni krejt mediat nga %(username)s"
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
msgid ""
"This is where your media will appear, but you don't seem to have added "
"anything yet."
msgstr "Media juaj do të shfaqet këtu, por nuk duket të keni shtuar gjë ende."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:157
-msgid "Add media"
-msgstr "Shtoni media"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:163
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:87
-#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:72
+#: 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 "Nuk duket ende të ketë ndonjë media këtu..."
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:39
-#, python-format
-msgid ""
-"<br />\n"
-" <a href=\"%(entry_url)s\">%(note)s</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:47
-#, python-format
-msgid "<br /><a href=\"%(remove_url)s\" class=\"remove\">(remove)</a>"
-msgstr ""
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
+msgstr "(hiqe)"
#: mediagoblin/templates/mediagoblin/utils/collections.html:20
#, python-format
msgid "In collections (%(collected)s)"
-msgstr ""
+msgstr "Te koleksionet (%(collected)s)"
#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
msgid "feed icon"
@@ -901,7 +933,7 @@ msgstr "Prurje Atom"
msgid "Location"
msgstr "Vend"
-#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:38
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
#, python-format
msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
msgstr "Shiheni te <a href=\"%(osm_url)s\">OpenStreetMap</a>"
@@ -940,94 +972,120 @@ msgstr "Etiketuar me"
msgid "Could not read the image file."
msgstr "Nuk lexoi dot kartelën e figurës."
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr "Oooh!"
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr "Ndodhi një gabim"
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr "Veprim i palejuar"
+
+#: mediagoblin/tools/response.py:47
+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 "Më ndjeni or trim, nuk ju lë dot ta bëni këtë!</p><p>Provuat të kryeni një funksion që nuk lejohet. Keni provuar prapë të fshini krejt llogaritë e përdoruesve?"
+
+#: mediagoblin/tools/response.py:55
+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 "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/user_pages/forms.py:28
msgid "I am sure I want to delete this"
msgstr "Jam i sigurt që dua të fshihet kjo"
#: mediagoblin/user_pages/forms.py:32
msgid "I am sure I want to remove this item from the collection"
-msgstr ""
+msgstr "Jam i sigurt se dua që të hiqet ky objekt prek koleksioni"
#: mediagoblin/user_pages/forms.py:35
msgid "-- Select --"
-msgstr ""
+msgstr "-- Përzgjidhni --"
#: mediagoblin/user_pages/forms.py:37
msgid "Include a note"
-msgstr ""
+msgstr "Përfshini një shënim"
#: mediagoblin/user_pages/lib.py:56
msgid "commented on your post"
-msgstr ""
+msgstr "komentoi te postimi juaj"
-#: mediagoblin/user_pages/views.py:161
+#: mediagoblin/user_pages/views.py:156
msgid "Oops, your comment was empty."
msgstr "Hmmm, komenti juaj qe i zbrazët."
-#: mediagoblin/user_pages/views.py:167
+#: mediagoblin/user_pages/views.py:162
msgid "Your comment has been posted!"
msgstr "Komenti juaj u postua!"
-#: mediagoblin/user_pages/views.py:235
+#: mediagoblin/user_pages/views.py:230
msgid "You have to select or add a collection"
-msgstr ""
+msgstr "Duhet të përzgjidhni ose shtoni një koleksion"
-#: mediagoblin/user_pages/views.py:243
+#: mediagoblin/user_pages/views.py:238
#, python-format
msgid "\"%s\" already in collection \"%s\""
-msgstr ""
+msgstr "\"%s\" gjendet tashmë te koleksioni \"%s\""
-#: mediagoblin/user_pages/views.py:258
+#: mediagoblin/user_pages/views.py:253
#, python-format
msgid "\"%s\" added to collection \"%s\""
-msgstr ""
+msgstr "\"%s\" u shtua te koleksioni \"%s\""
-#: mediagoblin/user_pages/views.py:266
+#: mediagoblin/user_pages/views.py:261
msgid "Please check your entries and try again."
-msgstr ""
+msgstr "Ju lutemi, kontrolloni zërat tuaj dhe riprovoni."
-#: mediagoblin/user_pages/views.py:297
+#: mediagoblin/user_pages/views.py:292
msgid ""
"Some of the files with this entry seem to be missing. Deleting anyway."
-msgstr ""
+msgstr "Duket se mungojnë disa nga kartelat në këtë zë. Po fshihet, sido qoftë."
-#: mediagoblin/user_pages/views.py:302
+#: mediagoblin/user_pages/views.py:297
msgid "You deleted the media."
msgstr "E fshitë median."
-#: mediagoblin/user_pages/views.py:309
+#: mediagoblin/user_pages/views.py:304
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:317
+#: mediagoblin/user_pages/views.py:312
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. Bëni kujdes."
+msgstr "Ju ndan një hap nga fshirja e medias të një tjetër përdoruesi. Hapni sytë."
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
-msgstr ""
+msgstr "E fshitë objektin prej koleksionit."
-#: mediagoblin/user_pages/views.py:383
+#: mediagoblin/user_pages/views.py:374
msgid "The item was not removed because you didn't check that you were sure."
-msgstr ""
+msgstr "Objekti nuk u fshi ngaqë, nuk pohuat se jeni të sigurt për këtë."
-#: mediagoblin/user_pages/views.py:393
+#: mediagoblin/user_pages/views.py:384
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
-msgstr ""
+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:426
+#: mediagoblin/user_pages/views.py:417
#, python-format
msgid "You deleted the collection \"%s\""
-msgstr ""
+msgstr "E fshitë koleksionin \"%s\""
-#: mediagoblin/user_pages/views.py:433
+#: mediagoblin/user_pages/views.py:424
msgid ""
"The collection was not deleted because you didn't check that you were sure."
-msgstr ""
+msgstr "Koleksioni nuk u fshi ngaqë, nuk pohuat se jeni të sigurt për këtë."
-#: mediagoblin/user_pages/views.py:443
+#: mediagoblin/user_pages/views.py:434
msgid ""
"You are about to delete another user's collection. Proceed with caution."
-msgstr ""
+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 132ae65d..dd67d341 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 168337b2..32e7d3d9 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: 2012-09-24 14:01-0500\n"
-"PO-Revision-Date: 2012-09-24 18:57+0000\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 15:14+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"
@@ -91,7 +91,7 @@ msgstr ""
msgid "You can now log in using your new password."
msgstr ""
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:83
+#: 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:40
msgid "Title"
@@ -102,7 +102,7 @@ msgid "Description of this work"
msgstr ""
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:87 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:44
msgid ""
"You can use\n"
@@ -118,11 +118,11 @@ msgstr ""
msgid "Separate tags by commas."
msgstr ""
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:91
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr ""
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:92
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr ""
@@ -161,20 +161,20 @@ msgstr ""
msgid "New password"
msgstr ""
-#: mediagoblin/edit/forms.py:72
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr ""
-#: mediagoblin/edit/forms.py:84
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:43
msgid "Description of this collection"
msgstr ""
-#: mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
@@ -188,33 +188,38 @@ msgstr ""
msgid "You are editing another user's media. Proceed with caution."
msgstr ""
-#: mediagoblin/edit/views.py:182
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr ""
+
+#: mediagoblin/edit/views.py:181
msgid "You are editing a user's profile. Proceed with caution."
msgstr ""
-#: mediagoblin/edit/views.py:198
+#: mediagoblin/edit/views.py:197
msgid "Profile changes saved"
msgstr ""
-#: mediagoblin/edit/views.py:227 mediagoblin/edit/views.py:247
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
msgid "Account settings saved"
msgstr ""
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:251
msgid "Wrong password"
msgstr ""
-#: mediagoblin/edit/views.py:288 mediagoblin/submit/views.py:211
-#: mediagoblin/user_pages/views.py:215
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr ""
-#: mediagoblin/edit/views.py:292
+#: mediagoblin/edit/views.py:291
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:309
+#: mediagoblin/edit/views.py:308
msgid "You are editing another user's collection. Proceed with caution."
msgstr ""
@@ -231,7 +236,7 @@ msgid "However, old link directory symlink found; removed.\n"
msgstr ""
#: mediagoblin/media_types/__init__.py:60
-#: mediagoblin/media_types/__init__.py:120
+#: mediagoblin/media_types/__init__.py:101
msgid "Sorry, I don't support that file type :("
msgstr ""
@@ -301,7 +306,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:60
msgid "The client {0} has been registered!"
msgstr ""
@@ -326,62 +331,43 @@ msgstr ""
msgid "Collection \"%s\" added!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/404.html:24
-msgid "Image of 404 goblin stressing out"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/404.html:25
-msgid "Oops!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/404.html:26
-msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/404.html:28
-msgid ""
-"If you're sure the address is correct, maybe the page you're looking for has"
-" been moved or deleted."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:50
+#: mediagoblin/templates/mediagoblin/base.html:48
msgid "MediaGoblin logo"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:60
-msgid "Verify your email!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:66
-msgid "+ Add media"
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:67
-msgid "+ Add collection"
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:69
-msgid "View your profile"
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:70
-msgid "Log out"
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:75
+#: 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:89
+#: mediagoblin/templates/mediagoblin/base.html:87
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project."
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:92
+#: mediagoblin/templates/mediagoblin/base.html:90
#, python-format
msgid ""
"Released under the <a "
@@ -389,31 +375,56 @@ msgid ""
"href=\"%(source_link)s\">Source code</a> available."
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:24
+#: mediagoblin/templates/mediagoblin/error.html:24
+msgid "Image of goblin stressing out"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:25
+msgid "Actions"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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/root.html:51
msgid "Explore"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:26
+#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Hi there, welcome to this MediaGoblin site!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/root.html:55
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:29
+#: mediagoblin/templates/mediagoblin/root.html:56
msgid ""
"To add your own media, place comments, and more, you can log in with your "
"MediaGoblin account."
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:31
+#: mediagoblin/templates/mediagoblin/root.html:58
msgid "Don't have one yet? It's easy!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:32
+#: mediagoblin/templates/mediagoblin/root.html:59
#, python-format
msgid ""
"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
@@ -421,17 +432,10 @@ msgid ""
" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:40
+#: mediagoblin/templates/mediagoblin/root.html:67
msgid "Most recent media"
msgstr ""
-#: 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/admin/panel.html:29
msgid ""
"Here you can track the state of media being processed on this instance."
@@ -540,30 +544,43 @@ msgstr ""
msgid "Editing attachments for %(media_title)s"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit.html:23
-#: mediagoblin/templates/mediagoblin/edit/edit.html:35
-#, python-format
-msgid "Editing %(media_title)s"
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:43
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
+msgid "Attachments"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:53
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
msgid "Cancel"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit.html:43
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
msgid "Save changes"
msgstr ""
+#: mediagoblin/templates/mediagoblin/edit/edit.html:23
+#: mediagoblin/templates/mediagoblin/edit/edit.html:35
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:41
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
#, python-format
msgid "Changing %(username)s's account settings"
msgstr ""
@@ -589,13 +606,12 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:23
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
msgid "Download"
msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:27
msgid "Original"
msgstr ""
@@ -622,6 +638,56 @@ msgstr ""
msgid "WebM file (Vorbis codec)"
msgstr ""
+#: 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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr ""
+
+#: 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 ""
+
+#: 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:40
msgid ""
"Sorry, this video will not work because \n"
@@ -646,7 +712,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
#: mediagoblin/templates/mediagoblin/submit/start.html:34
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:83
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
msgid "Add"
msgstr ""
@@ -675,14 +741,6 @@ msgstr ""
msgid "Delete"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection.html:59
-#, python-format
-msgid ""
-"<p>\n"
-" %(collection_description)s\n"
-" </p>"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
@@ -690,7 +748,7 @@ msgid "Really delete %(title)s?"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr ""
@@ -699,7 +757,7 @@ msgstr ""
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
msgid "Remove"
msgstr ""
@@ -725,12 +783,6 @@ msgstr ""
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:67
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
-#, python-format
-msgid "Image for %(media_title)s"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
msgid "Add a comment"
msgstr ""
@@ -757,13 +809,8 @@ msgid ""
" <p>%(date)s</p>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
-msgid "Attachments"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
-msgid "Add attachment"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
@@ -771,11 +818,11 @@ msgstr ""
msgid "Add %(title)s to collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
msgid "+"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
msgid "Add a new collection"
msgstr ""
@@ -846,41 +893,25 @@ msgstr ""
msgid "This user hasn't filled in their profile (yet)."
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:125
-msgid "Change account settings"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:138
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
#, python-format
msgid "View all of %(username)s's media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
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:157
-msgid "Add media"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:163
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:87
-#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:72
+#: 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:39
-#, python-format
-msgid ""
-"<br />\n"
-" <a href=\"%(entry_url)s\">%(note)s</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:47
-#, python-format
-msgid "<br /><a href=\"%(remove_url)s\" class=\"remove\">(remove)</a>"
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
msgstr ""
#: mediagoblin/templates/mediagoblin/utils/collections.html:20
@@ -900,7 +931,7 @@ msgstr ""
msgid "Location"
msgstr ""
-#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:38
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
#, python-format
msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
msgstr ""
@@ -939,6 +970,32 @@ msgstr ""
msgid "Could not read the image file."
msgstr ""
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr ""
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr ""
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr ""
+
+#: mediagoblin/tools/response.py:47
+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:55
+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/user_pages/forms.py:28
msgid "I am sure I want to delete this"
msgstr ""
@@ -959,74 +1016,74 @@ msgstr ""
msgid "commented on your post"
msgstr ""
-#: mediagoblin/user_pages/views.py:161
+#: mediagoblin/user_pages/views.py:156
msgid "Oops, your comment was empty."
msgstr ""
-#: mediagoblin/user_pages/views.py:167
+#: mediagoblin/user_pages/views.py:162
msgid "Your comment has been posted!"
msgstr ""
-#: mediagoblin/user_pages/views.py:235
+#: mediagoblin/user_pages/views.py:230
msgid "You have to select or add a collection"
msgstr ""
-#: mediagoblin/user_pages/views.py:243
+#: mediagoblin/user_pages/views.py:238
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:258
+#: mediagoblin/user_pages/views.py:253
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:266
+#: mediagoblin/user_pages/views.py:261
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:297
+#: mediagoblin/user_pages/views.py:292
msgid ""
"Some of the files with this entry seem to be missing. Deleting anyway."
msgstr ""
-#: mediagoblin/user_pages/views.py:302
+#: mediagoblin/user_pages/views.py:297
msgid "You deleted the media."
msgstr ""
-#: mediagoblin/user_pages/views.py:309
+#: mediagoblin/user_pages/views.py:304
msgid "The media was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:317
+#: mediagoblin/user_pages/views.py:312
msgid "You are about to delete another user's media. Proceed with caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr ""
-#: mediagoblin/user_pages/views.py:383
+#: 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:393
+#: mediagoblin/user_pages/views.py:384
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:426
+#: mediagoblin/user_pages/views.py:417
#, python-format
msgid "You deleted the collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:433
+#: mediagoblin/user_pages/views.py:424
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:443
+#: mediagoblin/user_pages/views.py:434
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 e2a0bc66..e4586d50 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 fda30875..d288feac 100644
--- a/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.po
@@ -9,8 +9,8 @@ msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2012-09-24 14:01-0500\n"
-"PO-Revision-Date: 2012-09-24 18:57+0000\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 15:14+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"
@@ -93,7 +93,7 @@ msgstr ""
msgid "You can now log in using your new password."
msgstr ""
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:83
+#: 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:40
msgid "Title"
@@ -104,7 +104,7 @@ msgid "Description of this work"
msgstr "Beskrivning av verket"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:87 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:44
msgid ""
"You can use\n"
@@ -120,11 +120,11 @@ msgstr "Taggar"
msgid "Separate tags by commas."
msgstr ""
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:91
+#: 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:92
+#: 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"
@@ -163,20 +163,20 @@ msgstr ""
msgid "New password"
msgstr ""
-#: mediagoblin/edit/forms.py:72
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr ""
-#: mediagoblin/edit/forms.py:84
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:43
msgid "Description of this collection"
msgstr ""
-#: mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
@@ -190,33 +190,38 @@ msgstr "Ett inlägg med det sökvägsnamnet existerar redan."
msgid "You are editing another user's media. Proceed with caution."
msgstr "Var försiktig, du redigerar någon annans inlägg."
-#: mediagoblin/edit/views.py:182
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr ""
+
+#: mediagoblin/edit/views.py:181
msgid "You are editing a user's profile. Proceed with caution."
msgstr "Var försiktig, du redigerar en annan användares profil."
-#: mediagoblin/edit/views.py:198
+#: mediagoblin/edit/views.py:197
msgid "Profile changes saved"
msgstr ""
-#: mediagoblin/edit/views.py:227 mediagoblin/edit/views.py:247
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
msgid "Account settings saved"
msgstr ""
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:251
msgid "Wrong password"
msgstr "Fel lösenord"
-#: mediagoblin/edit/views.py:288 mediagoblin/submit/views.py:211
-#: mediagoblin/user_pages/views.py:215
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr ""
-#: mediagoblin/edit/views.py:292
+#: mediagoblin/edit/views.py:291
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:309
+#: mediagoblin/edit/views.py:308
msgid "You are editing another user's collection. Proceed with caution."
msgstr ""
@@ -233,7 +238,7 @@ msgid "However, old link directory symlink found; removed.\n"
msgstr ""
#: mediagoblin/media_types/__init__.py:60
-#: mediagoblin/media_types/__init__.py:120
+#: mediagoblin/media_types/__init__.py:101
msgid "Sorry, I don't support that file type :("
msgstr ""
@@ -303,7 +308,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:60
msgid "The client {0} has been registered!"
msgstr ""
@@ -328,62 +333,43 @@ msgstr "Tjohoo! Upladdat!"
msgid "Collection \"%s\" added!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/404.html:24
-msgid "Image of 404 goblin stressing out"
-msgstr "Bild av stressat 404-troll."
-
-#: mediagoblin/templates/mediagoblin/404.html:25
-msgid "Oops!"
-msgstr "Ojoj!"
-
-#: mediagoblin/templates/mediagoblin/404.html:26
-msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr "Ledsen, det verkar inte vara någonting här."
-
-#: mediagoblin/templates/mediagoblin/404.html:28
-msgid ""
-"If you're sure the address is correct, maybe the page you're looking for has"
-" been moved or deleted."
-msgstr "Om du är säker på att adressen stämmer så kanske sidan du letar efter har flyttats eller tagits bort."
-
-#: mediagoblin/templates/mediagoblin/base.html:50
+#: mediagoblin/templates/mediagoblin/base.html:48
msgid "MediaGoblin logo"
msgstr "MediaGoblin-logotyp"
-#: mediagoblin/templates/mediagoblin/base.html:60
-msgid "Verify your email!"
-msgstr "Verifiera din e-postadress"
-
-#: mediagoblin/templates/mediagoblin/base.html:66
-msgid "+ Add media"
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:67
-msgid "+ Add collection"
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:69
-msgid "View your profile"
-msgstr ""
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
+msgstr "Lägg till media"
-#: mediagoblin/templates/mediagoblin/base.html:70
-msgid "Log out"
-msgstr ""
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
+msgstr "Verifiera din e-postadress"
-#: mediagoblin/templates/mediagoblin/base.html:75
+#: 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:89
+#: mediagoblin/templates/mediagoblin/base.html:87
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project."
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:92
+#: mediagoblin/templates/mediagoblin/base.html:90
#, python-format
msgid ""
"Released under the <a "
@@ -391,31 +377,56 @@ msgid ""
"href=\"%(source_link)s\">Source code</a> available."
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:24
+#: mediagoblin/templates/mediagoblin/error.html:24
+msgid "Image of goblin stressing out"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:25
+msgid "Actions"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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 "Mediabehandlingspanel"
+
+#: mediagoblin/templates/mediagoblin/root.html:51
msgid "Explore"
msgstr "Utforska"
-#: mediagoblin/templates/mediagoblin/root.html:26
+#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Hi there, welcome to this MediaGoblin site!"
msgstr "Hej, välkommen till den här MediaGoblin-sidan!"
-#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/root.html:55
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:29
+#: mediagoblin/templates/mediagoblin/root.html:56
msgid ""
"To add your own media, place comments, and more, you can log in with your "
"MediaGoblin account."
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:31
+#: mediagoblin/templates/mediagoblin/root.html:58
msgid "Don't have one yet? It's easy!"
msgstr "Har du inte ett redan?"
-#: mediagoblin/templates/mediagoblin/root.html:32
+#: mediagoblin/templates/mediagoblin/root.html:59
#, python-format
msgid ""
"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
@@ -423,17 +434,10 @@ msgid ""
" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:40
+#: mediagoblin/templates/mediagoblin/root.html:67
msgid "Most recent media"
msgstr "Senast medier"
-#: 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 "Mediabehandlingspanel"
-
#: mediagoblin/templates/mediagoblin/admin/panel.html:29
msgid ""
"Here you can track the state of media being processed on this instance."
@@ -542,30 +546,43 @@ msgstr "Hej %(username)s,\n\nöppna den följande webbadressen i din webbläsare
msgid "Editing attachments for %(media_title)s"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit.html:23
-#: mediagoblin/templates/mediagoblin/edit/edit.html:35
-#, python-format
-msgid "Editing %(media_title)s"
-msgstr "Redigerar %(media_title)s"
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:43
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
+msgid "Attachments"
+msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:53
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
msgid "Cancel"
msgstr "Avbryt"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:43
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
msgid "Save changes"
msgstr "Spara ändringar"
+#: mediagoblin/templates/mediagoblin/edit/edit.html:23
+#: mediagoblin/templates/mediagoblin/edit/edit.html:35
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "Redigerar %(media_title)s"
+
#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:41
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
#, python-format
msgid "Changing %(username)s's account settings"
msgstr ""
@@ -591,13 +608,12 @@ 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/image.html:23
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
msgid "Download"
msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:27
msgid "Original"
msgstr "Original"
@@ -624,6 +640,56 @@ msgstr ""
msgid "WebM file (Vorbis codec)"
msgstr ""
+#: 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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr ""
+
+#: 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 ""
+
+#: 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:40
msgid ""
"Sorry, this video will not work because \n"
@@ -648,7 +714,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
#: mediagoblin/templates/mediagoblin/submit/start.html:34
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:83
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
msgid "Add"
msgstr ""
@@ -677,14 +743,6 @@ msgstr ""
msgid "Delete"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection.html:59
-#, python-format
-msgid ""
-"<p>\n"
-" %(collection_description)s\n"
-" </p>"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
@@ -692,7 +750,7 @@ msgid "Really delete %(title)s?"
msgstr "Vill du verkligen radera %(title)s?"
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr ""
@@ -701,7 +759,7 @@ msgstr ""
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
msgid "Remove"
msgstr ""
@@ -727,12 +785,6 @@ 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:67
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
-#, python-format
-msgid "Image for %(media_title)s"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
msgid "Add a comment"
msgstr ""
@@ -759,13 +811,8 @@ msgid ""
" <p>%(date)s</p>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
-msgid "Attachments"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
-msgid "Add attachment"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
@@ -773,11 +820,11 @@ msgstr ""
msgid "Add %(title)s to collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
msgid "+"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
msgid "Add a new collection"
msgstr ""
@@ -848,41 +895,25 @@ msgstr "Redigera profil"
msgid "This user hasn't filled in their profile (yet)."
msgstr "Den här användaren har inte fyllt i sin profilsida ännu."
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:125
-msgid "Change account settings"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:138
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
#, python-format
msgid "View all of %(username)s's media"
msgstr "Se all media från %(username)s"
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
msgid ""
"This is where your media will appear, but you don't seem to have added "
"anything yet."
msgstr "Här kommer din media att dyka upp, du verkar inte ha lagt till någonting ännu."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:157
-msgid "Add media"
-msgstr "Lägg till media"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:163
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:87
-#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:72
+#: 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 "Det verkar inte finnas någon media här ännu."
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:39
-#, python-format
-msgid ""
-"<br />\n"
-" <a href=\"%(entry_url)s\">%(note)s</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:47
-#, python-format
-msgid "<br /><a href=\"%(remove_url)s\" class=\"remove\">(remove)</a>"
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
msgstr ""
#: mediagoblin/templates/mediagoblin/utils/collections.html:20
@@ -902,7 +933,7 @@ msgstr "Atom-feed"
msgid "Location"
msgstr ""
-#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:38
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
#, python-format
msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
msgstr ""
@@ -941,6 +972,32 @@ msgstr ""
msgid "Could not read the image file."
msgstr ""
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr "Ojoj!"
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr ""
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr ""
+
+#: mediagoblin/tools/response.py:47
+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:55
+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/user_pages/forms.py:28
msgid "I am sure I want to delete this"
msgstr "Jag är säker på att jag vill radera detta"
@@ -961,74 +1018,74 @@ msgstr ""
msgid "commented on your post"
msgstr ""
-#: mediagoblin/user_pages/views.py:161
+#: mediagoblin/user_pages/views.py:156
msgid "Oops, your comment was empty."
msgstr ""
-#: mediagoblin/user_pages/views.py:167
+#: mediagoblin/user_pages/views.py:162
msgid "Your comment has been posted!"
msgstr ""
-#: mediagoblin/user_pages/views.py:235
+#: mediagoblin/user_pages/views.py:230
msgid "You have to select or add a collection"
msgstr ""
-#: mediagoblin/user_pages/views.py:243
+#: mediagoblin/user_pages/views.py:238
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:258
+#: mediagoblin/user_pages/views.py:253
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:266
+#: mediagoblin/user_pages/views.py:261
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:297
+#: mediagoblin/user_pages/views.py:292
msgid ""
"Some of the files with this entry seem to be missing. Deleting anyway."
msgstr ""
-#: mediagoblin/user_pages/views.py:302
+#: mediagoblin/user_pages/views.py:297
msgid "You deleted the media."
msgstr ""
-#: mediagoblin/user_pages/views.py:309
+#: mediagoblin/user_pages/views.py:304
msgid "The media was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:317
+#: mediagoblin/user_pages/views.py:312
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:379
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr ""
-#: mediagoblin/user_pages/views.py:383
+#: 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:393
+#: mediagoblin/user_pages/views.py:384
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:426
+#: mediagoblin/user_pages/views.py:417
#, python-format
msgid "You deleted the collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:433
+#: mediagoblin/user_pages/views.py:424
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:443
+#: mediagoblin/user_pages/views.py:434
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 e341a891..5009e371 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 17d5910c..44a7bf44 100644
--- a/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.po
@@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2012-09-24 14:01-0500\n"
-"PO-Revision-Date: 2012-09-24 18:57+0000\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 15:14+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
@@ -92,7 +92,7 @@ msgstr ""
msgid "You can now log in using your new password."
msgstr ""
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:83
+#: 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:40
msgid "Title"
@@ -103,7 +103,7 @@ msgid "Description of this work"
msgstr ""
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:87 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:44
msgid ""
"You can use\n"
@@ -119,11 +119,11 @@ msgstr ""
msgid "Separate tags by commas."
msgstr ""
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:91
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr ""
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:92
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr ""
@@ -162,20 +162,20 @@ msgstr ""
msgid "New password"
msgstr ""
-#: mediagoblin/edit/forms.py:72
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr ""
-#: mediagoblin/edit/forms.py:84
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:43
msgid "Description of this collection"
msgstr ""
-#: mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
@@ -189,33 +189,38 @@ msgstr ""
msgid "You are editing another user's media. Proceed with caution."
msgstr ""
-#: mediagoblin/edit/views.py:182
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr ""
+
+#: mediagoblin/edit/views.py:181
msgid "You are editing a user's profile. Proceed with caution."
msgstr ""
-#: mediagoblin/edit/views.py:198
+#: mediagoblin/edit/views.py:197
msgid "Profile changes saved"
msgstr ""
-#: mediagoblin/edit/views.py:227 mediagoblin/edit/views.py:247
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
msgid "Account settings saved"
msgstr ""
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:251
msgid "Wrong password"
msgstr ""
-#: mediagoblin/edit/views.py:288 mediagoblin/submit/views.py:211
-#: mediagoblin/user_pages/views.py:215
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr ""
-#: mediagoblin/edit/views.py:292
+#: mediagoblin/edit/views.py:291
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:309
+#: mediagoblin/edit/views.py:308
msgid "You are editing another user's collection. Proceed with caution."
msgstr ""
@@ -232,7 +237,7 @@ msgid "However, old link directory symlink found; removed.\n"
msgstr ""
#: mediagoblin/media_types/__init__.py:60
-#: mediagoblin/media_types/__init__.py:120
+#: mediagoblin/media_types/__init__.py:101
msgid "Sorry, I don't support that file type :("
msgstr ""
@@ -302,7 +307,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:60
msgid "The client {0} has been registered!"
msgstr ""
@@ -327,62 +332,43 @@ msgstr ""
msgid "Collection \"%s\" added!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/404.html:24
-msgid "Image of 404 goblin stressing out"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/404.html:25
-msgid "Oops!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/404.html:26
-msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/404.html:28
-msgid ""
-"If you're sure the address is correct, maybe the page you're looking for has"
-" been moved or deleted."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:50
+#: mediagoblin/templates/mediagoblin/base.html:48
msgid "MediaGoblin logo"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:60
-msgid "Verify your email!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:66
-msgid "+ Add media"
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:67
-msgid "+ Add collection"
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:69
-msgid "View your profile"
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:70
-msgid "Log out"
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:75
+#: 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:89
+#: mediagoblin/templates/mediagoblin/base.html:87
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project."
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:92
+#: mediagoblin/templates/mediagoblin/base.html:90
#, python-format
msgid ""
"Released under the <a "
@@ -390,31 +376,56 @@ msgid ""
"href=\"%(source_link)s\">Source code</a> available."
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:24
+#: mediagoblin/templates/mediagoblin/error.html:24
+msgid "Image of goblin stressing out"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:25
+msgid "Actions"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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/root.html:51
msgid "Explore"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:26
+#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Hi there, welcome to this MediaGoblin site!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/root.html:55
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:29
+#: mediagoblin/templates/mediagoblin/root.html:56
msgid ""
"To add your own media, place comments, and more, you can log in with your "
"MediaGoblin account."
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:31
+#: mediagoblin/templates/mediagoblin/root.html:58
msgid "Don't have one yet? It's easy!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:32
+#: mediagoblin/templates/mediagoblin/root.html:59
#, python-format
msgid ""
"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
@@ -422,17 +433,10 @@ msgid ""
" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:40
+#: mediagoblin/templates/mediagoblin/root.html:67
msgid "Most recent media"
msgstr ""
-#: 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/admin/panel.html:29
msgid ""
"Here you can track the state of media being processed on this instance."
@@ -541,30 +545,43 @@ msgstr ""
msgid "Editing attachments for %(media_title)s"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit.html:23
-#: mediagoblin/templates/mediagoblin/edit/edit.html:35
-#, python-format
-msgid "Editing %(media_title)s"
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:43
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
+msgid "Attachments"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:53
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
msgid "Cancel"
msgstr "à°°à°¦à±à°¦à±à°šà±‡à°¯à°¿"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:43
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
msgid "Save changes"
msgstr "మారà±à°ªà±à°²à°¨à± à°­à°¦à±à°°à°ªà°°à°šà±"
+#: mediagoblin/templates/mediagoblin/edit/edit.html:23
+#: mediagoblin/templates/mediagoblin/edit/edit.html:35
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:41
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
#, python-format
msgid "Changing %(username)s's account settings"
msgstr ""
@@ -590,13 +607,12 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:23
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
msgid "Download"
msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:27
msgid "Original"
msgstr ""
@@ -623,6 +639,56 @@ msgstr ""
msgid "WebM file (Vorbis codec)"
msgstr ""
+#: 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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr ""
+
+#: 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 ""
+
+#: 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:40
msgid ""
"Sorry, this video will not work because \n"
@@ -647,7 +713,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
#: mediagoblin/templates/mediagoblin/submit/start.html:34
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:83
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
msgid "Add"
msgstr ""
@@ -676,14 +742,6 @@ msgstr ""
msgid "Delete"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection.html:59
-#, python-format
-msgid ""
-"<p>\n"
-" %(collection_description)s\n"
-" </p>"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
@@ -691,7 +749,7 @@ msgid "Really delete %(title)s?"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr ""
@@ -700,7 +758,7 @@ msgstr ""
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
msgid "Remove"
msgstr ""
@@ -726,12 +784,6 @@ msgstr ""
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:67
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
-#, python-format
-msgid "Image for %(media_title)s"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
msgid "Add a comment"
msgstr ""
@@ -758,13 +810,8 @@ msgid ""
" <p>%(date)s</p>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
-msgid "Attachments"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
-msgid "Add attachment"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
@@ -772,11 +819,11 @@ msgstr ""
msgid "Add %(title)s to collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
msgid "+"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
msgid "Add a new collection"
msgstr ""
@@ -847,41 +894,25 @@ msgstr ""
msgid "This user hasn't filled in their profile (yet)."
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:125
-msgid "Change account settings"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:138
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
#, python-format
msgid "View all of %(username)s's media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
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:157
-msgid "Add media"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:163
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:87
-#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:72
+#: 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:39
-#, python-format
-msgid ""
-"<br />\n"
-" <a href=\"%(entry_url)s\">%(note)s</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:47
-#, python-format
-msgid "<br /><a href=\"%(remove_url)s\" class=\"remove\">(remove)</a>"
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
msgstr ""
#: mediagoblin/templates/mediagoblin/utils/collections.html:20
@@ -901,7 +932,7 @@ msgstr ""
msgid "Location"
msgstr ""
-#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:38
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
#, python-format
msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
msgstr ""
@@ -940,6 +971,32 @@ msgstr ""
msgid "Could not read the image file."
msgstr ""
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr ""
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr ""
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr ""
+
+#: mediagoblin/tools/response.py:47
+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:55
+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/user_pages/forms.py:28
msgid "I am sure I want to delete this"
msgstr ""
@@ -960,74 +1017,74 @@ msgstr ""
msgid "commented on your post"
msgstr ""
-#: mediagoblin/user_pages/views.py:161
+#: mediagoblin/user_pages/views.py:156
msgid "Oops, your comment was empty."
msgstr ""
-#: mediagoblin/user_pages/views.py:167
+#: mediagoblin/user_pages/views.py:162
msgid "Your comment has been posted!"
msgstr ""
-#: mediagoblin/user_pages/views.py:235
+#: mediagoblin/user_pages/views.py:230
msgid "You have to select or add a collection"
msgstr ""
-#: mediagoblin/user_pages/views.py:243
+#: mediagoblin/user_pages/views.py:238
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:258
+#: mediagoblin/user_pages/views.py:253
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:266
+#: mediagoblin/user_pages/views.py:261
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:297
+#: mediagoblin/user_pages/views.py:292
msgid ""
"Some of the files with this entry seem to be missing. Deleting anyway."
msgstr ""
-#: mediagoblin/user_pages/views.py:302
+#: mediagoblin/user_pages/views.py:297
msgid "You deleted the media."
msgstr ""
-#: mediagoblin/user_pages/views.py:309
+#: mediagoblin/user_pages/views.py:304
msgid "The media was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:317
+#: mediagoblin/user_pages/views.py:312
msgid "You are about to delete another user's media. Proceed with caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr ""
-#: mediagoblin/user_pages/views.py:383
+#: 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:393
+#: mediagoblin/user_pages/views.py:384
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:426
+#: mediagoblin/user_pages/views.py:417
#, python-format
msgid "You deleted the collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:433
+#: mediagoblin/user_pages/views.py:424
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:443
+#: mediagoblin/user_pages/views.py:434
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 99f0c85b..7b1c154c 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 0729a2e7..5a47ef7c 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: 2012-09-24 14:01-0500\n"
-"PO-Revision-Date: 2012-09-24 18:57+0000\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 15:14+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"
@@ -91,7 +91,7 @@ msgstr ""
msgid "You can now log in using your new password."
msgstr ""
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:83
+#: 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:40
msgid "Title"
@@ -102,7 +102,7 @@ msgid "Description of this work"
msgstr ""
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:87 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:44
msgid ""
"You can use\n"
@@ -118,11 +118,11 @@ msgstr ""
msgid "Separate tags by commas."
msgstr ""
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:91
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
msgstr ""
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:92
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
msgstr ""
@@ -161,20 +161,20 @@ msgstr ""
msgid "New password"
msgstr ""
-#: mediagoblin/edit/forms.py:72
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
msgstr ""
-#: mediagoblin/edit/forms.py:84
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:43
msgid "Description of this collection"
msgstr ""
-#: mediagoblin/edit/forms.py:93
+#: mediagoblin/edit/forms.py:92
msgid ""
"The title part of this collection's address. You usually don't need to "
"change this."
@@ -188,33 +188,38 @@ msgstr ""
msgid "You are editing another user's media. Proceed with caution."
msgstr ""
-#: mediagoblin/edit/views.py:182
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr ""
+
+#: mediagoblin/edit/views.py:181
msgid "You are editing a user's profile. Proceed with caution."
msgstr ""
-#: mediagoblin/edit/views.py:198
+#: mediagoblin/edit/views.py:197
msgid "Profile changes saved"
msgstr ""
-#: mediagoblin/edit/views.py:227 mediagoblin/edit/views.py:247
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
msgid "Account settings saved"
msgstr ""
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:251
msgid "Wrong password"
msgstr ""
-#: mediagoblin/edit/views.py:288 mediagoblin/submit/views.py:211
-#: mediagoblin/user_pages/views.py:215
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
#, python-format
msgid "You already have a collection called \"%s\"!"
msgstr ""
-#: mediagoblin/edit/views.py:292
+#: mediagoblin/edit/views.py:291
msgid "A collection with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:309
+#: mediagoblin/edit/views.py:308
msgid "You are editing another user's collection. Proceed with caution."
msgstr ""
@@ -231,7 +236,7 @@ msgid "However, old link directory symlink found; removed.\n"
msgstr ""
#: mediagoblin/media_types/__init__.py:60
-#: mediagoblin/media_types/__init__.py:120
+#: mediagoblin/media_types/__init__.py:101
msgid "Sorry, I don't support that file type :("
msgstr ""
@@ -301,7 +306,7 @@ msgstr ""
msgid "This field is required for public clients"
msgstr ""
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:60
msgid "The client {0} has been registered!"
msgstr ""
@@ -326,62 +331,43 @@ msgstr ""
msgid "Collection \"%s\" added!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/404.html:24
-msgid "Image of 404 goblin stressing out"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/404.html:25
-msgid "Oops!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/404.html:26
-msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/404.html:28
-msgid ""
-"If you're sure the address is correct, maybe the page you're looking for has"
-" been moved or deleted."
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:50
+#: mediagoblin/templates/mediagoblin/base.html:48
msgid "MediaGoblin logo"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:60
-msgid "Verify your email!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/base.html:66
-msgid "+ Add media"
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(user_name)s</a>'s account"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:67
-msgid "+ Add collection"
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:69
-msgid "View your profile"
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:70
-msgid "Log out"
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:75
+#: 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:89
+#: mediagoblin/templates/mediagoblin/base.html:87
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project."
msgstr ""
-#: mediagoblin/templates/mediagoblin/base.html:92
+#: mediagoblin/templates/mediagoblin/base.html:90
#, python-format
msgid ""
"Released under the <a "
@@ -389,31 +375,56 @@ msgid ""
"href=\"%(source_link)s\">Source code</a> available."
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:24
+#: mediagoblin/templates/mediagoblin/error.html:24
+msgid "Image of goblin stressing out"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:25
+msgid "Actions"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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/root.html:51
msgid "Explore"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:26
+#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Hi there, welcome to this MediaGoblin site!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/root.html:55
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:29
+#: mediagoblin/templates/mediagoblin/root.html:56
msgid ""
"To add your own media, place comments, and more, you can log in with your "
"MediaGoblin account."
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:31
+#: mediagoblin/templates/mediagoblin/root.html:58
msgid "Don't have one yet? It's easy!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:32
+#: mediagoblin/templates/mediagoblin/root.html:59
#, python-format
msgid ""
"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n"
@@ -421,17 +432,10 @@ msgid ""
" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/root.html:40
+#: mediagoblin/templates/mediagoblin/root.html:67
msgid "Most recent media"
msgstr ""
-#: 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/admin/panel.html:29
msgid ""
"Here you can track the state of media being processed on this instance."
@@ -540,30 +544,43 @@ msgstr ""
msgid "Editing attachments for %(media_title)s"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit.html:23
-#: mediagoblin/templates/mediagoblin/edit/edit.html:35
-#, python-format
-msgid "Editing %(media_title)s"
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:43
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
+msgid "Attachments"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:53
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
msgid "Cancel"
msgstr ""
-#: mediagoblin/templates/mediagoblin/edit/edit.html:43
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
msgid "Save changes"
msgstr ""
+#: mediagoblin/templates/mediagoblin/edit/edit.html:23
+#: mediagoblin/templates/mediagoblin/edit/edit.html:35
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr ""
+
#: mediagoblin/templates/mediagoblin/edit/edit_account.html:28
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:41
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
#, python-format
msgid "Changing %(username)s's account settings"
msgstr ""
@@ -589,13 +606,12 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:23
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
msgid "Download"
msgstr ""
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:27
msgid "Original"
msgstr ""
@@ -622,6 +638,56 @@ msgstr ""
msgid "WebM file (Vorbis codec)"
msgstr ""
+#: 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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr ""
+
+#: 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 ""
+
+#: 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:40
msgid ""
"Sorry, this video will not work because \n"
@@ -646,7 +712,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
#: mediagoblin/templates/mediagoblin/submit/start.html:34
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:83
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
msgid "Add"
msgstr ""
@@ -675,14 +741,6 @@ msgstr ""
msgid "Delete"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection.html:59
-#, python-format
-msgid ""
-"<p>\n"
-" %(collection_description)s\n"
-" </p>"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
@@ -690,7 +748,7 @@ msgid "Really delete %(title)s?"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
msgstr ""
@@ -699,7 +757,7 @@ msgstr ""
msgid "Really remove %(media_title)s from %(collection_title)s?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
msgid "Remove"
msgstr ""
@@ -725,12 +783,6 @@ msgstr ""
msgid "â– Browsing media by <a href=\"%(user_url)s\">%(username)s</a>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:67
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
-#, python-format
-msgid "Image for %(media_title)s"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
msgid "Add a comment"
msgstr ""
@@ -757,13 +809,8 @@ msgid ""
" <p>%(date)s</p>"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
-msgid "Attachments"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
-msgid "Add attachment"
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
@@ -771,11 +818,11 @@ msgstr ""
msgid "Add %(title)s to collection"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
msgid "+"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
msgid "Add a new collection"
msgstr ""
@@ -846,41 +893,25 @@ msgstr ""
msgid "This user hasn't filled in their profile (yet)."
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:125
-msgid "Change account settings"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:138
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
#, python-format
msgid "View all of %(username)s's media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
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:157
-msgid "Add media"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:163
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:87
-#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:72
+#: 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:39
-#, python-format
-msgid ""
-"<br />\n"
-" <a href=\"%(entry_url)s\">%(note)s</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:47
-#, python-format
-msgid "<br /><a href=\"%(remove_url)s\" class=\"remove\">(remove)</a>"
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
msgstr ""
#: mediagoblin/templates/mediagoblin/utils/collections.html:20
@@ -900,7 +931,7 @@ msgstr ""
msgid "Location"
msgstr ""
-#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:38
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
#, python-format
msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
msgstr ""
@@ -939,6 +970,32 @@ msgstr ""
msgid "Could not read the image file."
msgstr ""
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr ""
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr ""
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr ""
+
+#: mediagoblin/tools/response.py:47
+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:55
+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/user_pages/forms.py:28
msgid "I am sure I want to delete this"
msgstr ""
@@ -959,74 +1016,74 @@ msgstr ""
msgid "commented on your post"
msgstr ""
-#: mediagoblin/user_pages/views.py:161
+#: mediagoblin/user_pages/views.py:156
msgid "Oops, your comment was empty."
msgstr ""
-#: mediagoblin/user_pages/views.py:167
+#: mediagoblin/user_pages/views.py:162
msgid "Your comment has been posted!"
msgstr ""
-#: mediagoblin/user_pages/views.py:235
+#: mediagoblin/user_pages/views.py:230
msgid "You have to select or add a collection"
msgstr ""
-#: mediagoblin/user_pages/views.py:243
+#: mediagoblin/user_pages/views.py:238
#, python-format
msgid "\"%s\" already in collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:258
+#: mediagoblin/user_pages/views.py:253
#, python-format
msgid "\"%s\" added to collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:266
+#: mediagoblin/user_pages/views.py:261
msgid "Please check your entries and try again."
msgstr ""
-#: mediagoblin/user_pages/views.py:297
+#: mediagoblin/user_pages/views.py:292
msgid ""
"Some of the files with this entry seem to be missing. Deleting anyway."
msgstr ""
-#: mediagoblin/user_pages/views.py:302
+#: mediagoblin/user_pages/views.py:297
msgid "You deleted the media."
msgstr ""
-#: mediagoblin/user_pages/views.py:309
+#: mediagoblin/user_pages/views.py:304
msgid "The media was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:317
+#: mediagoblin/user_pages/views.py:312
msgid "You are about to delete another user's media. Proceed with caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
msgstr ""
-#: mediagoblin/user_pages/views.py:383
+#: 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:393
+#: mediagoblin/user_pages/views.py:384
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
msgstr ""
-#: mediagoblin/user_pages/views.py:426
+#: mediagoblin/user_pages/views.py:417
#, python-format
msgid "You deleted the collection \"%s\""
msgstr ""
-#: mediagoblin/user_pages/views.py:433
+#: mediagoblin/user_pages/views.py:424
msgid ""
"The collection was not deleted because you didn't check that you were sure."
msgstr ""
-#: mediagoblin/user_pages/views.py:443
+#: mediagoblin/user_pages/views.py:434
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 379f1bdc..13346b7c 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 b8673f51..4a722732 100644
--- a/mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.po
@@ -4,13 +4,14 @@
#
# Translators:
# <chc@citi.sinica.edu.tw>, 2011.
-# Harry Chen <harryhow@gmail.com>, 2011, 2012.
+# Harry Chen <harryhow@gmail.com>, 2011-2012.
+# <medicalwei@gmail.com>, 2012.
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://issues.mediagoblin.org/\n"
-"POT-Creation-Date: 2012-09-24 14:01-0500\n"
-"PO-Revision-Date: 2012-09-24 18:57+0000\n"
+"POT-Creation-Date: 2012-12-20 09:18-0600\n"
+"PO-Revision-Date: 2012-12-20 15:14+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
@@ -30,11 +31,11 @@ msgstr "密碼"
#: mediagoblin/auth/forms.py:34
msgid "Email address"
-msgstr "é›»å­éƒµä»¶ä½ç½®"
+msgstr "Email ä½å€"
#: mediagoblin/auth/forms.py:51
msgid "Username or email"
-msgstr "使用者å稱或是電å­éƒµä»¶"
+msgstr "使用者å稱或 email"
#: mediagoblin/auth/forms.py:58
msgid "Incorrect input"
@@ -42,48 +43,48 @@ msgstr "輸入錯誤"
#: mediagoblin/auth/views.py:55
msgid "Sorry, registration is disabled on this instance."
-msgstr "抱歉, 這個項目已經被暫åœè¨»å†Š."
+msgstr "抱歉,本站已經暫åœè¨»å†Šã€‚"
#: mediagoblin/auth/views.py:75
msgid "Sorry, a user with that name already exists."
-msgstr "抱歉, 這個使用者å稱已經存在."
+msgstr "抱歉,這個使用者å稱已經存在。"
#: mediagoblin/auth/views.py:79
msgid "Sorry, a user with that email address already exists."
-msgstr "抱歉,此電å­éƒµä»¶å·²è¢«è¨»å†Šäº†ã€‚"
+msgstr "抱歉,此 email ä½ç½®å·²ç¶“被註冊了。"
#: mediagoblin/auth/views.py:182
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
-msgstr "你的電å­éƒµä»¶ä½å€å·²è¢«èªè­‰. ä½ ç¾åœ¨å°±å¯ä»¥ç™»å…¥, 編輯你的個人檔案而且éžäº¤ç…§ç‰‡!"
+msgstr "您的 email ä½å€å·²è¢«èªè­‰ã€‚您已經å¯ä»¥ç™»å…¥ï¼Œç·¨è¼¯æ‚¨çš„個人檔案並上傳圖片ï¼"
#: mediagoblin/auth/views.py:188
msgid "The verification key or user id is incorrect"
-msgstr "èªè­‰ç¢¼æˆ–是使用者帳號錯誤"
+msgstr "èªè­‰ç¢¼æˆ–是使用者 ID 錯誤"
#: mediagoblin/auth/views.py:206
msgid "You must be logged in so we know who to send the email to!"
-msgstr "你必須登入,我們æ‰çŸ¥é“ä¿¡è¦é€çµ¦èª°ï¼"
+msgstr "您必須登入,我們æ‰çŸ¥é“ä¿¡è¦é€çµ¦èª°ï¼"
#: mediagoblin/auth/views.py:214
msgid "You've already verified your email address!"
-msgstr "你的電å­éƒµä»¶å·²ç¶“確èªäº†ï¼"
+msgstr "您的電å­éƒµä»¶å·²ç¶“確èªäº†ï¼"
#: mediagoblin/auth/views.py:227
msgid "Resent your verification email."
-msgstr "é‡é€èªè­‰ä¿¡."
+msgstr "é‡é€èªè­‰ä¿¡ã€‚"
#: mediagoblin/auth/views.py:263
msgid ""
"An email has been sent with instructions on how to change your password."
-msgstr "修改密碼的指示已經由電å­éƒµä»¶å¯„é€åˆ°ä½ çš„信箱。"
+msgstr "修改密碼的指示已經由電å­éƒµä»¶å¯„é€åˆ°æ‚¨çš„信箱。"
#: mediagoblin/auth/views.py:273
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
-msgstr "無法傳é€å¯†ç¢¼å›žå¾©ä¿¡ä»¶ï¼Œå› ç‚ºä½ çš„使用者å稱已失效或是帳號尚未èªè­‰ã€‚"
+msgstr "無法傳é€å¯†ç¢¼å›žå¾©ä¿¡ä»¶ï¼Œå› ç‚ºæ‚¨çš„使用者å稱已失效或是帳號尚未èªè­‰ã€‚"
#: mediagoblin/auth/views.py:285
msgid "Couldn't find someone with that username or email."
@@ -91,9 +92,9 @@ msgstr "找ä¸åˆ°ç›¸é—œçš„使用者å稱或是電å­éƒµä»¶ã€‚"
#: mediagoblin/auth/views.py:333
msgid "You can now log in using your new password."
-msgstr "ä½ ç¾åœ¨å¯ä»¥ç”¨æ–°çš„密碼登入了ï¼"
+msgstr "您ç¾åœ¨å¯ä»¥ç”¨æ–°çš„密碼登入了ï¼"
-#: mediagoblin/edit/forms.py:25 mediagoblin/edit/forms.py:83
+#: 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:40
msgid "Title"
@@ -104,13 +105,13 @@ msgid "Description of this work"
msgstr "這個作å“çš„æè¿°"
#: mediagoblin/edit/forms.py:29 mediagoblin/edit/forms.py:52
-#: mediagoblin/edit/forms.py:87 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:44
msgid ""
"You can use\n"
" <a href=\"http://daringfireball.net/projects/markdown/basics\">\n"
" Markdown</a> for formatting."
-msgstr "ä½ å¯ä»¥ç”¨\n <a href=\"http://daringfireball.net/projects/markdown/basics\">\n Markdown</a> 來排版."
+msgstr "您å¯ä»¥ç”¨ <a href=\"http://markdown.tw\">Markdown</a> 來排版。"
#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:36
msgid "Tags"
@@ -120,19 +121,19 @@ msgstr "標籤"
msgid "Separate tags by commas."
msgstr "用逗號分隔標籤。"
-#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:91
+#: mediagoblin/edit/forms.py:38 mediagoblin/edit/forms.py:90
msgid "Slug"
-msgstr "自訂字串"
+msgstr "簡稱"
-#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:92
+#: mediagoblin/edit/forms.py:39 mediagoblin/edit/forms.py:91
msgid "The slug can't be empty"
-msgstr "自訂字串ä¸èƒ½ç©ºç™½"
+msgstr "簡稱ä¸èƒ½ç‚ºç©ºç™½"
#: mediagoblin/edit/forms.py:40
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
@@ -149,7 +150,7 @@ msgstr "網站"
#: mediagoblin/edit/forms.py:58
msgid "This address contains errors"
-msgstr "ç¶²å€æ˜¯ä¸æ˜¯æ‰“錯了? "
+msgstr "本網å€å‡ºéŒ¯äº†"
#: mediagoblin/edit/forms.py:63
msgid "Old password"
@@ -157,127 +158,132 @@ msgstr "舊的密碼"
#: mediagoblin/edit/forms.py:64
msgid "Enter your old password to prove you own this account."
-msgstr "è¼¸å…¥ä½ çš„èˆŠå¯†ç¢¼ä¾†è­‰æ˜Žä½ æ“æœ‰é€™å€‹å¸³è™Ÿã€‚"
+msgstr "è¼¸å…¥æ‚¨çš„èˆŠå¯†ç¢¼ä¾†è­‰æ˜Žæ‚¨æ“æœ‰é€™å€‹å¸³è™Ÿã€‚"
#: mediagoblin/edit/forms.py:67
msgid "New password"
msgstr "新密碼"
-#: mediagoblin/edit/forms.py:72
+#: mediagoblin/edit/forms.py:71
msgid "Email me when others comment on my media"
-msgstr ""
+msgstr "ç•¶æœ‰äººå°æˆ‘的媒體評論時寄信給我"
-#: mediagoblin/edit/forms.py:84
+#: mediagoblin/edit/forms.py:83
msgid "The title can't be empty"
-msgstr ""
+msgstr "標題ä¸èƒ½æ˜¯ç©ºçš„"
-#: mediagoblin/edit/forms.py:86 mediagoblin/submit/forms.py:50
+#: mediagoblin/edit/forms.py:85 mediagoblin/submit/forms.py:50
#: mediagoblin/user_pages/forms.py:43
msgid "Description of this collection"
-msgstr ""
+msgstr "這個è’è—çš„æè¿°"
-#: mediagoblin/edit/forms.py:93
+#: 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/views.py:65
msgid "An entry with that slug already exists for this user."
-msgstr "這個自訂字串已經被其他人用了"
+msgstr "這個簡稱已經被其他人用了"
#: mediagoblin/edit/views.py:86
msgid "You are editing another user's media. Proceed with caution."
-msgstr "你正在編輯他人的媒體檔案. 請謹慎處ç†."
+msgstr "您正在修改別人的媒體,請å°å¿ƒæ“作。"
+
+#: mediagoblin/edit/views.py:156
+#, python-format
+msgid "You added the attachment %s!"
+msgstr "您加上了附件「%sã€ï¼"
-#: mediagoblin/edit/views.py:182
+#: mediagoblin/edit/views.py:181
msgid "You are editing a user's profile. Proceed with caution."
-msgstr "你正在編輯一ä½ç”¨æˆ¶çš„æª”案. 請謹慎處ç†."
+msgstr "您正在修改別人的個人檔案,請å°å¿ƒæ“作。"
-#: mediagoblin/edit/views.py:198
+#: mediagoblin/edit/views.py:197
msgid "Profile changes saved"
-msgstr "修改的檔案已存檔"
+msgstr "個人檔案修改已儲存"
-#: mediagoblin/edit/views.py:227 mediagoblin/edit/views.py:247
+#: mediagoblin/edit/views.py:226 mediagoblin/edit/views.py:246
msgid "Account settings saved"
-msgstr "帳號設定已存檔"
+msgstr "帳號設定已儲存"
-#: mediagoblin/edit/views.py:252
+#: mediagoblin/edit/views.py:251
msgid "Wrong password"
msgstr "密碼錯誤"
-#: mediagoblin/edit/views.py:288 mediagoblin/submit/views.py:211
-#: mediagoblin/user_pages/views.py:215
+#: mediagoblin/edit/views.py:287 mediagoblin/submit/views.py:211
+#: mediagoblin/user_pages/views.py:210
#, python-format
msgid "You already have a collection called \"%s\"!"
-msgstr ""
+msgstr "您已經有一個稱åšã€Œ%sã€çš„è’è—了ï¼"
-#: mediagoblin/edit/views.py:292
+#: mediagoblin/edit/views.py:291
msgid "A collection with that slug already exists for this user."
-msgstr ""
+msgstr "這個使用者已經有使用該簡稱的è’è—了。"
-#: mediagoblin/edit/views.py:309
+#: mediagoblin/edit/views.py:308
msgid "You are editing another user's collection. Proceed with caution."
-msgstr ""
+msgstr "您正在修改別人的è’è—,請å°å¿ƒæ“作。"
#: mediagoblin/gmg_commands/theme.py:58
msgid "Cannot link theme... no theme set\n"
-msgstr ""
+msgstr "無法連çµä½ˆæ™¯â€¦æ²’有此佈景\n"
#: mediagoblin/gmg_commands/theme.py:71
msgid "No asset directory for this theme\n"
-msgstr ""
+msgstr "此佈景沒有素æç›®éŒ„\n"
#: mediagoblin/gmg_commands/theme.py:74
msgid "However, old link directory symlink found; removed.\n"
-msgstr ""
+msgstr "但是舊的目錄連çµå·²ç¶“找到並移除。\n"
#: mediagoblin/media_types/__init__.py:60
-#: mediagoblin/media_types/__init__.py:120
+#: mediagoblin/media_types/__init__.py:101
msgid "Sorry, I don't support that file type :("
msgstr "æŠ±æ­‰ï¼Œæˆ‘ä¸æ”¯æ´é€™æ¨£çš„æª”æ¡ˆæ ¼å¼ :("
#: mediagoblin/media_types/video/processing.py:35
msgid "Video transcoding failed"
-msgstr ""
+msgstr "å½±åƒè½‰ç¢¼å¤±æ•—"
#: mediagoblin/plugins/oauth/forms.py:26
msgid "Client ID"
-msgstr ""
+msgstr "客戶 ID"
#: mediagoblin/plugins/oauth/forms.py:28
msgid "Next URL"
-msgstr ""
+msgstr "下一個 URL"
#: mediagoblin/plugins/oauth/forms.py:30
msgid "Allow"
-msgstr ""
+msgstr "å…許"
#: mediagoblin/plugins/oauth/forms.py:31
msgid "Deny"
-msgstr ""
+msgstr "拒絕"
#: mediagoblin/plugins/oauth/forms.py:35
msgid "Name"
-msgstr ""
+msgstr "å稱"
#: mediagoblin/plugins/oauth/forms.py:36
msgid "The name of the OAuth client"
-msgstr ""
+msgstr "OAuth client çš„å稱"
#: mediagoblin/plugins/oauth/forms.py:37
msgid "Description"
-msgstr ""
+msgstr "æè¿°"
#: mediagoblin/plugins/oauth/forms.py:39
msgid ""
"This will be visible to users allowing your\n"
" application to authenticate as them."
-msgstr ""
+msgstr "本æè¿°å°‡æœƒè¢«é€²è¡Œæ‡‰ç”¨ç¨‹å¼èªè¨¼çš„使用者看到。"
#: mediagoblin/plugins/oauth/forms.py:41
msgid "Type"
-msgstr ""
+msgstr "類型"
#: mediagoblin/plugins/oauth/forms.py:46
msgid ""
@@ -287,25 +293,25 @@ 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> — OAuth client å¯ä»¥å° GNU MediaGoblin ç«™å°ç™¼é€ä¸è¢«ä½¿ç”¨è€…ä»£ç†æ””截的請求 (例如伺æœç«¯çš„ client)。\n<strong>公開</strong> — OAuth client ç„¡æ³•å° GNU MediaGoblin ç«™å°ç™¼é€ç§˜å¯†çš„請求 (例如客戶端的 JavaScript client)。"
#: mediagoblin/plugins/oauth/forms.py:53
msgid "Redirect URI"
-msgstr ""
+msgstr "é‡å®šå‘ URI"
#: mediagoblin/plugins/oauth/forms.py:55
msgid ""
"The redirect URI for the applications, this field\n"
" is <strong>required</strong> for public clients."
-msgstr ""
+msgstr "此應用程å¼çš„é‡å®šå‘ URI,本欄ä½åœ¨å…¬é–‹é¡žåž‹çš„ OAuth client 為必填。"
#: mediagoblin/plugins/oauth/forms.py:67
msgid "This field is required for public clients"
-msgstr ""
+msgstr "本欄ä½åœ¨å…¬é–‹é¡žåž‹çš„ OAuth client 為必填"
-#: mediagoblin/plugins/oauth/views.py:59
+#: mediagoblin/plugins/oauth/views.py:60
msgid "The client {0} has been registered!"
-msgstr ""
+msgstr "OAuth client {0} 註冊完æˆï¼"
#: mediagoblin/processing/__init__.py:138
msgid "Invalid file given for media type."
@@ -317,127 +323,126 @@ msgstr "檔案"
#: mediagoblin/submit/views.py:57
msgid "You must provide a file."
-msgstr "ä½ å¿…é ˆæä¾›ä¸€å€‹æª”案"
+msgstr "您必須æä¾›ä¸€å€‹æª”案"
#: mediagoblin/submit/views.py:164
msgid "Woohoo! Submitted!"
-msgstr "呼呼! é€å‡ºåŽ»åš•!"
+msgstr "啊哈ï¼PO 上去啦ï¼"
#: mediagoblin/submit/views.py:215
#, python-format
msgid "Collection \"%s\" added!"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/404.html:24
-msgid "Image of 404 goblin stressing out"
-msgstr "Image of 404 goblin stressing out"
-
-#: mediagoblin/templates/mediagoblin/404.html:25
-msgid "Oops!"
-msgstr "糟糕ï¼"
-
-#: mediagoblin/templates/mediagoblin/404.html:26
-msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr "這個ä½å€ä¼¼ä¹Žæ²’有網é ã€‚抱歉ï¼"
-
-#: mediagoblin/templates/mediagoblin/404.html:28
-msgid ""
-"If you're sure the address is correct, maybe the page you're looking for has"
-" been moved or deleted."
-msgstr "如果你確定這個ä½å€æ˜¯æ­£ç¢ºçš„,或許你在找的網é å·²ç¶“被移除或是刪除了。"
+msgstr "è’è—「%sã€æ–°å¢žå®Œæˆï¼"
-#: mediagoblin/templates/mediagoblin/base.html:50
+#: mediagoblin/templates/mediagoblin/base.html:48
msgid "MediaGoblin logo"
msgstr "MediaGoblin 標誌"
-#: mediagoblin/templates/mediagoblin/base.html:60
-msgid "Verify your email!"
-msgstr "確èªä½ çš„é›»å­éƒµä»¶"
-
-#: mediagoblin/templates/mediagoblin/base.html:66
-msgid "+ Add media"
-msgstr "+ 加入媒體"
+#: mediagoblin/templates/mediagoblin/base.html:54
+#, 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:67
-msgid "+ Add collection"
-msgstr ""
+#: mediagoblin/templates/mediagoblin/base.html:60
+msgid "log out"
+msgstr "登出"
-#: mediagoblin/templates/mediagoblin/base.html:69
-msgid "View your profile"
-msgstr "檢視你個人檔案"
+#: mediagoblin/templates/mediagoblin/base.html:62
+#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+msgid "Add media"
+msgstr "新增媒體"
-#: mediagoblin/templates/mediagoblin/base.html:70
-msgid "Log out"
-msgstr "登出"
+#: mediagoblin/templates/mediagoblin/base.html:68
+msgid "Verify your email!"
+msgstr "ç¢ºèªæ‚¨çš„é›»å­éƒµä»¶"
-#: mediagoblin/templates/mediagoblin/base.html:75
+#: 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:89
+#: mediagoblin/templates/mediagoblin/base.html:87
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project."
-msgstr "由 <a href=\"http://mediagoblin.org\">MediaGoblin</a>製作, 它是一個 <a href=\"http://gnu.org/\">GNU</a> 專案"
+msgstr "基於 <a href=\"http://mediagoblin.org\">MediaGoblin</a> — 一項 <a href=\"http://gnu.org/\">GNU</a> 專案。"
-#: mediagoblin/templates/mediagoblin/base.html:92
+#: mediagoblin/templates/mediagoblin/base.html:90
#, 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>."
+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:25
+msgid "Actions"
+msgstr "動作"
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid "Create new collection"
+msgstr "新增新的è’è—"
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid "Change account settings"
+msgstr "更改帳號設定"
-#: mediagoblin/templates/mediagoblin/root.html:24
+#: mediagoblin/templates/mediagoblin/root.html:38
+#: mediagoblin/templates/mediagoblin/root.html:44
+#: 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/root.html:51
msgid "Explore"
msgstr "探索"
-#: mediagoblin/templates/mediagoblin/root.html:26
+#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Hi there, welcome to this MediaGoblin site!"
-msgstr "å˜¿ï¼æ­¡è¿Žä¾†åˆ° 媒體怪ç¸(MediaGoblin) 網站"
+msgstr "å˜¿ï¼æ­¡è¿Žä¾†åˆ° MediaGoblin ç«™å°ï¼ "
-#: mediagoblin/templates/mediagoblin/root.html:28
+#: mediagoblin/templates/mediagoblin/root.html:55
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>, 他是一個超讚的媒體分享架站軟體."
+msgstr "本站使用 <a href=\"http://mediagoblin.org\">MediaGoblin</a> — 與眾ä¸åŒçš„媒體分享網站。"
-#: mediagoblin/templates/mediagoblin/root.html:29
+#: mediagoblin/templates/mediagoblin/root.html:56
msgid ""
"To add your own media, place comments, and more, you can log in with your "
"MediaGoblin account."
-msgstr ""
+msgstr "您å¯ä»¥ç™»å…¥æ‚¨çš„ MediaGoblin 帳號以進行上傳媒體ã€å¼µè²¼è©•論等等。"
-#: mediagoblin/templates/mediagoblin/root.html:31
+#: mediagoblin/templates/mediagoblin/root.html:58
msgid "Don't have one yet? It's easy!"
-msgstr "還沒有嗎?其實éžå¸¸ç°¡å–®ï¼"
+msgstr "沒有帳號嗎?開帳號很簡單ï¼"
-#: mediagoblin/templates/mediagoblin/root.html:32
+#: mediagoblin/templates/mediagoblin/root.html:59
#, 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\">在你的伺æœå™¨ä¸Šå»ºç«‹ä¸€å€‹è‡ªå·±çš„媒體怪ç¸(MedaiGoblin)</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:40
+#: mediagoblin/templates/mediagoblin/root.html:67
msgid "Most recent media"
msgstr "最新的媒體"
-#: 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/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
@@ -452,26 +457,26 @@ msgstr "沒有正在處ç†ä¸­çš„媒體"
#: mediagoblin/templates/mediagoblin/admin/panel.html:61
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:59
msgid "These uploads failed to process:"
-msgstr "無法處ç†é€™äº›æ›´æ–°"
+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"
@@ -498,7 +503,7 @@ msgid ""
"\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如果你èªç‚ºé€™å€‹æ˜¯å€‹èª¤æœƒï¼Œè«‹å¿½ç•¥æ­¤å°ä¿¡ä»¶ï¼Œç¹¼çºŒç•¶å€‹å¿«æ¨‚çš„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!"
@@ -506,11 +511,11 @@ msgstr "登入失敗ï¼"
#: mediagoblin/templates/mediagoblin/auth/login.html:44
msgid "Don't have an account yet?"
-msgstr "還沒有帳號嗎?"
+msgstr "還沒有帳號嗎?"
#: mediagoblin/templates/mediagoblin/auth/login.html:45
msgid "Create one here!"
-msgstr "在這裡建立一個å§!"
+msgstr "在這裡建立一個å§ï¼"
#: mediagoblin/templates/mediagoblin/auth/login.html:51
msgid "Forgot your password?"
@@ -519,7 +524,7 @@ 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"
@@ -534,52 +539,65 @@ msgid ""
"your web browser:\n"
"\n"
"%(verification_url)s"
-msgstr "å—¨ %(username)s,\n\n啟動 GNU MediaGoblin 帳號, 在你的ç€è¦½å™¨ä¸­æ‰“開下é¢çš„ç¶²å€:\n\n%(verification_url)s"
+msgstr "%(username)s 您好:\n\nè¦å•Ÿå‹• GNU MediaGoblin 帳號,請在您的ç€è¦½å™¨ä¸­æ‰“開下é¢çš„ç¶²å€:\n\n%(verification_url)s"
#: mediagoblin/templates/mediagoblin/edit/attachments.html:23
#: 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/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/attachments.html:43
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
+msgid "Attachments"
+msgstr "附件"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:56
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
+msgid "Add attachment"
+msgstr "新增附件"
+
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:60
+#: 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:53
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:81
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:48
msgid "Cancel"
msgstr "å–æ¶ˆ"
-#: mediagoblin/templates/mediagoblin/edit/edit.html:43
-#: mediagoblin/templates/mediagoblin/edit/edit_account.html:47
+#: mediagoblin/templates/mediagoblin/edit/attachments.html:62
+#: mediagoblin/templates/mediagoblin/edit/edit.html:42
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:51
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:33
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:41
msgid "Save changes"
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:41
+#: mediagoblin/templates/mediagoblin/edit/edit_account.html:40
#, python-format
msgid "Changing %(username)s's account settings"
-msgstr "正在改變 %(username)s的帳號設定"
+msgstr "正在改變 %(username)s 的帳號設定"
#: mediagoblin/templates/mediagoblin/edit/edit_collection.html:29
#, python-format
msgid "Editing %(collection_title)s"
-msgstr ""
+msgstr "編輯 %(collection_title)s"
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:23
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
#, python-format
msgid "Editing %(username)s's profile"
-msgstr "編輯 %(username)s'的檔案中"
+msgstr "編輯 %(username)s 的個人檔案"
#: mediagoblin/templates/mediagoblin/listings/collection.html:30
#: mediagoblin/templates/mediagoblin/listings/collection.html:35
@@ -587,85 +605,134 @@ msgstr "編輯 %(username)s'的檔案中"
#: mediagoblin/templates/mediagoblin/listings/tag.html:35
#, python-format
msgid "Media tagged with: %(tag_name)s"
-msgstr "此媒體被標識為:%(tag_name)s"
+msgstr "此媒體被 tag æˆï¼š%(tag_name)s"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:34
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:56
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:23
+#: mediagoblin/templates/mediagoblin/media_displays/stl.html:136
#: mediagoblin/templates/mediagoblin/media_displays/video.html:52
msgid "Download"
msgstr "下載"
#: mediagoblin/templates/mediagoblin/media_displays/ascii.html:38
-#: mediagoblin/templates/mediagoblin/media_displays/image.html:27
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 "抱歉,此è²éŸ³æª”案無法播放,因為你的ç€è¦½å™¨ä¸æ”¯æ´HTML5音訊。"
+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\">\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/video.html:56
msgid "Original file"
-msgstr ""
+msgstr "原始檔案"
#: mediagoblin/templates/mediagoblin/media_displays/audio.html:63
msgid "WebM file (Vorbis codec)"
-msgstr "WebM 檔案 (Vorbis codec)"
+msgstr "WebM 檔案 (Vorbis 編碼)"
+
+#: 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:67
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
+#, python-format
+msgid "Image for %(media_title)s"
+msgstr " %(media_title)s 的照片"
+
+#: 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:40
msgid ""
"Sorry, this video will not work because \n"
"\t your web browser does not support HTML5 \n"
"\t video."
-msgstr "抱歉, 此影片無法使用,因為 \n<span class=\"whitespace other\" title=\"Tab\">»</span> ä½ çš„ç€è¦½å™¨ä¸æ”¯æ´ HTML5 \n<span class=\"whitespace other\" title=\"Tab\">»</span> 的影片."
+msgstr "抱歉,此影片無法使用,因為您的ç€è¦½å™¨ä¸æ”¯æ´ HTML5 的影片."
#: mediagoblin/templates/mediagoblin/media_displays/video.html:43
msgid ""
"You can get a modern web browser that \n"
"\t can play this video at <a href=\"http://getfirefox.com\">\n"
"\t http://getfirefox.com</a>!"
-msgstr "ä½ å¯ä»¥å–å¾—\n<span class=\"whitespace other\" title=\"Tab\">»</span> 播放這樣檔案的最新ç€è¦½å™¨ <a href=\"http://getfirefox.com\">\n<span class=\"whitespace other\" title=\"Tab\">»</span> http://getfirefox.com</a>!"
+msgstr "您å¯ä»¥åœ¨ <a href=\"http://getfirefox.com\">http://getfirefox.com</a> å–å¾—å¯ä»¥æ’­æ”¾æ­¤å½±ç‰‡çš„ç€è¦½å™¨ï¼"
#: mediagoblin/templates/mediagoblin/media_displays/video.html:59
msgid "WebM file (640p; VP8/Vorbis)"
-msgstr ""
+msgstr "WebM 檔案 (640p; VP8/Vorbis)"
#: mediagoblin/templates/mediagoblin/submit/collection.html:26
msgid "Add a collection"
-msgstr ""
+msgstr "新增è’è—"
#: mediagoblin/templates/mediagoblin/submit/collection.html:30
#: mediagoblin/templates/mediagoblin/submit/start.html:34
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:83
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:82
msgid "Add"
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 çš„è’è—)"
#: 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 by <a href=\"%(user_url)s\">%(username)s</a>"
#: mediagoblin/templates/mediagoblin/user_pages/collection.html:52
#: mediagoblin/templates/mediagoblin/user_pages/media.html:87
@@ -677,14 +744,6 @@ msgstr "編輯"
msgid "Delete"
msgstr "刪除"
-#: mediagoblin/templates/mediagoblin/user_pages/collection.html:59
-#, python-format
-msgid ""
-"<p>\n"
-" %(collection_description)s\n"
-" </p>"
-msgstr ""
-
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:30
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
@@ -692,25 +751,25 @@ msgid "Really delete %(title)s?"
msgstr "真的è¦åˆªé™¤ %(title)s?"
#: mediagoblin/templates/mediagoblin/user_pages/collection_confirm_delete.html:47
-#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Delete permanently"
-msgstr "æ°¸é åˆªé™¤"
+msgstr "永久刪除"
#: 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 "確定è¦å¾ž %(collection_title)s 移除 %(media_title)s 嗎?"
-#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:54
+#: mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html:53
msgid "Remove"
-msgstr ""
+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 ""
+msgstr "%(username)s 您好:\n%(comment_author)s 在 %(instance_name)s å°æ‚¨çš„內容 (%(comment_url)s) 張貼評論\n"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30
#, python-format
@@ -720,18 +779,12 @@ msgstr "%(username)s的媒體"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:37
#, python-format
msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media"
-msgstr "<a href=\"%(user_url)s\">%(username)s</a>的媒體檔案"
+msgstr "<a href=\"%(user_url)s\">%(username)s</a> 的媒體"
#: mediagoblin/templates/mediagoblin/user_pages/media.html:46
#, 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:67
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:73
-#, python-format
-msgid "Image for %(media_title)s"
-msgstr " %(media_title)s的照片"
+msgstr "â– ç€è¦½ <a href=\"%(user_url)s\">%(username)s</a> 的媒體"
#: mediagoblin/templates/mediagoblin/user_pages/media.html:102
msgid "Add a comment"
@@ -742,11 +795,11 @@ msgid ""
"You can use <a "
"href=\"http://daringfireball.net/projects/markdown/basics\">Markdown</a> for"
" formatting."
-msgstr "ä½ å¯ä»¥ç”¨ <a href=\"http://daringfireball.net/projects/markdown/basics\"> Markdown</a> 來排版."
+msgstr "您å¯ä»¥ç”¨ <a href=\"http://markdown.tw\">Markdown</a> 來排版。"
#: mediagoblin/templates/mediagoblin/user_pages/media.html:113
msgid "Add this comment"
-msgstr "增加此評論"
+msgstr "增加評論"
#: mediagoblin/templates/mediagoblin/user_pages/media.html:132
msgid "at"
@@ -759,46 +812,41 @@ msgid ""
" <p>%(date)s</p>"
msgstr "<h3>加入日期</h3>\n <p>%(date)s</p>"
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:171
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:187
-msgid "Attachments"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/user_pages/media.html:192
-msgid "Add attachment"
-msgstr ""
+#: mediagoblin/templates/mediagoblin/user_pages/media.html:202
+msgid "Add media to collection"
+msgstr "將媒體加入è’è—"
#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:35
#, python-format
msgid "Add %(title)s to collection"
-msgstr ""
+msgstr "新增 %(title)s 到è’è—"
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:51
msgid "+"
-msgstr ""
+msgstr "+"
-#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:57
+#: mediagoblin/templates/mediagoblin/user_pages/media_collect.html:56
msgid "Add a new collection"
-msgstr ""
+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 "é‡å°ä½ çš„展示å€ï¼Œä½ å¯ä»¥åœ¨é€™è£¡è¿½è¹¤åª’體處ç†çš„狀態。"
+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
#, python-format
msgid "%(username)s's profile"
-msgstr "%(username)s的個人檔案"
+msgstr "%(username)s 的個人檔案"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:43
msgid "Sorry, no such user found."
-msgstr "抱歉,找ä¸åˆ°é€™å€‹ä½¿ç”¨è€…."
+msgstr "抱歉,找ä¸åˆ°é€™å€‹ä½¿ç”¨è€…。"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:50
#: mediagoblin/templates/mediagoblin/user_pages/user.html:70
@@ -807,16 +855,16 @@ msgstr "需è¦èªè­‰é›»å­éƒµä»¶"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:53
msgid "Almost done! Your account still needs to be activated."
-msgstr "幾乎完æˆäº†ï¼ä½†ä½ çš„帳號ä»ç„¶éœ€è¦è¢«å•Ÿç”¨ã€‚"
+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 "馬上會有一å°é›»å­éƒµä»¶å‘Šè¨´ä½ å¦‚何åš."
+msgstr "啟用步驟的 email 將會寄到您的信箱。"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:62
msgid "In case it doesn't:"
-msgstr "如果ä»ç„¶ç„¡æ³•èªè­‰ï¼Œä½ å¯ä»¥:"
+msgstr "如果ä»ç„¶ç„¡æ³•èªè­‰ï¼Œæ‚¨å¯ä»¥ï¼š"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:65
msgid "Resend verification email"
@@ -826,18 +874,18 @@ msgstr "é‡é€èªè­‰ä¿¡"
msgid ""
"Someone has registered an account with this username, but it still has to be"
" activated."
-msgstr "有人用了這個帳號登錄了,但是這個帳號ä»éœ€è¦è¢«å•Ÿç”¨ã€‚"
+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> 然後é‡é€ä¸€æ¬¡."
+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 "這個地方能讓你å‘他人介紹自己。"
+msgstr "這個地方能讓您å‘他人介紹自己。"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:101
#: mediagoblin/templates/mediagoblin/user_pages/user.html:118
@@ -846,53 +894,37 @@ msgstr "編輯個人檔案"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:106
msgid "This user hasn't filled in their profile (yet)."
-msgstr "這個使用者還沒(來得åŠ)填寫個人檔案。"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:125
-msgid "Change account settings"
-msgstr "更改帳號設定"
+msgstr "這個使用者(還)沒有填寫個人檔案。"
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:138
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:132
#, python-format
msgid "View all of %(username)s's media"
-msgstr "查看%(username)s的全部媒體檔案"
+msgstr "查看 %(username)s 的全部媒體"
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:151
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:145
msgid ""
"This is where your media will appear, but you don't seem to have added "
"anything yet."
-msgstr "這個地方是你的媒體檔案會出ç¾çš„地方,但是你似乎還沒有加入任何æ±è¥¿ã€‚"
+msgstr "此處是您的媒體會出ç¾çš„地方,但是似乎還沒有加入任何æ±è¥¿ã€‚"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:157
-msgid "Add media"
-msgstr "新增媒體檔案"
-
-#: mediagoblin/templates/mediagoblin/user_pages/user.html:163
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:87
-#: mediagoblin/templates/mediagoblin/utils/object_gallery.html:72
+#: 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 "似乎還沒有任何的媒體檔案..."
+msgstr "那裡好åƒé‚„沒有任何的媒體…"
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:39
-#, python-format
-msgid ""
-"<br />\n"
-" <a href=\"%(entry_url)s\">%(note)s</a>"
-msgstr ""
-
-#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:47
-#, python-format
-msgid "<br /><a href=\"%(remove_url)s\" class=\"remove\">(remove)</a>"
-msgstr ""
+#: mediagoblin/templates/mediagoblin/utils/collection_gallery.html:49
+msgid "(remove)"
+msgstr " (移除)"
#: mediagoblin/templates/mediagoblin/utils/collections.html:20
#, python-format
msgid "In collections (%(collected)s)"
-msgstr ""
+msgstr "在è’è— (%(collected)s)"
#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
msgid "feed icon"
-msgstr "feed圖示"
+msgstr "feed 圖示"
#: mediagoblin/templates/mediagoblin/utils/feed_link.html:23
msgid "Atom feed"
@@ -902,10 +934,10 @@ msgstr "Atom feed"
msgid "Location"
msgstr "ä½ç½®"
-#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:38
+#: mediagoblin/templates/mediagoblin/utils/geolocation_map.html:53
#, python-format
msgid "View on <a href=\"%(osm_url)s\">OpenStreetMap</a>"
-msgstr "在 <a href=\"%(osm_url)s\">OpenStreetMap</a>上觀看"
+msgstr "在 <a href=\"%(osm_url)s\">OpenStreetMap</a> 上觀看"
#: mediagoblin/templates/mediagoblin/utils/license.html:25
msgid "All rights reserved"
@@ -913,11 +945,11 @@ 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:"
@@ -926,109 +958,135 @@ 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:78
msgid "Could not read the image file."
-msgstr "無法讀å–å½±åƒæª”案。"
+msgstr "無法讀å–圖片檔案。"
+
+#: mediagoblin/tools/response.py:30
+msgid "Oops!"
+msgstr "糟糕ï¼"
+
+#: mediagoblin/tools/response.py:31
+msgid "An error occured"
+msgstr "發生錯誤"
+
+#: mediagoblin/tools/response.py:46
+msgid "Operation not allowed"
+msgstr "æ“作ä¸å…許"
+
+#: mediagoblin/tools/response.py:47
+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 "Dave å°ä¸èµ·ï¼Œæˆ‘ä¸èƒ½è®“你這樣åšï¼</p><p>您正在試著æ“作ä¸å…許您使用的功能。您打算刪除所有使用者的帳號嗎?"
+
+#: mediagoblin/tools/response.py:55
+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/user_pages/forms.py:28
msgid "I am sure I want to delete this"
-msgstr "我確定我想è¦åˆªé™¤"
+msgstr "我確定我è¦åˆªé™¤é€™å€‹åª’é«”"
#: mediagoblin/user_pages/forms.py:32
msgid "I am sure I want to remove this item from the collection"
-msgstr ""
+msgstr "我確定我è¦å¾žè’è—中移除此項目"
#: mediagoblin/user_pages/forms.py:35
msgid "-- Select --"
-msgstr ""
+msgstr "— è«‹é¸æ“‡ —"
#: mediagoblin/user_pages/forms.py:37
msgid "Include a note"
-msgstr ""
+msgstr "加註"
#: mediagoblin/user_pages/lib.py:56
msgid "commented on your post"
-msgstr ""
+msgstr "在您的內容張貼評論"
-#: mediagoblin/user_pages/views.py:161
+#: mediagoblin/user_pages/views.py:156
msgid "Oops, your comment was empty."
-msgstr "啊,你的留言是空的。"
+msgstr "啊,您的留言是空的。"
-#: mediagoblin/user_pages/views.py:167
+#: mediagoblin/user_pages/views.py:162
msgid "Your comment has been posted!"
-msgstr "你的留言已經刊登ï¼"
+msgstr "您的留言已經張貼完æˆï¼"
-#: mediagoblin/user_pages/views.py:235
+#: mediagoblin/user_pages/views.py:230
msgid "You have to select or add a collection"
-msgstr ""
+msgstr "您需è¦é¸æ“‡æˆ–是新增一個è’è—"
-#: mediagoblin/user_pages/views.py:243
+#: mediagoblin/user_pages/views.py:238
#, python-format
msgid "\"%s\" already in collection \"%s\""
-msgstr ""
+msgstr "「%sã€å·²ç¶“在「%sã€è’è—"
-#: mediagoblin/user_pages/views.py:258
+#: mediagoblin/user_pages/views.py:253
#, python-format
msgid "\"%s\" added to collection \"%s\""
-msgstr ""
+msgstr "「%sã€åŠ å…¥ã€Œ%sã€è’è—"
-#: mediagoblin/user_pages/views.py:266
+#: mediagoblin/user_pages/views.py:261
msgid "Please check your entries and try again."
-msgstr ""
+msgstr "請檢查項目並é‡è©¦ã€‚"
-#: mediagoblin/user_pages/views.py:297
+#: mediagoblin/user_pages/views.py:292
msgid ""
"Some of the files with this entry seem to be missing. Deleting anyway."
-msgstr ""
+msgstr "在此項目中有些檔案好åƒä¸è¦‹äº†ï¼Œå·²å…ˆè¡Œåˆªé™¤ã€‚"
-#: mediagoblin/user_pages/views.py:302
+#: mediagoblin/user_pages/views.py:297
msgid "You deleted the media."
-msgstr "你已刪除此媒體檔案。"
+msgstr "您已經刪除此媒體。"
-#: mediagoblin/user_pages/views.py:309
+#: mediagoblin/user_pages/views.py:304
msgid "The media was not deleted because you didn't check that you were sure."
-msgstr "此媒體檔案尚未被刪除因為你還沒有確èªä½ çœŸçš„è¦åˆªé™¤ã€‚"
+msgstr "由於您沒有勾é¸ç¢ºèªï¼Œè©²åª’體沒有被移除。"
-#: mediagoblin/user_pages/views.py:317
+#: mediagoblin/user_pages/views.py:312
msgid "You are about to delete another user's media. Proceed with caution."
-msgstr "你在刪除其他人的媒體檔案。請å°å¿ƒè™•ç†å–”。"
+msgstr "您正在刪除別人的媒體,請å°å¿ƒæ“作。"
-#: mediagoblin/user_pages/views.py:379
+#: mediagoblin/user_pages/views.py:370
msgid "You deleted the item from the collection."
-msgstr ""
+msgstr "您已經從該è’è—中刪除該項目。"
-#: mediagoblin/user_pages/views.py:383
+#: 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:393
+#: mediagoblin/user_pages/views.py:384
msgid ""
"You are about to delete an item from another user's collection. Proceed with"
" caution."
-msgstr ""
+msgstr "您正在從別人的è’è—中刪除項目,請å°å¿ƒæ“作。"
-#: mediagoblin/user_pages/views.py:426
+#: mediagoblin/user_pages/views.py:417
#, python-format
msgid "You deleted the collection \"%s\""
-msgstr ""
+msgstr "您已經刪除「%sã€è’è—。"
-#: mediagoblin/user_pages/views.py:433
+#: mediagoblin/user_pages/views.py:424
msgid ""
"The collection was not deleted because you didn't check that you were sure."
-msgstr ""
+msgstr "由於您沒有勾é¸ç¢ºèªï¼Œè©²è’è—æ²’有被移除。"
-#: mediagoblin/user_pages/views.py:443
+#: mediagoblin/user_pages/views.py:434
msgid ""
"You are about to delete another user's collection. Proceed with caution."
-msgstr ""
+msgstr "您正在刪除別人的è’è—,請å°å¿ƒæ“作。"
diff --git a/mediagoblin/init/__init__.py b/mediagoblin/init/__init__.py
index 88af377e..ab6e6399 100644
--- a/mediagoblin/init/__init__.py
+++ b/mediagoblin/init/__init__.py
@@ -19,7 +19,7 @@ from beaker.util import parse_cache_config_options
import jinja2
from mediagoblin.tools import staticdirect
-from mediagoblin.tools.translate import get_available_locales
+from mediagoblin.tools.translate import set_available_locales
from mediagoblin.init.config import (
read_mediagoblin_config, generate_validation_report)
from mediagoblin import mg_globals
@@ -40,7 +40,7 @@ class ImproperlyConfigured(Error):
def setup_locales():
"""Checks which language translations are available and sets them"""
- setup_globals(available_locales=get_available_locales())
+ set_available_locales()
def setup_global_and_app_config(config_path):
@@ -66,15 +66,13 @@ def setup_database():
load_models(app_config)
# Set up the database
- connection, db = setup_connection_and_db_from_config(app_config)
+ db = setup_connection_and_db_from_config(app_config)
check_db_migrations_current(db)
- setup_globals(
- db_connection=connection,
- database=db)
+ setup_globals(database=db)
- return connection, db
+ return db
def get_jinja_loader(user_template_path=None, current_theme=None,
diff --git a/mediagoblin/listings/routing.py b/mediagoblin/listings/routing.py
index d25f1c8c..e5683168 100644
--- a/mediagoblin/listings/routing.py
+++ b/mediagoblin/listings/routing.py
@@ -14,7 +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.routing import add_route
+from mediagoblin.tools.routing import add_route
add_route('mediagoblin.listings.tags_listing',
"/tag/<string:tag>/",
diff --git a/mediagoblin/listings/views.py b/mediagoblin/listings/views.py
index a8824390..d37161fc 100644
--- a/mediagoblin/listings/views.py
+++ b/mediagoblin/listings/views.py
@@ -14,8 +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/>.
-from mediagoblin.db.util import media_entries_for_tag_slug, DESCENDING
-
+from mediagoblin.db.models import MediaEntry
+from mediagoblin.db.util import media_entries_for_tag_slug
from mediagoblin.tools.pagination import Pagination
from mediagoblin.tools.response import render_to_response
from mediagoblin.decorators import uses_pagination
@@ -36,10 +36,6 @@ def _get_tag_name_from_entries(media_entries, tag_slug):
tag_name = tag['name']
break
break
- # TODO: Remove after SQL-switch, it's mongo specific
- if hasattr(media_entries, "rewind"):
- media_entries.rewind()
-
return tag_name
@@ -49,7 +45,7 @@ def tag_listing(request, page):
tag_slug = request.matchdict[u'tag']
cursor = media_entries_for_tag_slug(request.db, tag_slug)
- cursor = cursor.sort('created', DESCENDING)
+ cursor = cursor.order_by(MediaEntry.created.desc())
pagination = Pagination(page, cursor)
media_entries = pagination()
@@ -75,7 +71,7 @@ def tag_atom_feed(request):
tag_slug = request.matchdict[u'tag']
cursor = media_entries_for_tag_slug(request.db, tag_slug)
- cursor = cursor.sort('created', DESCENDING)
+ cursor = cursor.order_by(MediaEntry.created.desc())
cursor = cursor.limit(ATOM_DEFAULT_NR_OF_UPDATED_ITEMS)
"""
diff --git a/mediagoblin/meddleware/csrf.py b/mediagoblin/meddleware/csrf.py
index 1488e6d9..661f0ba2 100644
--- a/mediagoblin/meddleware/csrf.py
+++ b/mediagoblin/meddleware/csrf.py
@@ -17,11 +17,12 @@
import random
import logging
-from webob.exc import HTTPForbidden
+from werkzeug.exceptions import Forbidden
from wtforms import Form, HiddenField, validators
from mediagoblin import mg_globals
from mediagoblin.meddleware import BaseMeddleware
+from mediagoblin.tools.translate import lazy_pass_to_ugettext as _
_log = logging.getLogger(__name__)
@@ -127,9 +128,13 @@ class CsrfMeddleware(BaseMeddleware):
None)
if cookie_token is None:
- # the CSRF cookie must be present in the request
+ # the CSRF cookie must be present in the request, if not a
+ # cookie blocker might be in action (in the best case)
_log.error('CSRF cookie not present')
- return HTTPForbidden()
+ raise Forbidden(_('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.'))
# get the form token and confirm it matches
form = CsrfForm(request.form)
@@ -142,5 +147,6 @@ class CsrfMeddleware(BaseMeddleware):
# either the tokens didn't match or the form token wasn't
# present; either way, the request is denied
- _log.error('CSRF validation failed')
- return HTTPForbidden()
+ errstr = 'CSRF validation failed'
+ _log.error(errstr)
+ raise Forbidden(errstr)
diff --git a/mediagoblin/media_types/__init__.py b/mediagoblin/media_types/__init__.py
index 5bf0124c..06763510 100644
--- a/mediagoblin/media_types/__init__.py
+++ b/mediagoblin/media_types/__init__.py
@@ -78,25 +78,6 @@ def get_media_managers():
yield media_type, sys.modules[media_type].MEDIA_MANAGER
-def get_media_manager(_media_type):
- '''
- Get the MEDIA_MANAGER based on a media type string
-
- Example::
- get_media_type('mediagoblin.media_types.image')
- '''
- if not _media_type:
- return False
-
- for media_type, manager in get_media_managers():
- if media_type in _media_type:
- return manager
-
- # Nope? Then raise an error
- raise FileTypeNotSupported(
- "MediaManager not in enabled types. Check media_types in config?")
-
-
def get_media_type_and_manager(filename):
'''
Try to find the media type based on the file name, extension
diff --git a/mediagoblin/media_types/ascii/models.py b/mediagoblin/media_types/ascii/models.py
index 865c216c..3416993c 100644
--- a/mediagoblin/media_types/ascii/models.py
+++ b/mediagoblin/media_types/ascii/models.py
@@ -15,13 +15,16 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-from mediagoblin.db.sql.base import Base
+from mediagoblin.db.base import Base
from sqlalchemy import (
Column, Integer, ForeignKey)
from sqlalchemy.orm import relationship, backref
+BACKREF_NAME = "ascii__media_data"
+
+
class AsciiData(Base):
__tablename__ = "ascii__mediadata"
@@ -29,7 +32,7 @@ class AsciiData(Base):
media_entry = Column(Integer, ForeignKey('core__media_entries.id'),
primary_key=True)
get_media_entry = relationship("MediaEntry",
- backref=backref("ascii__media_data", cascade="all, delete-orphan"))
+ backref=backref(BACKREF_NAME, cascade="all, delete-orphan"))
DATA_MODEL = AsciiData
diff --git a/mediagoblin/media_types/ascii/processing.py b/mediagoblin/media_types/ascii/processing.py
index 04d1166c..254717eb 100644
--- a/mediagoblin/media_types/ascii/processing.py
+++ b/mediagoblin/media_types/ascii/processing.py
@@ -19,6 +19,7 @@ import Image
import logging
from mediagoblin import mg_globals as mgg
+from mediagoblin.decorators import get_workbench
from mediagoblin.processing import create_pub_filepath
from mediagoblin.media_types.ascii import asciitoimage
@@ -38,12 +39,14 @@ def sniff_handler(media_file, **kw):
return False
-def process_ascii(entry):
- '''
- Code to process a txt file
- '''
+@get_workbench
+def process_ascii(entry, workbench=None):
+ """Code to process a txt file. Will be run by celery.
+
+ A Workbench() represents a local tempory dir. It is automatically
+ cleaned up when this function exits.
+ """
ascii_config = mgg.global_config['media_type:mediagoblin.media_types.ascii']
- workbench = mgg.workbench_manager.create_workbench()
# Conversions subdirectory to avoid collisions
conversions_subdir = os.path.join(
workbench.dir, 'conversions')
diff --git a/mediagoblin/media_types/audio/models.py b/mediagoblin/media_types/audio/models.py
index 5f18d2c2..368ab1eb 100644
--- a/mediagoblin/media_types/audio/models.py
+++ b/mediagoblin/media_types/audio/models.py
@@ -15,13 +15,16 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-from mediagoblin.db.sql.base import Base
+from mediagoblin.db.base import Base
from sqlalchemy import (
Column, Integer, ForeignKey)
from sqlalchemy.orm import relationship, backref
+BACKREF_NAME = "audio__media_data"
+
+
class AudioData(Base):
__tablename__ = "audio__mediadata"
@@ -29,7 +32,7 @@ class AudioData(Base):
media_entry = Column(Integer, ForeignKey('core__media_entries.id'),
primary_key=True)
get_media_entry = relationship("MediaEntry",
- backref=backref("audio__media_data", cascade="all, delete-orphan"))
+ backref=backref(BACKREF_NAME, cascade="all, delete-orphan"))
DATA_MODEL = AudioData
diff --git a/mediagoblin/media_types/audio/processing.py b/mediagoblin/media_types/audio/processing.py
index fada083f..e12cefe6 100644
--- a/mediagoblin/media_types/audio/processing.py
+++ b/mediagoblin/media_types/audio/processing.py
@@ -15,10 +15,11 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import logging
-import tempfile
+from tempfile import NamedTemporaryFile
import os
from mediagoblin import mg_globals as mgg
+from mediagoblin.decorators import get_workbench
from mediagoblin.processing import (create_pub_filepath, BadMediaFail,
FilenameBuilder, ProgressCallback)
@@ -42,10 +43,14 @@ def sniff_handler(media_file, **kw):
return False
-def process_audio(entry):
- audio_config = mgg.global_config['media_type:mediagoblin.media_types.audio']
+@get_workbench
+def process_audio(entry, workbench=None):
+ """Code to process uploaded audio. Will be run by celery.
- workbench = mgg.workbench_manager.create_workbench()
+ A Workbench() represents a local tempory dir. It is automatically
+ cleaned up when this function exits.
+ """
+ audio_config = mgg.global_config['media_type:mediagoblin.media_types.audio']
queued_filepath = entry.queued_media_file
queued_filename = workbench.localized_file(
@@ -73,7 +78,7 @@ def process_audio(entry):
transcoder = AudioTranscoder()
- with tempfile.NamedTemporaryFile() as webm_audio_tmp:
+ with NamedTemporaryFile(dir=workbench.dir) as webm_audio_tmp:
progress_callback = ProgressCallback(entry)
transcoder.transcode(
@@ -99,7 +104,7 @@ def process_audio(entry):
original=os.path.splitext(
queued_filepath[-1])[0]))
- with tempfile.NamedTemporaryFile(suffix='.ogg') as wav_tmp:
+ with NamedTemporaryFile(dir=workbench.dir, suffix='.ogg') as wav_tmp:
_log.info('Creating OGG source for spectrogram')
transcoder.transcode(
queued_filename,
@@ -109,7 +114,7 @@ def process_audio(entry):
thumbnailer = AudioThumbnailer()
- with tempfile.NamedTemporaryFile(suffix='.jpg') as spectrogram_tmp:
+ with NamedTemporaryFile(dir=workbench.dir, suffix='.jpg') as spectrogram_tmp:
thumbnailer.spectrogram(
wav_tmp.name,
spectrogram_tmp.name,
@@ -122,7 +127,7 @@ def process_audio(entry):
entry.media_files['spectrogram'] = spectrogram_filepath
- with tempfile.NamedTemporaryFile(suffix='.jpg') as thumb_tmp:
+ with NamedTemporaryFile(dir=workbench.dir, suffix='.jpg') as thumb_tmp:
thumbnailer.thumbnail_spectrogram(
spectrogram_tmp.name,
thumb_tmp.name,
@@ -143,8 +148,3 @@ def process_audio(entry):
entry.media_files['thumb'] = ['fake', 'thumb', 'path.jpg']
mgg.queue_store.delete_file(queued_filepath)
-
- entry.save()
-
- # clean up workbench
- workbench.destroy_self()
diff --git a/mediagoblin/media_types/image/models.py b/mediagoblin/media_types/image/models.py
index fc518daa..63d80aa8 100644
--- a/mediagoblin/media_types/image/models.py
+++ b/mediagoblin/media_types/image/models.py
@@ -15,12 +15,15 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-from mediagoblin.db.sql.base import Base
+from mediagoblin.db.base import Base
from sqlalchemy import (
Column, Integer, Float, ForeignKey)
from sqlalchemy.orm import relationship, backref
-from mediagoblin.db.sql.extratypes import JSONEncoded
+from mediagoblin.db.extratypes import JSONEncoded
+
+
+BACKREF_NAME = "image__media_data"
class ImageData(Base):
@@ -30,7 +33,7 @@ class ImageData(Base):
media_entry = Column(Integer, ForeignKey('core__media_entries.id'),
primary_key=True)
get_media_entry = relationship("MediaEntry",
- backref=backref("image__media_data", cascade="all, delete-orphan"))
+ backref=backref(BACKREF_NAME, cascade="all, delete-orphan"))
width = Column(Integer)
height = Column(Integer)
diff --git a/mediagoblin/media_types/image/processing.py b/mediagoblin/media_types/image/processing.py
index bdb2290f..e6a34ca0 100644
--- a/mediagoblin/media_types/image/processing.py
+++ b/mediagoblin/media_types/image/processing.py
@@ -19,6 +19,7 @@ import os
import logging
from mediagoblin import mg_globals as mgg
+from mediagoblin.decorators import get_workbench
from mediagoblin.processing import BadMediaFail, \
create_pub_filepath, FilenameBuilder
from mediagoblin.tools.exif import exif_fix_image_orientation, \
@@ -76,11 +77,13 @@ def sniff_handler(media_file, **kw):
return False
-def process_image(entry):
- """
- Code to process an image
+@get_workbench
+def process_image(entry, workbench=None):
+ """Code to process an image. Will be run by celery.
+
+ A Workbench() represents a local tempory dir. It is automatically
+ cleaned up when this function exits.
"""
- workbench = mgg.workbench_manager.create_workbench()
# Conversions subdirectory to avoid collisions
conversions_subdir = os.path.join(
workbench.dir, 'conversions')
@@ -120,17 +123,10 @@ def process_image(entry):
else:
medium_filepath = None
- # we have to re-read because unlike PIL, not everything reads
- # things in string representation :)
- queued_file = file(queued_filename, 'rb')
-
- with queued_file:
- original_filepath = create_pub_filepath(
+ # Copy our queued local workbench to its final destination
+ original_filepath = create_pub_filepath(
entry, name_builder.fill('{basename}{ext}'))
-
- with mgg.public_store.get_file(original_filepath, 'wb') \
- as original_file:
- original_file.write(queued_file.read())
+ mgg.public_store.copy_local_to_storage(queued_filename, original_filepath)
# Remove queued media file from storage and database
mgg.queue_store.delete_file(queued_filepath)
@@ -154,8 +150,6 @@ def process_image(entry):
gps_data['gps_' + key] = gps_data.pop(key)
entry.media_data_init(**gps_data)
- # clean up workbench
- workbench.destroy_self()
if __name__ == '__main__':
import sys
diff --git a/mediagoblin/db/sql/fake.py b/mediagoblin/media_types/stl/__init__.py
index 0fd0cc41..edffc633 100644
--- a/mediagoblin/db/sql/fake.py
+++ b/mediagoblin/media_types/stl/__init__.py
@@ -14,32 +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/>.
+from mediagoblin.media_types.stl.processing import process_stl, \
+ sniff_handler
-"""
-This module contains some fake classes and functions to
-calm the rest of the code base. Or provide super minimal
-implementations.
-Currently:
-- ObjectId "class": It's a function mostly doing
- int(init_arg) to convert string primary keys into
- integer primary keys.
-- InvalidId exception
-- DESCENDING "constant"
-"""
-
-
-DESCENDING = object() # a unique object for this "constant"
-
-
-class InvalidId(Exception):
- pass
-
-
-def ObjectId(value=None):
- if value is None:
- return None
- try:
- return int(value)
- except ValueError:
- raise InvalidId("%r is an invalid id" % value)
+MEDIA_MANAGER = {
+ "human_readable": "stereo lithographics",
+ "processor": process_stl,
+ "sniff_handler": sniff_handler,
+ "display_template": "mediagoblin/media_displays/stl.html",
+ "default_thumb": "images/media_thumbs/video.jpg",
+ "accepted_extensions": ["obj", "stl"]}
diff --git a/mediagoblin/media_types/stl/assets/blender_render.blend b/mediagoblin/media_types/stl/assets/blender_render.blend
new file mode 100644
index 00000000..dd356a06
--- /dev/null
+++ b/mediagoblin/media_types/stl/assets/blender_render.blend
Binary files differ
diff --git a/mediagoblin/media_types/stl/assets/blender_render.py b/mediagoblin/media_types/stl/assets/blender_render.py
new file mode 100644
index 00000000..99d5fa31
--- /dev/null
+++ b/mediagoblin/media_types/stl/assets/blender_render.py
@@ -0,0 +1,84 @@
+# 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 bpy, json, os
+
+
+try:
+ CONFIG = json.loads(os.environ["RENDER_SETUP"])
+ MODEL_EXT = CONFIG["model_ext"]
+ MODEL_PATH = CONFIG["model_path"]
+ CAMERA_COORD = CONFIG["camera_coord"]
+ CAMERA_FOCUS = CONFIG["camera_focus"]
+ CAMERA_CLIP = CONFIG["camera_clip"]
+ CAMERA_TYPE = CONFIG["projection"]
+ CAMERA_ORTHO = CONFIG["greatest"] * 1.5
+ RENDER_WIDTH = CONFIG["width"]
+ RENDER_HEIGHT = CONFIG["height"]
+ RENDER_FILE = CONFIG["out_file"]
+except KeyError:
+ print("Failed to load RENDER_SETUP environment variable.")
+ exit(1)
+
+
+# add and setup camera
+bpy.ops.object.camera_add(view_align=False, enter_editmode=False,
+ location = CAMERA_COORD)
+camera_ob = bpy.data.objects[0]
+camera = bpy.data.cameras[0]
+camera.clip_end = CAMERA_CLIP
+camera.ortho_scale = CAMERA_ORTHO
+camera.type = CAMERA_TYPE
+
+
+
+# add an empty for focusing the camera
+bpy.ops.object.add(location=CAMERA_FOCUS)
+target = bpy.data.objects[1]
+bpy.ops.object.select_all(action="SELECT")
+bpy.ops.object.track_set(type="TRACKTO")
+bpy.ops.object.select_all(action="DESELECT")
+
+
+if MODEL_EXT == 'stl':
+ # import an stl model
+ bpy.ops.import_mesh.stl(filepath=MODEL_PATH)
+
+elif MODEL_EXT == 'obj':
+ # import an obj model
+ bpy.ops.import_scene.obj(
+ filepath=MODEL_PATH,
+ use_smooth_groups=False,
+ use_image_search=False,
+ axis_forward="Y",
+ axis_up="Z")
+
+
+# rotate the imported objects with meshes in the scene
+if CAMERA_TYPE == "PERSP":
+ for obj in bpy.data.objects[2:]:
+ obj.rotation_euler[2]=-.3
+
+
+# attempt to render
+scene = bpy.data.scenes.values()[0]
+scene.camera = camera_ob
+scene.render.filepath = RENDER_FILE
+scene.render.resolution_x = RENDER_WIDTH
+scene.render.resolution_y = RENDER_HEIGHT
+scene.render.resolution_percentage = 100
+bpy.ops.render.render(write_still=True)
diff --git a/mediagoblin/db/mongo/__init__.py b/mediagoblin/media_types/stl/migrations.py
index 621845ba..f54c23ea 100644
--- a/mediagoblin/db/mongo/__init__.py
+++ b/mediagoblin/media_types/stl/migrations.py
@@ -13,3 +13,5 @@
#
# 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/>.
+
+MIGRATIONS = {}
diff --git a/mediagoblin/media_types/stl/model_loader.py b/mediagoblin/media_types/stl/model_loader.py
new file mode 100644
index 00000000..60fa4851
--- /dev/null
+++ b/mediagoblin/media_types/stl/model_loader.py
@@ -0,0 +1,134 @@
+# 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 struct
+
+
+class ThreeDeeParseError(Exception):
+ pass
+
+
+class ThreeDee():
+ """
+ 3D model parser base class. Derrived classes are used for basic
+ analysis of 3D models, and are not intended to be used for 3D
+ rendering.
+ """
+
+ def __init__(self, fileob):
+ self.verts = []
+ self.average = [0, 0, 0]
+ self.min = [None, None, None]
+ self.max = [None, None, None]
+ self.width = 0 # x axis
+ self.depth = 0 # y axis
+ self.height = 0 # z axis
+
+ self.load(fileob)
+ if not len(self.verts):
+ raise ThreeDeeParseError("Empty model.")
+
+ for vector in self.verts:
+ for i in range(3):
+ num = vector[i]
+ self.average[i] += num
+ if not self.min[i]:
+ self.min[i] = num
+ self.max[i] = num
+ else:
+ if self.min[i] > num:
+ self.min[i] = num
+ if self.max[i] < num:
+ self.max[i] = num
+
+ for i in range(3):
+ self.average[i]/=len(self.verts)
+
+ self.width = abs(self.min[0] - self.max[0])
+ self.depth = abs(self.min[1] - self.max[1])
+ self.height = abs(self.min[2] - self.max[2])
+
+
+ def load(self, fileob):
+ """Override this method in your subclass."""
+ pass
+
+
+class ObjModel(ThreeDee):
+ """
+ Parser for textureless wavefront obj files. File format
+ reference: http://en.wikipedia.org/wiki/Wavefront_.obj_file
+ """
+
+ def __vector(self, line, expected=3):
+ nums = map(float, line.strip().split(" ")[1:])
+ return tuple(nums[:expected])
+
+ def load(self, fileob):
+ for line in fileob:
+ if line[0] == "v":
+ self.verts.append(self.__vector(line))
+
+
+class BinaryStlModel(ThreeDee):
+ """
+ Parser for ascii-encoded stl files. File format reference:
+ http://en.wikipedia.org/wiki/STL_%28file_format%29#Binary_STL
+ """
+
+ def load(self, fileob):
+ fileob.seek(80) # skip the header
+ count = struct.unpack("<I", fileob.read(4))[0]
+ for i in range(count):
+ fileob.read(12) # skip the normal vector
+ for v in range(3):
+ self.verts.append(struct.unpack("<3f", fileob.read(12)))
+ fileob.read(2) # skip the attribute bytes
+
+
+def auto_detect(fileob, hint):
+ """
+ Attempt to divine which parser to use to divine information about
+ the model / verify the file."""
+
+ if hint == "obj" or not hint:
+ try:
+ return ObjModel(fileob)
+ except ThreeDeeParseError:
+ pass
+
+ if hint == "stl" or not hint:
+ try:
+ # HACK Ascii formatted stls are similar enough to obj
+ # files that we can just use the same parser for both.
+ # Isn't that something?
+ return ObjModel(fileob)
+ except ThreeDeeParseError:
+ pass
+ except ValueError:
+ pass
+ try:
+ # It is pretty important that the binary stl model loader
+ # is tried second, because its possible for it to parse
+ # total garbage from plaintext =)
+ return BinaryStlModel(fileob)
+ except ThreeDeeParseError:
+ pass
+ except MemoryError:
+ pass
+
+ raise ThreeDeeParseError("Could not successfully parse the model :(")
diff --git a/mediagoblin/media_types/stl/models.py b/mediagoblin/media_types/stl/models.py
new file mode 100644
index 00000000..17091f0e
--- /dev/null
+++ b/mediagoblin/media_types/stl/models.py
@@ -0,0 +1,49 @@
+# 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.db.base import Base
+
+from sqlalchemy import (
+ Column, Integer, Float, String, ForeignKey)
+from sqlalchemy.orm import relationship, backref
+
+
+BACKREF_NAME = "stl__media_data"
+
+
+class StlData(Base):
+ __tablename__ = "stl__mediadata"
+
+ # The primary key *and* reference to the main media_entry
+ media_entry = Column(Integer, ForeignKey('core__media_entries.id'),
+ primary_key=True)
+ get_media_entry = relationship("MediaEntry",
+ backref=backref(BACKREF_NAME, cascade="all, delete-orphan"))
+
+ center_x = Column(Float)
+ center_y = Column(Float)
+ center_z = Column(Float)
+
+ width = Column(Float)
+ height = Column(Float)
+ depth = Column(Float)
+
+ file_type = Column(String)
+
+
+DATA_MODEL = StlData
+MODELS = [StlData]
diff --git a/mediagoblin/media_types/stl/processing.py b/mediagoblin/media_types/stl/processing.py
new file mode 100644
index 00000000..3089f295
--- /dev/null
+++ b/mediagoblin/media_types/stl/processing.py
@@ -0,0 +1,190 @@
+# 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 json
+import logging
+import subprocess
+import pkg_resources
+
+from mediagoblin import mg_globals as mgg
+from mediagoblin.decorators import get_workbench
+from mediagoblin.processing import create_pub_filepath, \
+ FilenameBuilder
+
+from mediagoblin.media_types.stl import model_loader
+
+
+_log = logging.getLogger(__name__)
+SUPPORTED_FILETYPES = ['stl', 'obj']
+
+BLEND_FILE = pkg_resources.resource_filename(
+ 'mediagoblin.media_types.stl',
+ os.path.join(
+ 'assets',
+ 'blender_render.blend'))
+BLEND_SCRIPT = pkg_resources.resource_filename(
+ 'mediagoblin.media_types.stl',
+ os.path.join(
+ 'assets',
+ 'blender_render.py'))
+
+
+def sniff_handler(media_file, **kw):
+ 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
+ else:
+ _log.debug('Media present, extension not found in {0}'.format(
+ SUPPORTED_FILETYPES))
+ else:
+ _log.warning('Need additional information (keyword argument \'media\')'
+ ' to be able to handle sniffing')
+
+ return False
+
+
+def blender_render(config):
+ """
+ Called to prerender a model.
+ """
+ arg_string = "blender -b blender_render.blend -F "
+ arg_string +="JPEG -P blender_render.py"
+ env = {"RENDER_SETUP" : json.dumps(config), "DISPLAY":":0"}
+ subprocess.call(
+ ["blender",
+ "-b", BLEND_FILE,
+ "-F", "JPEG",
+ "-P", BLEND_SCRIPT],
+ env=env)
+
+
+@get_workbench
+def process_stl(entry, workbench=None):
+ """Code to process an stl or obj model. Will be run by celery.
+
+ A Workbench() represents a local tempory dir. It is automatically
+ cleaned up when this function exits.
+ """
+ queued_filepath = entry.queued_media_file
+ queued_filename = workbench.localized_file(
+ mgg.queue_store, queued_filepath, 'source')
+ name_builder = FilenameBuilder(queued_filename)
+
+ ext = queued_filename.lower().strip()[-4:]
+ if ext.startswith("."):
+ ext = ext[1:]
+ else:
+ ext = None
+
+ # Attempt to parse the model file and divine some useful
+ # information about it.
+ with open(queued_filename, 'rb') as model_file:
+ model = model_loader.auto_detect(model_file, ext)
+
+ # generate preview images
+ greatest = [model.width, model.height, model.depth]
+ greatest.sort()
+ greatest = greatest[-1]
+
+ def snap(name, camera, width=640, height=640, project="ORTHO"):
+ filename = name_builder.fill(name)
+ workbench_path = workbench.joinpath(filename)
+ shot = {
+ "model_path": queued_filename,
+ "model_ext": ext,
+ "camera_coord": camera,
+ "camera_focus": model.average,
+ "camera_clip": greatest*10,
+ "greatest": greatest,
+ "projection": project,
+ "width": width,
+ "height": height,
+ "out_file": workbench_path,
+ }
+ blender_render(shot)
+
+ # make sure the image rendered to the workbench path
+ assert os.path.exists(workbench_path)
+
+ # copy it up!
+ with open(workbench_path, 'rb') as rendered_file:
+ public_path = create_pub_filepath(entry, filename)
+
+ with mgg.public_store.get_file(public_path, "wb") as public_file:
+ public_file.write(rendered_file.read())
+
+ return public_path
+
+ thumb_path = snap(
+ "{basename}.thumb.jpg",
+ [0, greatest*-1.5, greatest],
+ mgg.global_config['media:thumb']['max_width'],
+ mgg.global_config['media:thumb']['max_height'],
+ project="PERSP")
+
+ perspective_path = snap(
+ "{basename}.perspective.jpg",
+ [0, greatest*-1.5, greatest], project="PERSP")
+
+ topview_path = snap(
+ "{basename}.top.jpg",
+ [model.average[0], model.average[1], greatest*2])
+
+ frontview_path = snap(
+ "{basename}.front.jpg",
+ [model.average[0], greatest*-2, model.average[2]])
+
+ sideview_path = snap(
+ "{basename}.side.jpg",
+ [greatest*-2, model.average[1], model.average[2]])
+
+ ## Save the public file stuffs
+ model_filepath = create_pub_filepath(
+ entry, name_builder.fill('{basename}{ext}'))
+
+ with mgg.public_store.get_file(model_filepath, 'wb') as model_file:
+ with open(queued_filename, 'rb') as queued_file:
+ model_file.write(queued_file.read())
+
+ # Remove queued media file from storage and database
+ mgg.queue_store.delete_file(queued_filepath)
+ entry.queued_media_file = []
+
+ # Insert media file information into database
+ media_files_dict = entry.setdefault('media_files', {})
+ media_files_dict[u'original'] = model_filepath
+ media_files_dict[u'thumb'] = thumb_path
+ media_files_dict[u'perspective'] = perspective_path
+ media_files_dict[u'top'] = topview_path
+ media_files_dict[u'side'] = sideview_path
+ media_files_dict[u'front'] = frontview_path
+
+ # Put model dimensions into the database
+ dimensions = {
+ "center_x" : model.average[0],
+ "center_y" : model.average[1],
+ "center_z" : model.average[2],
+ "width" : model.width,
+ "height" : model.height,
+ "depth" : model.depth,
+ "file_type" : ext,
+ }
+ entry.media_data_init(**dimensions)
diff --git a/mediagoblin/media_types/video/models.py b/mediagoblin/media_types/video/models.py
index 35ed92bf..645ef4d3 100644
--- a/mediagoblin/media_types/video/models.py
+++ b/mediagoblin/media_types/video/models.py
@@ -15,13 +15,16 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-from mediagoblin.db.sql.base import Base
+from mediagoblin.db.base import Base
from sqlalchemy import (
Column, Integer, SmallInteger, ForeignKey)
from sqlalchemy.orm import relationship, backref
+BACKREF_NAME = "video__media_data"
+
+
class VideoData(Base):
__tablename__ = "video__mediadata"
@@ -29,7 +32,7 @@ class VideoData(Base):
media_entry = Column(Integer, ForeignKey('core__media_entries.id'),
primary_key=True)
get_media_entry = relationship("MediaEntry",
- backref=backref("video__media_data", cascade="all, delete-orphan"))
+ backref=backref(BACKREF_NAME, cascade="all, delete-orphan"))
width = Column(SmallInteger)
height = Column(SmallInteger)
diff --git a/mediagoblin/media_types/video/processing.py b/mediagoblin/media_types/video/processing.py
index ce47313f..22c4355d 100644
--- a/mediagoblin/media_types/video/processing.py
+++ b/mediagoblin/media_types/video/processing.py
@@ -14,10 +14,11 @@
# 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 tempfile
+from tempfile import NamedTemporaryFile
import logging
from mediagoblin import mg_globals as mgg
+from mediagoblin.decorators import get_workbench
from mediagoblin.processing import \
create_pub_filepath, FilenameBuilder, BaseProcessingFail, ProgressCallback
from mediagoblin.tools.translate import lazy_pass_to_ugettext as _
@@ -51,16 +52,17 @@ def sniff_handler(media_file, **kw):
return False
-
-def process_video(entry):
+@get_workbench
+def process_video(entry, workbench=None):
"""
Process a video entry, transcode the queued media files (originals) and
create a thumbnail for the entry.
+
+ A Workbench() represents a local tempory dir. It is automatically
+ cleaned up when this function exits.
"""
video_config = mgg.global_config['media_type:mediagoblin.media_types.video']
- workbench = mgg.workbench_manager.create_workbench()
-
queued_filepath = entry.queued_media_file
queued_filename = workbench.localized_file(
mgg.queue_store, queued_filepath,
@@ -74,7 +76,7 @@ def process_video(entry):
entry, name_builder.fill('{basename}.thumbnail.jpg'))
# Create a temporary file for the video destination
- tmp_dst = tempfile.NamedTemporaryFile()
+ tmp_dst = NamedTemporaryFile(dir=workbench.dir)
with tmp_dst:
# Transcode queued file to a VP8/vorbis file that fits in a 640x640 square
@@ -88,6 +90,7 @@ def process_video(entry):
# Push transcoded video to public storage
_log.debug('Saving medium...')
+ # TODO (#419, we read everything in RAM here!)
mgg.public_store.get_file(medium_filepath, 'wb').write(
tmp_dst.read())
_log.debug('Saved medium')
@@ -100,7 +103,7 @@ def process_video(entry):
height=transcoder.dst_data.videoheight)
# Create a temporary file for the video thumbnail
- tmp_thumb = tempfile.NamedTemporaryFile(suffix='.jpg')
+ tmp_thumb = NamedTemporaryFile(dir=workbench.dir, suffix='.jpg')
with tmp_thumb:
# Create a thumbnail.jpg that fits in a 180x180 square
@@ -129,6 +132,7 @@ def process_video(entry):
with mgg.public_store.get_file(original_filepath, 'wb') as \
original_file:
_log.debug('Saving original...')
+ # TODO (#419, we read everything in RAM here!)
original_file.write(queued_file.read())
_log.debug('Saved original')
@@ -136,5 +140,5 @@ def process_video(entry):
mgg.queue_store.delete_file(queued_filepath)
- # Save the MediaEntry
- entry.save()
+ # clean up workbench
+ workbench.destroy_self()
diff --git a/mediagoblin/media_types/video/transcoders.py b/mediagoblin/media_types/video/transcoders.py
index 26f96b5f..152de288 100644
--- a/mediagoblin/media_types/video/transcoders.py
+++ b/mediagoblin/media_types/video/transcoders.py
@@ -636,7 +636,7 @@ class VideoTranscoder:
'''
def __init__(self):
_log.info('Initializing VideoTranscoder...')
-
+ self.progress_percentage = None
self.loop = gobject.MainLoop()
def transcode(self, src, dst, **kwargs):
@@ -913,12 +913,14 @@ class VideoTranscoder:
elif message.type == gst.MESSAGE_ELEMENT:
if message.structure.get_name() == 'progress':
data = dict(message.structure)
-
- if self._progress_callback:
- self._progress_callback(data.get('percent'))
-
- _log.info('{percent}% done...'.format(
- percent=data.get('percent')))
+ # Update progress state if it has changed
+ if self.progress_percentage != data.get('percent'):
+ self.progress_percentage = data.get('percent')
+ if self._progress_callback:
+ self._progress_callback(data.get('percent'))
+
+ _log.info('{percent}% done...'.format(
+ percent=data.get('percent')))
_log.debug(data)
elif t == gst.MESSAGE_ERROR:
diff --git a/mediagoblin/mg_globals.py b/mediagoblin/mg_globals.py
index 646fbdbd..8c7c64c2 100644
--- a/mediagoblin/mg_globals.py
+++ b/mediagoblin/mg_globals.py
@@ -26,10 +26,7 @@ import threading
# General mediagoblin globals
#############################
-# mongokit.Connection
-db_connection = None
-
-# mongokit.Connection
+# SQL database engine
database = None
# beaker's cache manager
@@ -45,8 +42,6 @@ workbench_manager = None
# A thread-local scope
thread_scope = threading.local()
-# a list of translated locales
-available_locales = None
# gettext (this will be populated on demand with gettext.Translations)
thread_scope.translations = None
diff --git a/mediagoblin/plugins/api/tools.py b/mediagoblin/plugins/api/tools.py
index ecc50364..e5878258 100644
--- a/mediagoblin/plugins/api/tools.py
+++ b/mediagoblin/plugins/api/tools.py
@@ -18,9 +18,9 @@ import logging
import json
from functools import wraps
-from webob import exc, Response
from urlparse import urljoin
-
+from werkzeug.exceptions import Forbidden
+from werkzeug.wrappers import Response
from mediagoblin import mg_globals
from mediagoblin.tools.pluginapi import PluginManager
from mediagoblin.storage.filestorage import BasicFileStorage
@@ -54,23 +54,22 @@ class Auth(object):
def json_response(serializable, _disable_cors=False, *args, **kw):
'''
- Serializes a json objects and returns a webob.Response object with the
+ Serializes a json objects and returns a werkzeug Response object with the
serialized value as the response body and Content-Type: application/json.
:param serializable: A json-serializable object
Any extra arguments and keyword arguments are passed to the
- webob.Response.__init__ method.
+ Response.__init__ method.
'''
- response = Response(json.dumps(serializable), *args, **kw)
- response.headers['Content-Type'] = 'application/json'
+ response = Response(json.dumps(serializable), *args, content_type='application/json', **kw)
if not _disable_cors:
cors_headers = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, X-Requested-With'}
- response.headers.update(cors_headers)
+ (response.headers.set(key, value) for key, value in cors_headers)
return response
@@ -136,14 +135,14 @@ def api_auth(controller):
auth_candidates = []
for auth in PluginManager().get_hook_callables('auth'):
- _log.debug('Plugin auth: {0}'.format(auth))
if auth.trigger(request):
+ _log.debug('{0} believes it is capable of authenticating this request.'.format(auth))
auth_candidates.append(auth)
# If we can't find any authentication methods, we should not let them
# pass.
if not auth_candidates:
- return exc.HTTPForbidden()
+ raise Forbidden()
# For now, just select the first one in the list
auth = auth_candidates[0]
@@ -157,7 +156,7 @@ def api_auth(controller):
'status': 403,
'errors': auth.errors})
- return exc.HTTPForbidden()
+ raise Forbidden()
return controller(request, *args, **kw)
diff --git a/mediagoblin/plugins/api/views.py b/mediagoblin/plugins/api/views.py
index a1b1bcac..6aa4ef9f 100644
--- a/mediagoblin/plugins/api/views.py
+++ b/mediagoblin/plugins/api/views.py
@@ -16,22 +16,18 @@
import json
import logging
-import uuid
from os.path import splitext
-from webob import exc, Response
-from werkzeug.utils import secure_filename
from werkzeug.datastructures import FileStorage
-from celery import registry
+from werkzeug.exceptions import BadRequest, Forbidden
+from werkzeug.wrappers import Response
-from mediagoblin.db.util import ObjectId
from mediagoblin.decorators import require_active_login
-from mediagoblin.processing import mark_entry_failed
-from mediagoblin.processing.task import ProcessMedia
from mediagoblin.meddleware.csrf import csrf_exempt
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 prepare_queue_task, run_process_media
_log = logging.getLogger(__name__)
@@ -47,20 +43,19 @@ def post_entry(request):
if request.method != 'POST':
_log.debug('Must POST against post_entry')
- return exc.HTTPBadRequest()
+ raise BadRequest()
if not 'file' in request.files \
or not isinstance(request.files['file'], FileStorage) \
or not request.files['file'].stream:
_log.debug('File field not found')
- return exc.HTTPBadRequest()
+ raise BadRequest()
media_file = request.files['file']
media_type, media_manager = sniff_media(media_file)
entry = request.db.MediaEntry()
- entry.id = ObjectId()
entry.media_type = unicode(media_type)
entry.title = unicode(request.form.get('title')
or splitext(media_file.filename)[0])
@@ -72,28 +67,14 @@ def post_entry(request):
entry.generate_slug()
- task_id = unicode(uuid.uuid4())
-
- # Now store generate the queueing related filename
- queue_filepath = request.app.queue_store.get_unique_filepath(
- ['media_entries',
- task_id,
- secure_filename(media_file.filename)])
-
# queue appropriately
- queue_file = request.app.queue_store.get_file(
- queue_filepath, 'wb')
+ queue_file = prepare_queue_task(request.app, entry, media_file.filename)
with queue_file:
queue_file.write(request.files['file'].stream.read())
- # Add queued filename to the entry
- entry.queued_media_file = queue_filepath
-
- entry.queued_task_id = task_id
-
# Save now so we have this data before kicking off processing
- entry.save(validate=True)
+ entry.save()
if request.form.get('callback_url'):
metadata = request.db.ProcessingMetaData()
@@ -105,36 +86,20 @@ def post_entry(request):
#
# (... don't change entry after this point to avoid race
# conditions with changes to the document via processing code)
- process_media = registry.tasks[ProcessMedia.name]
- try:
- process_media.apply_async(
- [unicode(entry._id)], {},
- task_id=task_id)
- except BaseException as e:
- # The purpose of this section is because when running in "lazy"
- # or always-eager-with-exceptions-propagated celery mode that
- # the failure handling won't happen on Celery end. Since we
- # expect a lot of users to run things in this way we have to
- # capture stuff here.
- #
- # ... not completely the diaper pattern because the
- # exception is re-raised :)
- mark_entry_failed(entry._id, e)
- # re-raise the exception
- raise
+ run_process_media(entry)
return json_response(get_entry_serializable(entry, request.urlgen))
@api_auth
+@require_active_login
def api_test(request):
- if not request.user:
- return exc.HTTPForbidden()
-
user_data = {
'username': request.user.username,
'email': request.user.email}
+ # TODO: This is the *only* thing using Response() here, should that
+ # not simply use json_response()?
return Response(json.dumps(user_data))
diff --git a/mediagoblin/plugins/httpapiauth/__init__.py b/mediagoblin/plugins/httpapiauth/__init__.py
index d3d2065e..081b590e 100644
--- a/mediagoblin/plugins/httpapiauth/__init__.py
+++ b/mediagoblin/plugins/httpapiauth/__init__.py
@@ -41,7 +41,7 @@ class HTTPAuth(Auth):
return False
user = request.db.User.query.filter_by(
- username=request.authorization['username']).first()
+ username=unicode(request.authorization['username'])).first()
if user.check_login(request.authorization['password']):
request.user = user
diff --git a/mediagoblin/plugins/oauth/migrations.py b/mediagoblin/plugins/oauth/migrations.py
index 797e7585..6aa0d7cb 100644
--- a/mediagoblin/plugins/oauth/migrations.py
+++ b/mediagoblin/plugins/oauth/migrations.py
@@ -19,8 +19,8 @@ from sqlalchemy import (MetaData, Table, Column,
Integer, Unicode, Enum, DateTime, ForeignKey)
from sqlalchemy.ext.declarative import declarative_base
-from mediagoblin.db.sql.util import RegisterMigration
-from mediagoblin.db.sql.models import User
+from mediagoblin.db.migration_tools import RegisterMigration
+from mediagoblin.db.models import User
MIGRATIONS = {}
diff --git a/mediagoblin/plugins/oauth/models.py b/mediagoblin/plugins/oauth/models.py
index 7e247c1a..695dad31 100644
--- a/mediagoblin/plugins/oauth/models.py
+++ b/mediagoblin/plugins/oauth/models.py
@@ -19,8 +19,8 @@ import bcrypt
from datetime import datetime, timedelta
-from mediagoblin.db.sql.base import Base
-from mediagoblin.db.sql.models import User
+from mediagoblin.db.base import Base
+from mediagoblin.db.models import User
from sqlalchemy import (
Column, Unicode, Integer, DateTime, ForeignKey, Enum)
diff --git a/mediagoblin/plugins/oauth/views.py b/mediagoblin/plugins/oauth/views.py
index cf605fd2..c7b2a332 100644
--- a/mediagoblin/plugins/oauth/views.py
+++ b/mediagoblin/plugins/oauth/views.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
# GNU MediaGoblin -- federated, autonomous media hosting
# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
#
@@ -17,7 +18,6 @@
import logging
import json
-from webob import exc, Response
from urllib import urlencode
from uuid import uuid4
from datetime import datetime
@@ -94,7 +94,7 @@ def authorize_client(request):
if not client:
_log.error('''No such client id as received from client authorization
form.''')
- return exc.HTTPBadRequest()
+ return BadRequest()
if form.validate():
relation = OAuthUserClient()
@@ -105,11 +105,11 @@ def authorize_client(request):
elif form.deny.data:
relation.state = u'rejected'
else:
- return exc.HTTPBadRequest
+ return BadRequest
relation.save()
- return exc.HTTPFound(location=form.next.data)
+ return redirect(request, location=form.next.data)
return render_to_response(
request,
@@ -162,7 +162,7 @@ def authorize(request, client):
_log.debug('Redirecting to {0}'.format(redirect_uri))
- return exc.HTTPFound(location=redirect_uri)
+ return redirect(request, location=redirect_uri)
else:
# Show prompt to allow client to access data
# - on accept: send the user agent back to the redirect_uri with the
@@ -216,12 +216,15 @@ def access_token(request):
token.client = code.client
token.save()
+ # expire time of token in full seconds
+ # timedelta.total_seconds is python >= 2.7 or we would use that
+ td = token.expires - datetime.now()
+ exp_in = 86400*td.days + td.seconds # just ignore µsec
+
access_token_data = {
'access_token': token.token,
'token_type': 'bearer',
- 'expires_in': int(
- round(
- (token.expires - datetime.now()).total_seconds()))}
+ 'expires_in': exp_in}
return json_response(access_token_data, _disable_cors=True)
else:
return json_response({
diff --git a/mediagoblin/processing/__init__.py b/mediagoblin/processing/__init__.py
index 6b2d50e2..e2bc1a13 100644
--- a/mediagoblin/processing/__init__.py
+++ b/mediagoblin/processing/__init__.py
@@ -38,7 +38,7 @@ class ProgressCallback(object):
def create_pub_filepath(entry, filename):
return mgg.public_store.get_unique_filepath(
['media_entries',
- unicode(entry._id),
+ unicode(entry.id),
filename])
@@ -93,7 +93,7 @@ def mark_entry_failed(entry_id, exc):
# Looks like yes, so record information about that failure and any
# metadata the user might have supplied.
atomic_update(mgg.database.MediaEntry,
- {'_id': entry_id},
+ {'id': entry_id},
{u'state': u'failed',
u'fail_error': unicode(exc.exception_path),
u'fail_metadata': exc.metadata})
@@ -104,7 +104,7 @@ def mark_entry_failed(entry_id, exc):
# metadata (in fact overwrite it if somehow it had previous info
# here)
atomic_update(mgg.database.MediaEntry,
- {'_id': entry_id},
+ {'id': entry_id},
{u'state': u'failed',
u'fail_error': None,
u'fail_metadata': {}})
diff --git a/mediagoblin/processing/task.py b/mediagoblin/processing/task.py
index 187b893d..b29de9bd 100644
--- a/mediagoblin/processing/task.py
+++ b/mediagoblin/processing/task.py
@@ -19,8 +19,7 @@ import logging
from celery.task import Task
from mediagoblin import mg_globals as mgg
-from mediagoblin.db.util import ObjectId
-from mediagoblin.media_types import get_media_manager
+from mediagoblin.db.models import MediaEntry
from mediagoblin.processing import mark_entry_failed, BaseProcessingFail
from mediagoblin.tools.processing import json_processing_callback
@@ -42,26 +41,26 @@ class ProcessMedia(Task):
Pass the media entry off to the appropriate processing function
(for now just process_image...)
"""
- entry = mgg.database.MediaEntry.one(
- {'_id': ObjectId(media_id)})
+ entry = MediaEntry.query.get(media_id)
# Try to process, and handle expected errors.
try:
- manager = get_media_manager(entry.media_type)
-
entry.state = u'processing'
entry.save()
_log.debug('Processing {0}'.format(entry))
- manager['processor'](entry)
+ # run the processing code
+ entry.media_manager['processor'](entry)
+ # We set the state to processed and save the entry here so there's
+ # no need to save at the end of the processing stage, probably ;)
entry.state = u'processed'
entry.save()
json_processing_callback(entry)
except BaseProcessingFail as exc:
- mark_entry_failed(entry._id, exc)
+ mark_entry_failed(entry.id, exc)
json_processing_callback(entry)
return
@@ -72,7 +71,7 @@ class ProcessMedia(Task):
entry.title,
exc))
- mark_entry_failed(entry._id, exc)
+ mark_entry_failed(entry.id, exc)
json_processing_callback(entry)
except Exception as exc:
@@ -80,7 +79,7 @@ class ProcessMedia(Task):
+ ' processing {0}'.format(
entry))
- mark_entry_failed(entry._id, exc)
+ mark_entry_failed(entry.id, exc)
json_processing_callback(entry)
raise
diff --git a/mediagoblin/routing.py b/mediagoblin/routing.py
index defbc4ba..a650f22f 100644
--- a/mediagoblin/routing.py
+++ b/mediagoblin/routing.py
@@ -14,42 +14,29 @@
# 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 werkzeug.routing import Map, Rule
+import logging
-url_map = Map()
+from mediagoblin.tools.routing import add_route, mount, url_map
+from mediagoblin.tools.pluginapi import PluginManager
+from mediagoblin.admin.routing import admin_routes
+from mediagoblin.auth.routing import auth_routes
-view_functions = {}
-def add_route(endpoint, url, controller):
- """
- Add a route to the url mapping
- """
- # XXX: We cannot use this, since running tests means that the plugin
- # routes will be populated over and over over the same session.
- #
- # assert endpoint not in view_functions.keys(), 'Trying to overwrite a rule'
+_log = logging.getLogger(__name__)
- view_functions.update({endpoint: controller})
- url_map.add(Rule(url, endpoint=endpoint))
+def get_url_map():
+ add_route('index', '/', 'mediagoblin.views:root_view')
+ mount('/auth', auth_routes)
+ mount('/a', admin_routes)
-def mount(mountpoint, routes):
- """
- Mount a bunch of routes to this mountpoint
- """
- for endpoint, url, controller in routes:
- url = "%s/%s" % (mountpoint.rstrip('/'), url.lstrip('/'))
- add_route(endpoint, url, controller)
+ import mediagoblin.submit.routing
+ import mediagoblin.user_pages.routing
+ import mediagoblin.edit.routing
+ import mediagoblin.webfinger.routing
+ import mediagoblin.listings.routing
-add_route('index', '/', 'mediagoblin.views:root_view')
+ for route in PluginManager().get_routes():
+ add_route(*route)
-from mediagoblin.admin.routing import admin_routes
-from mediagoblin.auth.routing import auth_routes
-mount('/auth', auth_routes)
-mount('/a', admin_routes)
-
-import mediagoblin.submit.routing
-import mediagoblin.user_pages.routing
-import mediagoblin.edit.routing
-import mediagoblin.webfinger.routing
-import mediagoblin.listings.routing
+ return url_map
diff --git a/mediagoblin/static/css/base.css b/mediagoblin/static/css/base.css
index 4ccebfe1..04b4ee28 100644
--- a/mediagoblin/static/css/base.css
+++ b/mediagoblin/static/css/base.css
@@ -169,7 +169,7 @@ footer {
width: 640px;
margin-left: 0px;
margin-right: 10px;
- float: left;
+ float: left;
}
.media_sidebar {
@@ -220,17 +220,6 @@ footer {
font-family: 'Lato', sans-serif;
}
-.button_collect {
- background-image: url("../images/icon_collect.png");
- background-repeat: no-repeat;
- background-position:top center;
- height: 30px;
- width: 30px;
- margin: 0px;
- padding: 3px 3px 2px 3px;
- position: relative;
-}
-
.pagination {
text-align: center;
}
@@ -343,6 +332,12 @@ textarea#description, textarea#bio {
height: 100px;
}
+.delete {
+ margin-top: 36px;
+ display: block;
+ text-align: center;
+}
+
/* comments */
.comment_wrapper {
@@ -383,9 +378,8 @@ textarea#comment_content {
float: left;
padding: 0px;
width: 180px;
- height: 156px;
overflow: hidden;
- margin: 0px 4px 10px;
+ margin: 0px 3px 10px;
text-align: center;
font-size: 0.875em;
background-color: #222;
@@ -394,6 +388,9 @@ textarea#comment_content {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
+ border-color: #0D0D0D;
+ border-style: solid;
+ border-width: 1px 1px 2px;
}
.media_thumbnail a {
@@ -402,6 +399,11 @@ textarea#comment_content {
display: block;
}
+.media_thumbnail a.remove {
+ color: #86D4B1;
+ text-decoration: underline;
+}
+
a.thumb_entry_title {
padding: 8px;
}
@@ -414,34 +416,6 @@ a.thumb_entry_title {
margin-right: 0px;
}
-/* collection media */
-
-.collection_thumbnail {
- float: left;
- padding: 0px;
- width: 180px;
- margin: 0px 4px 10px;
- text-align: left;
- font-size: 0.875em;
- background-color: #222;
- border-radius: 0 0 5px 5px;
- padding: 0 0 6px;
- text-overflow: ellipsis;
-}
-
-.collection_thumbnail a {
- color: #eee;
- text-decoration: none;
-}
-
-.collection_thumbnail a.remove {
- color: #86D4B1;
-}
-
-.collection_thumbnail img {
- max-height: 135px;
-}
-
/* media detail */
h2.media_title {
diff --git a/mediagoblin/static/extlib/video-js b/mediagoblin/static/extlib/video-js
new file mode 120000
index 00000000..65652d6e
--- /dev/null
+++ b/mediagoblin/static/extlib/video-js
@@ -0,0 +1 @@
+../../../extlib/video-js/ \ No newline at end of file
diff --git a/mediagoblin/static/js/extlib/video-js b/mediagoblin/static/js/extlib/video-js
deleted file mode 120000
index 35da21ca..00000000
--- a/mediagoblin/static/js/extlib/video-js
+++ /dev/null
@@ -1 +0,0 @@
-../../../../extlib/video-js \ No newline at end of file
diff --git a/mediagoblin/submit/lib.py b/mediagoblin/submit/lib.py
new file mode 100644
index 00000000..db5dfe53
--- /dev/null
+++ b/mediagoblin/submit/lib.py
@@ -0,0 +1,105 @@
+# 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 urllib
+import urllib2
+import logging
+import uuid
+from celery import registry
+from werkzeug.utils import secure_filename
+
+from mediagoblin import mg_globals
+from mediagoblin.processing import mark_entry_failed
+from mediagoblin.processing.task import ProcessMedia
+
+
+_log = logging.getLogger(__name__)
+
+
+def prepare_queue_task(app, entry, filename):
+ """
+ Prepare a MediaEntry for the processing queue and get a queue file
+ """
+ # We generate this ourselves so we know what the taks id is for
+ # retrieval later.
+
+ # (If we got it off the task's auto-generation, there'd be
+ # a risk of a race condition when we'd save after sending
+ # off the task)
+ task_id = unicode(uuid.uuid4())
+ entry.queued_task_id = task_id
+
+ # Now store generate the queueing related filename
+ queue_filepath = app.queue_store.get_unique_filepath(
+ ['media_entries',
+ task_id,
+ secure_filename(filename)])
+
+ # queue appropriately
+ queue_file = app.queue_store.get_file(
+ queue_filepath, 'wb')
+
+ # Add queued filename to the entry
+ entry.queued_media_file = queue_filepath
+
+ return queue_file
+
+
+def run_process_media(entry):
+ process_media = registry.tasks[ProcessMedia.name]
+ try:
+ process_media.apply_async(
+ [unicode(entry.id)], {},
+ task_id=entry.queued_task_id)
+ except BaseException as exc:
+ # The purpose of this section is because when running in "lazy"
+ # or always-eager-with-exceptions-propagated celery mode that
+ # the failure handling won't happen on Celery end. Since we
+ # expect a lot of users to run things in this way we have to
+ # capture stuff here.
+ #
+ # ... not completely the diaper pattern because the
+ # exception is re-raised :)
+ mark_entry_failed(entry.id, exc)
+ # re-raise the exception
+ raise
+
+
+def handle_push_urls(request):
+ if mg_globals.app_config["push_urls"]:
+ feed_url = request.urlgen(
+ 'mediagoblin.user_pages.atom_feed',
+ qualified=True,
+ user=request.user.username)
+ hubparameters = {
+ 'hub.mode': 'publish',
+ 'hub.url': feed_url}
+ hubdata = urllib.urlencode(hubparameters)
+ hubheaders = {
+ "Content-type": "application/x-www-form-urlencoded",
+ "Connection": "close"}
+ for huburl in mg_globals.app_config["push_urls"]:
+ hubrequest = urllib2.Request(huburl, hubdata, hubheaders)
+ try:
+ hubresponse = urllib2.urlopen(hubrequest)
+ except urllib2.HTTPError as exc:
+ # This is not a big issue, the item will be fetched
+ # by the PuSH server next time we hit it
+ _log.warning(
+ "push url %r gave error %r", huburl, exc.code)
+ except urllib2.URLError as exc:
+ _log.warning(
+ "push url %r is unreachable %r", huburl, exc.reason)
diff --git a/mediagoblin/submit/routing.py b/mediagoblin/submit/routing.py
index fbe3c39c..085344fd 100644
--- a/mediagoblin/submit/routing.py
+++ b/mediagoblin/submit/routing.py
@@ -14,7 +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.routing import add_route
+from mediagoblin.tools.routing import add_route
add_route('mediagoblin.submit.start',
'/submit/', 'mediagoblin.submit.views:submit_start')
diff --git a/mediagoblin/submit/views.py b/mediagoblin/submit/views.py
index 02026f45..2d609b31 100644
--- a/mediagoblin/submit/views.py
+++ b/mediagoblin/submit/views.py
@@ -16,30 +16,24 @@
from mediagoblin import messages
import mediagoblin.mg_globals as mg_globals
-import uuid
from os.path import splitext
-from celery import registry
-import urllib
-import urllib2
import logging
_log = logging.getLogger(__name__)
-from werkzeug.utils import secure_filename
from werkzeug.datastructures import FileStorage
-from mediagoblin.db.util import ObjectId
from mediagoblin.tools.text import convert_to_tag_list_of_dicts
from mediagoblin.tools.translate import pass_to_ugettext as _
from mediagoblin.tools.response import render_to_response, redirect
from mediagoblin.decorators import require_active_login
from mediagoblin.submit import forms as submit_forms
-from mediagoblin.processing import mark_entry_failed
-from mediagoblin.processing.task import ProcessMedia
from mediagoblin.messages import add_message, SUCCESS
from mediagoblin.media_types import sniff_media, \
InvalidFileType, FileTypeNotSupported
+from mediagoblin.submit.lib import handle_push_urls, run_process_media, \
+ prepare_queue_task
@require_active_login
@@ -66,7 +60,6 @@ def submit_start(request):
# create entry and save in database
entry = request.db.MediaEntry()
- entry.id = ObjectId()
entry.media_type = unicode(media_type)
entry.title = (
unicode(request.form['title'])
@@ -76,7 +69,7 @@ def submit_start(request):
entry.license = unicode(request.form.get('license', "")) or None
- entry.uploader = request.user._id
+ entry.uploader = request.user.id
# Process the user's folksonomy "tags"
entry.tags = convert_to_tag_list_of_dicts(
@@ -85,81 +78,21 @@ def submit_start(request):
# Generate a slug from the title
entry.generate_slug()
- # We generate this ourselves so we know what the taks id is for
- # retrieval later.
-
- # (If we got it off the task's auto-generation, there'd be
- # a risk of a race condition when we'd save after sending
- # off the task)
- task_id = unicode(uuid.uuid4())
-
- # Now store generate the queueing related filename
- queue_filepath = request.app.queue_store.get_unique_filepath(
- ['media_entries',
- task_id,
- secure_filename(filename)])
-
- # queue appropriately
- queue_file = request.app.queue_store.get_file(
- queue_filepath, 'wb')
+ queue_file = prepare_queue_task(request.app, entry, filename)
with queue_file:
queue_file.write(request.files['file'].stream.read())
- # Add queued filename to the entry
- entry.queued_media_file = queue_filepath
-
- entry.queued_task_id = task_id
-
# Save now so we have this data before kicking off processing
- entry.save(validate=True)
+ 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)
- process_media = registry.tasks[ProcessMedia.name]
- try:
- process_media.apply_async(
- [unicode(entry._id)], {},
- task_id=task_id)
- except BaseException as exc:
- # The purpose of this section is because when running in "lazy"
- # or always-eager-with-exceptions-propagated celery mode that
- # the failure handling won't happen on Celery end. Since we
- # expect a lot of users to run things in this way we have to
- # capture stuff here.
- #
- # ... not completely the diaper pattern because the
- # exception is re-raised :)
- mark_entry_failed(entry._id, exc)
- # re-raise the exception
- raise
+ run_process_media(entry)
- if mg_globals.app_config["push_urls"]:
- feed_url = request.urlgen(
- 'mediagoblin.user_pages.atom_feed',
- qualified=True,
- user=request.user.username)
- hubparameters = {
- 'hub.mode': 'publish',
- 'hub.url': feed_url}
- hubdata = urllib.urlencode(hubparameters)
- hubheaders = {
- "Content-type": "application/x-www-form-urlencoded",
- "Connection": "close"}
- for huburl in mg_globals.app_config["push_urls"]:
- hubrequest = urllib2.Request(huburl, hubdata, hubheaders)
- try:
- hubresponse = urllib2.urlopen(hubrequest)
- except urllib2.HTTPError as exc:
- # This is not a big issue, the item will be fetched
- # by the PuSH server next time we hit it
- _log.warning(
- "push url %r gave error %r", huburl, exc.code)
- except urllib2.URLError as exc:
- _log.warning(
- "push url %r is unreachable %r", huburl, exc.reason)
+ handle_push_urls(request)
add_message(request, SUCCESS, _('Woohoo! Submitted!'))
@@ -193,24 +126,22 @@ def add_collection(request, media=None):
if request.method == 'POST' and submit_form.validate():
try:
collection = request.db.Collection()
- collection.id = ObjectId()
collection.title = unicode(request.form['title'])
-
collection.description = unicode(request.form.get('description'))
- collection.creator = request.user._id
+ collection.creator = request.user.id
collection.generate_slug()
# Make sure this user isn't duplicating an existing collection
existing_collection = request.db.Collection.find_one({
- 'creator': request.user._id,
+ 'creator': request.user.id,
'title':collection.title})
if existing_collection:
messages.add_message(
request, messages.ERROR, _('You already have a collection called "%s"!' % collection.title))
else:
- collection.save(validate=True)
+ collection.save()
add_message(request, SUCCESS, _('Collection "%s" added!' % collection.title))
diff --git a/mediagoblin/templates/mediagoblin/admin/panel.html b/mediagoblin/templates/mediagoblin/admin/panel.html
index d3c6c958..6bcb5c24 100644
--- a/mediagoblin/templates/mediagoblin/admin/panel.html
+++ b/mediagoblin/templates/mediagoblin/admin/panel.html
@@ -42,7 +42,7 @@
</tr>
{% for media_entry in processing_entries %}
<tr>
- <td>{{ media_entry._id }}</td>
+ <td>{{ media_entry.id }}</td>
<td>{{ media_entry.get_uploader.username }}</td>
<td>{{ media_entry.title }}</td>
<td>{{ media_entry.created.strftime("%F %R") }}</td>
@@ -72,7 +72,7 @@
</tr>
{% for media_entry in failed_entries %}
<tr>
- <td>{{ media_entry._id }}</td>
+ <td>{{ media_entry.id }}</td>
<td>{{ media_entry.get_uploader.username }}</td>
<td>{{ media_entry.title }}</td>
<td>{{ media_entry.created.strftime("%F %R") }}</td>
@@ -101,7 +101,7 @@
</tr>
{% for media_entry in processed_entries %}
<tr>
- <td>{{ media_entry._id }}</td>
+ <td>{{ media_entry.id }}</td>
<td>{{ media_entry.get_uploader.username }}</td>
<td><a href="{{ media_entry.url_for_self(request.urlgen) }}">{{ media_entry.title }}</a></td>
<td>{{ media_entry.created.strftime("%F %R") }}</td>
diff --git a/mediagoblin/templates/mediagoblin/base.html b/mediagoblin/templates/mediagoblin/base.html
index 904a69d9..173bf668 100644
--- a/mediagoblin/templates/mediagoblin/base.html
+++ b/mediagoblin/templates/mediagoblin/base.html
@@ -28,8 +28,6 @@
<link rel="shortcut icon"
href="{{ request.staticdirect('/images/goblin.ico') }}" />
<script src="{{ request.staticdirect('/js/extlib/jquery.js') }}"></script>
- <script type="text/javascript"
- src="{{ request.staticdirect('/js/header_dropdown.js') }}"></script>
<!--[if lt IE 9]>
<script src="{{ request.staticdirect('/js/extlib/html5shiv.js') }}"></script>
<![endif]-->
@@ -43,13 +41,7 @@
{% block mediagoblin_body %}
{% block mediagoblin_header %}
<header>
- {% block mediagoblin_logo %}
- <a class="logo"
- href="{{ request.urlgen('index') }}"
- ><img src="{{ request.staticdirect('/images/logo.png') }}"
- alt="{% trans %}MediaGoblin logo{% endtrans %}" />
- </a>
- {% endblock mediagoblin_logo %}
+ {%- include "mediagoblin/bits/logo.html" -%}
{% block mediagoblin_header_title %}{% endblock %}
<div class="header_right">
{% if request.user %}
@@ -65,16 +57,24 @@
or <a href="{{ request.urlgen('mediagoblin.auth.logout') }}">{% trans %}log out{% endtrans %}</a>
{% endif %}
{% else %}
- <a href="{{ request.urlgen('mediagoblin.auth.login') }}">
+ <a href="{{ request.urlgen('mediagoblin.auth.login') }}?next={{
+ request.base_url|urlencode }}">
{% trans %}Log in{% endtrans %}</a>
{% endif %}
</div>
<div class="clear"></div>
{% if request.user and request.user.status == 'active' %}
<div class="header_dropdown">
- <p><span class="dropdown_title">
- <a href="{{ request.urlgen('mediagoblin.user_pages.user_home', user= request.user.username) }}">{{ request.user.username }}</a>{% trans %}'s account{% endtrans %}</span>
- (<a href="{{ request.urlgen('mediagoblin.auth.logout') }}">{% trans %}log out{% endtrans %}</a>)</p>
+ <p>
+ <span class="dropdown_title">
+ {% trans user_url=request.urlgen('mediagoblin.user_pages.user_home',
+ user=request.user.username),
+ user_name=request.user.username -%}
+ <a href="{{ user_url }}">{{ user_name }}</a>'s account
+ {%- endtrans %}
+ </span>
+ (<a href="{{ request.urlgen('mediagoblin.auth.logout') }}">{% trans %}log out{% endtrans %}</a>)
+ </p>
<ul>
<li><a class="button_action" href="{{ request.urlgen('mediagoblin.submit.start') }}">
{%- trans %}Add media{% endtrans -%}
diff --git a/mediagoblin/db/sql/__init__.py b/mediagoblin/templates/mediagoblin/bits/logo.html
index 621845ba..5bd8edd8 100644
--- a/mediagoblin/db/sql/__init__.py
+++ b/mediagoblin/templates/mediagoblin/bits/logo.html
@@ -1,3 +1,4 @@
+{#
# GNU MediaGoblin -- federated, autonomous media hosting
# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
#
@@ -13,3 +14,12 @@
#
# 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_logo %}
+ <a class="logo"
+ href="{{ request.urlgen('index') }}"
+ ><img src="{{ request.staticdirect('/images/logo.png') }}"
+ alt="{% trans %}MediaGoblin logo{% endtrans %}" />
+ </a>
+{% endblock mediagoblin_logo -%}
diff --git a/mediagoblin/templates/mediagoblin/edit/attachments.html b/mediagoblin/templates/mediagoblin/edit/attachments.html
index 641306e8..55d446de 100644
--- a/mediagoblin/templates/mediagoblin/edit/attachments.html
+++ b/mediagoblin/templates/mediagoblin/edit/attachments.html
@@ -28,7 +28,7 @@
{% block mediagoblin_content %}
<form action="{{ request.urlgen('mediagoblin.edit.attachments',
user= media.get_uploader.username,
- media= media._id) }}"
+ media= media.id) }}"
method="POST" enctype="multipart/form-data">
<div class="form_box">
<h1>
@@ -46,18 +46,21 @@
<li>
<a target="_blank" href="{{ request.app.public_store.file_url(
attachment['filepath']) }}">
- {{ attachment.name -}}
- </a><br />
+ {{- attachment.name -}}
+ </a>
</li>
{% endfor %}
</ul>
{% endif %}
- <h2>{% trans %]Add attachment{% endtrans %}</h2>
+ <h2>{% trans %}Add attachment{% endtrans %}</h2>
{{ wtforms_util.render_divs(form) }}
<div class="form_submit_buttons">
- <a href="{{ media.url_for_self(request.urlgen) }}">Cancel</a>
- <input type="submit" value="Save changes" class="button_form" />
+ <a href="{{ media.url_for_self(request.urlgen) }}">
+ {%- trans %}Cancel{% endtrans -%}
+ </a>
+ <input type="submit" value="{% trans %}Save changes{% endtrans %}"
+ class="button_form" />
{{ csrf_token }}
</div>
</div>
diff --git a/mediagoblin/templates/mediagoblin/edit/delete_account.html b/mediagoblin/templates/mediagoblin/edit/delete_account.html
new file mode 100644
index 00000000..6d56d77c
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/edit/delete_account.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 mediagoblin_content %}
+
+ <form action="{{ request.urlgen('mediagoblin.edit.delete_account') }}"
+ method="POST" enctype="multipart/form-data">
+ <div class="form_box">
+ <h1>Really delete user '{{ user.username }}' and all related media/comments?
+ </h1>
+ <p class="delete_checkbox_box">
+ <input type="checkbox" name="confirmed"/>
+ <label for="confirmed">Yes, really delete my account</label>
+ </p>
+
+ <div class="form_submit_buttons">
+ <a class="button_action" href="{{ request.urlgen(
+ 'mediagoblin.user_pages.user_home',
+ user=user.username) }}">{% trans %}Cancel{% endtrans %}</a>
+ {{ csrf_token }}
+ <input type="submit" value="{% trans %}Delete permanently{% endtrans %}" class="button_form" />
+ </div>
+ </div>
+ </form>
+{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/edit/edit.html b/mediagoblin/templates/mediagoblin/edit/edit.html
index 144184df..9a040095 100644
--- a/mediagoblin/templates/mediagoblin/edit/edit.html
+++ b/mediagoblin/templates/mediagoblin/edit/edit.html
@@ -29,7 +29,7 @@
<form action="{{ request.urlgen('mediagoblin.edit.edit_media',
user= media.get_uploader.username,
- media= media._id) }}"
+ media_id=media.id) }}"
method="POST" enctype="multipart/form-data">
<div class="form_box_xl edit_box">
<h1>{% trans media_title=media.title %}Editing {{ media_title }}{% endtrans %}</h1>
diff --git a/mediagoblin/templates/mediagoblin/edit/edit_account.html b/mediagoblin/templates/mediagoblin/edit/edit_account.html
index 38d99893..cfeb7281 100644
--- a/mediagoblin/templates/mediagoblin/edit/edit_account.html
+++ b/mediagoblin/templates/mediagoblin/edit/edit_account.html
@@ -53,4 +53,8 @@
</div>
</div>
</form>
+ <div class="delete">
+ <a href="{{request.urlgen('mediagoblin.edit.delete_account')
+ }}">Delete my account</a>
+ </div>
{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/edit/edit_profile.html b/mediagoblin/templates/mediagoblin/edit/edit_profile.html
index 2b2fa4fa..163fe186 100644
--- a/mediagoblin/templates/mediagoblin/edit/edit_profile.html
+++ b/mediagoblin/templates/mediagoblin/edit/edit_profile.html
@@ -27,9 +27,8 @@
{% block mediagoblin_content %}
- <form action="{{ request.urlgen('mediagoblin.edit.profile') }}?username={{
- user.username }}"
- method="POST" enctype="multipart/form-data">
+ <form action="{{ request.urlgen('mediagoblin.edit.profile',
+ user=user.username) }}" method="POST" enctype="multipart/form-data">
<div class="form_box edit_box">
<h1>
{%- trans username=user.username -%}
diff --git a/mediagoblin/templates/mediagoblin/media_displays/stl.html b/mediagoblin/templates/mediagoblin/media_displays/stl.html
new file mode 100644
index 00000000..043faac8
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/media_displays/stl.html
@@ -0,0 +1,150 @@
+{#
+# 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/user_pages/media.html' %}
+
+
+{% block mediagoblin_media %}
+
+
+{% set model_download = request.app.public_store.file_url(
+ media.get_display_media(media.media_files)) %}
+{% set perspective_view = request.app.public_store.file_url(
+ media.media_files['perspective']) %}
+{% set top_view = request.app.public_store.file_url(
+ media.media_files['top']) %}
+{% set side_view = request.app.public_store.file_url(
+ media.media_files['side']) %}
+{% set front_view = request.app.public_store.file_url(
+ media.media_files['front']) %}
+
+<style type="text/css">
+#top_view, #side_view, #front_view, #thingy_view {
+ display: none;
+}
+.media_image {
+ cursor: inherit!important;
+}
+
+</style>
+
+{% if media.media_data.file_type == "stl" %}
+ <script src="{{ request.staticdirect('/js/extlib/thingiview.js/Three.js') }}"></script>
+ <script src="{{ request.staticdirect('/js/extlib/thingiview.js/plane.js') }}"></script>
+ <script src="{{ request.staticdirect('/js/extlib/thingiview.js/thingiview.js') }}"></script>
+{% endif %}
+
+
+<script type="text/javascript">
+window.show = function (view_id) {
+ ids = [
+ "perspective",
+ "top_view",
+ "side_view",
+ "front_view",
+ "thingy_view",
+ ];
+ for (var i=0; i<ids.length; i+=1) {
+ id = ids[i];
+ var view = document.getElementById(id);
+ view.style.display = id===view_id ? "block" : "none";
+ }
+};
+
+window.show_things = function () {
+ document.getElementById("webgl_button").onclick = function () {
+ show('thingy_view');
+ };
+ window.show("thingy_view");
+ thingiurlbase = "{{ request.staticdirect('/js/extlib/thingiview.js') }}";
+ thingiview = new Thingiview("thingy_view");
+ thingiview.setObjectColor('#821543');
+ thingiview.initScene();
+ thingiview.loadSTL("{{ model_download }}");
+ thingiview.setRotation(false);
+};
+</script>
+
+<img
+ id="perspective"
+ class="media_image"
+ src="{{ perspective_view }}"
+ alt="{% trans media_title=media.title -%}
+ Image for {{ media_title }}{% endtrans %}" />
+<img
+ id="top_view"
+ class="media_image"
+ src="{{ top_view }}"
+ alt="{% trans media_title=media.title -%}
+ Image for {{ media_title }}{% endtrans %}" />
+<img
+ id="side_view"
+ class="media_image"
+ src="{{ side_view }}"
+ alt="{% trans media_title=media.title -%}
+ Image for {{ media_title }}{% endtrans %}" />
+<img
+ id="front_view"
+ class="media_image"
+ src="{{ front_view }}"
+ alt="{% trans media_title=media.title -%}
+ Image for {{ media_title }}{% endtrans %}" />
+<div id="thingy_view" style="width:640px;height:640px;"></div>
+
+
+<div style="padding: 4px;">
+ <a class="button_action" onclick="show('perspective');"
+ title="{%- trans %}Toggle Rotate{% endtrans -%}">
+ {%- trans %}Perspective{% endtrans -%}
+ </a>
+ <a class="button_action" onclick="show('front_view');"
+ title="{%- trans %}Front{% endtrans -%}">
+ {%- trans %}Front{% endtrans -%}
+ </a>
+ <a class="button_action" onclick="show('top_view');"
+ title="{%- trans %}Top{% endtrans -%}">
+ {%- trans %}Top{% endtrans -%}
+ </a>
+ <a class="button_action" onclick="show('side_view');"
+ title="{%- trans %}Side{% endtrans -%}">
+ {%- 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 -%}">
+ {%- trans %}WebGL{% endtrans -%}
+ </a>
+{% endif %}
+
+ <a class="button_action" href="{{ model_download }}"
+ title="{%- trans %}Download{% endtrans -%}"
+ style="float:right;">
+ {%- trans %}Download model{% endtrans -%}
+ </a>
+</div>
+
+
+{% endblock %}
+
+{% block mediagoblin_sidebar %}
+<h3>{% trans %}File Format{% endtrans %}</h3>
+<p>{{ media.media_data.file_type }}</p>
+<h3>{% trans %}Object Height{% endtrans %}</h3>
+<p>~{{ media.media_data.height|int }} mm</p>
+{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/media_displays/video.html b/mediagoblin/templates/mediagoblin/media_displays/video.html
index d72de2ca..7d5ede8d 100644
--- a/mediagoblin/templates/mediagoblin/media_displays/video.html
+++ b/mediagoblin/templates/mediagoblin/media_displays/video.html
@@ -18,34 +18,30 @@
{% extends 'mediagoblin/user_pages/media.html' %}
-{% block mediagoblin_head %}
+{% block mediagoblin_head -%}
{{ super() }}
- <script type="text/javascript"
- src="{{ request.staticdirect('/js/extlib/video-js/video.js') }}"></script>
- <link href="{{ request.staticdirect('/css/vjs-mg-skin.css') }}" rel="stylesheet">
-{% endblock %}
+ <script type="text/javascript" src="{{
+ request.staticdirect('/extlib/video-js/video.min.js') }}"></script>
+ <link href="{{ request.staticdirect('/css/vjs-mg-skin.css')
+ }}" rel="stylesheet">
+{%- endblock %}
{% block mediagoblin_media %}
- <div class="video-player" style="position: relative;">
- <video class="video-js vjs-mg-skin"
- width="{{ media.media_data.width }}"
- height="{{ media.media_data.height }}"
- controls="controls"
- preload="metadata"
- data-setup="">
- <source src="{{ request.app.public_store.file_url(
- media.media_files['webm_640']) }}"
- type="video/webm; codecs=&quot;vp8, vorbis&quot;" />
- <div class="no_html5">
- {%- trans -%}Sorry, this video will not work because
- your web browser does not support HTML5
- video.{%- endtrans -%}<br/>
- {%- trans -%}You can get a modern web browser that
- can play this video at <a href="http://getfirefox.com">
- http://getfirefox.com</a>!{%- endtrans -%}
- </div>
- </video>
- </div>
+ <video controls autoplay preload="auto" class="video-js vjs-mg-skin"
+ data-setup='{"height": {{ media.media_data.height }},
+ "width": {{ media.media_data.width }} }'>
+ <source src="{{ request.app.public_store.file_url(
+ media.media_files['webm_640']) }}"
+ type="video/webm; codecs=&quot;vp8, vorbis&quot;" />
+ <div class="no_html5">
+ {%- trans -%}Sorry, this video will not work because
+ your web browser does not support HTML5
+ video.{%- endtrans -%}<br/>
+ {%- trans -%}You can get a modern web browser that
+ can play this video at <a href="http://getfirefox.com">
+ http://getfirefox.com</a>!{%- endtrans -%}
+ </div>
+ </video>
{% endblock %}
{% block mediagoblin_sidebar %}
diff --git a/mediagoblin/templates/mediagoblin/user_pages/collection.html b/mediagoblin/templates/mediagoblin/user_pages/collection.html
index 7ea84876..5a7baadd 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/collection.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/collection.html
@@ -44,7 +44,7 @@
{{ collection_title }} by <a href="{{ user_url }}">{{ username }}</a>
{%- endtrans %}
</h1>
- {% if request.user and (collection.creator == request.user._id or
+ {% if request.user and (collection.creator == request.user.id or
request.user.is_admin) %}
{% set edit_url = request.urlgen('mediagoblin.edit.edit_collection',
user=collection.get_creator.username,
@@ -56,11 +56,11 @@
<a class="button_action" href="{{ delete_url }}">{% trans %}Delete{% endtrans %}</a>
{% endif %}
- {%- trans collection_description=collection.description -%}
<p>
- {{ collection_description }}
+ {% autoescape False %}
+ {{ collection.description_html }}
+ {% endautoescape %}
</p>
- {%- endtrans %}
{{ collection_gallery(request, collection_items, pagination) }}
diff --git a/mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html b/mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html
index 9be10321..447201cd 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/collection_item_confirm_remove.html
@@ -24,7 +24,7 @@
<form action="{{ request.urlgen('mediagoblin.user_pages.collection_item_confirm_remove',
user=collection_item.in_collection.get_creator.username,
collection=collection_item.in_collection.slug,
- collection_item=collection_item._id) }}"
+ collection_item=collection_item.id) }}"
method="POST" enctype="multipart/form-data">
<div class="form_box">
<h1>
diff --git a/mediagoblin/templates/mediagoblin/user_pages/collection_list.html b/mediagoblin/templates/mediagoblin/user_pages/collection_list.html
new file mode 100644
index 00000000..abf22623
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/user_pages/collection_list.html
@@ -0,0 +1,56 @@
+{#
+# 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 title %}
+ {%- trans username=user.username -%}
+ {{ username }}'s collections
+ {%- endtrans %} &mdash; {{ super() }}
+{% endblock %}
+
+{% block mediagoblin_content -%}
+ <h1>
+ {%- trans username=user.username,
+ user_url=request.urlgen(
+ 'mediagoblin.user_pages.user_home',
+ user=user.username) -%}
+ <a href="{{ user_url }}">{{ username }}</a>'s collections
+ {%- endtrans %}
+ </h1>
+
+ {% if request.user %}
+ {% if request.user.status == 'active' %}
+ <p>
+ <a href="{{ request.urlgen('mediagoblin.submit.collection',
+ user=user.username) }}">
+ {%- trans %}Create new collection{% endtrans -%}
+ </p>
+ {% endif %}
+ {% endif %}
+
+ <ul>
+ {% for coll in collections %}
+ {% set coll_url = request.urlgen(
+ 'mediagoblin.user_pages.user_collection',
+ user=user.username,
+ collection=coll.slug) %}
+ <li><a href="{{ coll_url }}">{{ coll.title }}</li>
+ {% endfor %}
+ </ul>
+
+{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html
index b870a8ae..10b48296 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/media.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/media.html
@@ -79,15 +79,15 @@
{{ media.title }}
</h2>
{% if request.user and
- (media.uploader == request.user._id or
+ (media.uploader == request.user.id or
request.user.is_admin) %}
{% set edit_url = request.urlgen('mediagoblin.edit.edit_media',
user= media.get_uploader.username,
- media= media._id) %}
+ media_id=media.id) %}
<a class="button_action" href="{{ edit_url }}">{% trans %}Edit{% endtrans %}</a>
{% set delete_url = request.urlgen('mediagoblin.user_pages.media_confirm_delete',
user= media.get_uploader.username,
- media= media._id) %}
+ media_id=media.id) %}
<a class="button_action" href="{{ delete_url }}">{% trans %}Delete{% endtrans %}</a>
{% endif %}
{% autoescape False %}
@@ -104,7 +104,7 @@
{% if request.user %}
<form action="{{ request.urlgen('mediagoblin.user_pages.media_post_comment',
user= media.get_uploader.username,
- media=media._id) }}" method="POST" id="form_comment">
+ media_id=media.id) }}" method="POST" id="form_comment">
<p>
{% trans %}You can use <a href="http://daringfireball.net/projects/markdown/basics">Markdown</a> for formatting.{% endtrans %}
</p>
@@ -117,11 +117,11 @@
{% endif %}
{% for comment in comments %}
{% set comment_author = comment.get_author %}
- {% if pagination.active_id == comment._id %}
- <div class="comment_wrapper comment_active" id="comment-{{ comment._id }}">
+ {% if pagination.active_id == comment.id %}
+ <div class="comment_wrapper comment_active" id="comment-{{ comment.id }}">
<a name="comment" id="comment"></a>
{% else %}
- <div class="comment_wrapper" id="comment-{{ comment._id }}">
+ <div class="comment_wrapper" id="comment-{{ comment.id }}">
{% endif %}
<div class="comment_author">
<img src="{{ request.staticdirect('/images/icon_comment.png') }}" />
@@ -131,7 +131,7 @@
</a>
{% trans %}at{% endtrans %}
<a href="{{ request.urlgen('mediagoblin.user_pages.media_home.view_comment',
- comment = comment._id,
+ comment = comment.id,
user = media.get_uploader.username,
media = media.slug_or_id) }}#comment">
{{ comment.created.strftime("%I:%M%p %Y-%m-%d") }}
@@ -173,7 +173,7 @@
{% for attachment in media.attachment_files %}
<li>
<a href="{{ request.app.public_store.file_url(attachment.filepath) }}">
- {{ attachment.name }}
+ {{- attachment.name -}}
</a>
</li>
{% endfor %}
@@ -181,7 +181,7 @@
{% endif %}
{% if app_config['allow_attachments']
and request.user
- and (media.uploader == request.user._id
+ and (media.uploader == request.user.id
or request.user.is_admin) %}
{% if not media.attachment_files|count %}
<h3>{% trans %}Attachments{% endtrans %}</h3>
@@ -189,7 +189,7 @@
<p>
<a href="{{ request.urlgen('mediagoblin.edit.attachments',
user=media.get_uploader.username,
- media=media._id) }}">{% trans %}Add attachment{% endtrans %}</a>
+ media=media.id) }}">{% trans %}Add attachment{% endtrans %}</a>
</p>
{% endif %}
@@ -197,9 +197,11 @@
<p>
<a type="submit" href="{{ request.urlgen('mediagoblin.user_pages.media_collect',
user=media.get_uploader.username,
- media=media._id) }}"
- class="button_action button_collect"
+ media=media.id) }}"
+ class="button_action"
title="{% trans %}Add media to collection{% endtrans %}">
+ <img src="{{ request.staticdirect('/images/icon_collect.png') }}"
+ />
</a>
</p>
{% endif %}
diff --git a/mediagoblin/templates/mediagoblin/user_pages/media_collect.html b/mediagoblin/templates/mediagoblin/user_pages/media_collect.html
index cefe638b..4f35dfa3 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/media_collect.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/media_collect.html
@@ -28,7 +28,7 @@
<form action="{{ request.urlgen('mediagoblin.user_pages.media_collect',
user=media.get_uploader.username,
- media=media._id) }}"
+ media=media.id) }}"
method="POST" enctype="multipart/form-data">
<div class="form_box">
<h1>
diff --git a/mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html b/mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html
index a3cf0210..d2a5655e 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html
@@ -23,7 +23,7 @@
<form action="{{ request.urlgen('mediagoblin.user_pages.media_confirm_delete',
user=media.get_uploader.username,
- media=media._id) }}"
+ media_id=media.id) }}"
method="POST" enctype="multipart/form-data">
<div class="form_box">
<h1>
diff --git a/mediagoblin/templates/mediagoblin/user_pages/processing_panel.html b/mediagoblin/templates/mediagoblin/user_pages/processing_panel.html
index e673902b..2a449d45 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/processing_panel.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/processing_panel.html
@@ -41,7 +41,7 @@
</tr>
{% for media_entry in processing_entries %}
<tr>
- <td>{{ media_entry._id }}</td>
+ <td>{{ media_entry.id }}</td>
<td>{{ media_entry.title }}</td>
<td>{{ media_entry.created.strftime("%F %R") }}</td>
{% if media_entry.transcoding_progress %}
@@ -69,7 +69,7 @@
</tr>
{% for media_entry in failed_entries %}
<tr>
- <td>{{ media_entry._id }}</td>
+ <td>{{ media_entry.id }}</td>
<td>{{ media_entry.title }}</td>
<td>{{ media_entry.created.strftime("%F %R") }}</td>
{% if media_entry.get_fail_exception() %}
@@ -97,7 +97,7 @@
</tr>
{% for entry in processed_entries %}
<tr>
- <td>{{ entry._id }}</td>
+ <td>{{ entry.id }}</td>
<td><a href="{{ entry.url_for_self(request.urlgen) }}">{{ entry.title }}</a></td>
<td>{{ entry.created.strftime("%F %R") }}</td>
</tr>
diff --git a/mediagoblin/templates/mediagoblin/user_pages/user.html b/mediagoblin/templates/mediagoblin/user_pages/user.html
index eb3bde48..76bce1e2 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/user.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/user.html
@@ -90,14 +90,13 @@
</h1>
{% if not user.url and not user.bio %}
- {% if request.user and (request.user._id == user._id) %}
+ {% if request.user and (request.user.id == user.id) %}
<div class="profile_sidebar empty_space">
<p>
{% trans %}Here's a spot to tell others about yourself.{% endtrans %}
</p>
- <a href="{{ request.urlgen('mediagoblin.edit.profile') }}?username={{
- user.username }}"
- class="button_action">
+ <a href="{{ request.urlgen('mediagoblin.edit.profile',
+ user=user.username) }}" class="button_action">
{%- trans %}Edit profile{% endtrans -%}
</a>
{% else %}
@@ -112,9 +111,9 @@
<div class="profile_sidebar">
{% include "mediagoblin/utils/profile.html" %}
{% if request.user and
- (request.user._id == user._id or request.user.is_admin) %}
- <a href="{{ request.urlgen('mediagoblin.edit.profile') }}?username={{
- user.username }}">
+ (request.user.id == user.id or request.user.is_admin) %}
+ <a href="{{ request.urlgen('mediagoblin.edit.profile',
+ user=user.username) }}">
{%- trans %}Edit profile{% endtrans -%}
</a>
{% endif %}
@@ -124,7 +123,7 @@
{% if media_entries.count() %}
<div class="profile_showcase">
{{ object_gallery(request, media_entries, pagination,
- pagination_base_url=user_gallery_url, col_number=2) }}
+ pagination_base_url=user_gallery_url, col_number=3) }}
{% include "mediagoblin/utils/object_gallery.html" %}
<div class="clear"></div>
<p>
@@ -139,7 +138,7 @@
{% include "mediagoblin/utils/feed_link.html" %}
</div>
{% else %}
- {% if request.user and (request.user._id == user._id) %}
+ {% if request.user and (request.user.id == user.id) %}
<div class="profile_showcase empty_space">
<p>
{% trans -%}
diff --git a/mediagoblin/templates/mediagoblin/utils/collection_gallery.html b/mediagoblin/templates/mediagoblin/utils/collection_gallery.html
index 5f8ffea1..dcc59244 100644
--- a/mediagoblin/templates/mediagoblin/utils/collection_gallery.html
+++ b/mediagoblin/templates/mediagoblin/utils/collection_gallery.html
@@ -20,14 +20,14 @@
{% macro media_grid(request, collection_items, col_number=5) %}
<table class="thumb_gallery">
- {% for row in gridify_cursor(collection_items, col_number) %}
+ {% for row in collection_items|batch(col_number) %}
<tr class="thumb_row
{%- if loop.first %} thumb_row_first
{%- elif loop.last %} thumb_row_last{% endif %}">
{% for item in row %}
{% set media_entry = item.get_media_entry %}
{% set entry_url = media_entry.url_for_self(request.urlgen) %}
- <td class="collection_thumbnail thumb_entry
+ <td class="media_thumbnail thumb_entry
{%- if loop.first %} thumb_entry_first
{%- elif loop.last %} thumb_entry_last{% endif %}">
<a href="{{ entry_url }}">
@@ -35,21 +35,19 @@
</a>
{% if item.note %}
- {%- trans note=item.note -%}
- <br />
- <a href="{{ entry_url }}">{{ note }}</a>
- {%- endtrans -%}
+ <a href="{{ entry_url }}">{{ item.note }}</a>
{% endif %}
{% if request.user and
- (item.in_collection.creator == request.user._id or
+ (item.in_collection.creator == request.user.id or
request.user.is_admin) %}
- {%- trans remove_url=request.urlgen(
+ {%- set remove_url=request.urlgen(
'mediagoblin.user_pages.collection_item_confirm_remove',
user=item.in_collection.get_creator.username,
collection=item.in_collection.slug,
collection_item=item.id) -%}
- <br /><a href="{{ remove_url }}" class="remove">(remove)</a>
- {%- endtrans -%}
+ <a href="{{ remove_url }}" class="remove">
+ {%- trans %}(remove){% endtrans -%}
+ </a>
{% endif %}
</td>
{% endfor %}
diff --git a/mediagoblin/templates/mediagoblin/utils/object_gallery.html b/mediagoblin/templates/mediagoblin/utils/object_gallery.html
index b4da5bc1..d328b552 100644
--- a/mediagoblin/templates/mediagoblin/utils/object_gallery.html
+++ b/mediagoblin/templates/mediagoblin/utils/object_gallery.html
@@ -20,7 +20,7 @@
{% macro media_grid(request, media_entries, col_number=5) %}
<table class="thumb_gallery">
- {% for row in gridify_cursor(media_entries, col_number) %}
+ {% for row in media_entries|batch(col_number) %}
<tr class="thumb_row
{%- if loop.first %} thumb_row_first
{%- elif loop.last %} thumb_row_last{% endif %}">
@@ -47,7 +47,7 @@
Args:
- request: Request
- - media_entries: pymongo cursor of media entries
+ - media_entries: db cursor of media entries
- pagination: Paginator object
- pagination_base_url: If you want the pagination to point to a
different URL, point it here
diff --git a/mediagoblin/tests/__init__.py b/mediagoblin/tests/__init__.py
index 4e84914a..5a3235c6 100644
--- a/mediagoblin/tests/__init__.py
+++ b/mediagoblin/tests/__init__.py
@@ -25,6 +25,10 @@ from mediagoblin.tests.tools import (
def setup_package():
suicide_if_bad_celery_environ()
+ import warnings
+ from sqlalchemy.exc import SAWarning
+ warnings.simplefilter("error", SAWarning)
+
def teardown_package():
# Remove and reinstall user_dev directories
diff --git a/mediagoblin/tests/test_api.py b/mediagoblin/tests/test_api.py
new file mode 100644
index 00000000..4b784da3
--- /dev/null
+++ b/mediagoblin/tests/test_api.py
@@ -0,0 +1,104 @@
+# 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 base64
+
+from pkg_resources import resource_filename
+
+from mediagoblin import mg_globals
+from mediagoblin.tools import template, pluginapi
+from mediagoblin.tests.tools import get_test_app, fixture_add_user
+
+
+_log = logging.getLogger(__name__)
+
+def resource(filename):
+ '''
+ Borrowed from the submission tests
+ '''
+ return resource_filename('mediagoblin.tests', 'test_submission/' + filename)
+
+
+GOOD_JPG = resource('good.jpg')
+GOOD_PNG = resource('good.png')
+EVIL_FILE = resource('evil')
+EVIL_JPG = resource('evil.jpg')
+EVIL_PNG = resource('evil.png')
+BIG_BLUE = resource('bigblue.png')
+
+
+class TestAPI(object):
+ def setUp(self):
+ self.app = get_test_app(dump_old_app=False)
+ self.db = mg_globals.database
+
+ self.user_password = u'4cc355_70k3N'
+ self.user = fixture_add_user(u'joapi', self.user_password)
+
+ def login(self):
+ self.app.post(
+ '/auth/login/', {
+ 'username': self.user.username,
+ 'password': self.user_password})
+
+ def get_context(self, template_name):
+ return template.TEMPLATE_TEST_CONTEXT[template_name]
+
+ def http_auth_headers(self):
+ return {'Authorization': 'Basic {0}'.format(
+ base64.b64encode(':'.join([
+ self.user.username,
+ self.user_password])))}
+
+ def do_post(self, data, **kwargs):
+ url = kwargs.pop('url', '/api/submit')
+ do_follow = kwargs.pop('do_follow', False)
+
+ if not 'headers' in kwargs.keys():
+ kwargs['headers'] = self.http_auth_headers()
+
+ response = self.app.post(url, data, **kwargs)
+
+ if do_follow:
+ response.follow()
+
+ return response
+
+ def upload_data(self, filename):
+ return {'upload_files': [('file', filename)]}
+
+ def test_1_test_test_view(self):
+ self.login()
+
+ response = self.app.get(
+ '/api/test',
+ headers=self.http_auth_headers())
+
+ assert response.body == \
+ '{"username": "joapi", "email": "joapi@example.com"}'
+
+ def test_2_test_submission(self):
+ self.login()
+
+ response = self.do_post(
+ {'title': 'Great JPG!'},
+ **self.upload_data(GOOD_JPG))
+
+ assert response.status_int == 200
+
+ assert self.db.MediaEntry.query.filter_by(title=u'Great JPG!').first()
diff --git a/mediagoblin/tests/test_auth.py b/mediagoblin/tests/test_auth.py
index 1b84b435..a40c9cbc 100644
--- a/mediagoblin/tests/test_auth.py
+++ b/mediagoblin/tests/test_auth.py
@@ -19,9 +19,10 @@ import datetime
from nose.tools import assert_equal
-from mediagoblin.auth import lib as auth_lib
-from mediagoblin.tests.tools import setup_fresh_app, fixture_add_user
from mediagoblin import mg_globals
+from mediagoblin.auth import lib as auth_lib
+from mediagoblin.db.models import User
+from mediagoblin.tests.tools import get_test_app, fixture_add_user
from mediagoblin.tools import template, mail
@@ -66,11 +67,11 @@ def test_bcrypt_gen_password_hash():
'notthepassword', hashed_pw, '3><7R45417')
-@setup_fresh_app
-def test_register_views(test_app):
+def test_register_views():
"""
Massive test function that all our registration-related views all work.
"""
+ test_app = get_test_app(dump_old_app=False)
# Test doing a simple GET on the page
# -----------------------------------
@@ -124,7 +125,7 @@ def test_register_views(test_app):
u'Invalid email address.']
## At this point there should be no users in the database ;)
- assert not mg_globals.database.User.find().count()
+ assert not User.query.count()
# Successful register
# -------------------
@@ -153,7 +154,7 @@ def test_register_views(test_app):
## Make sure user is logged in
request = template.TEMPLATE_TEST_CONTEXT[
'mediagoblin/user_pages/user.html']['request']
- assert request.session['user_id'] == unicode(new_user._id)
+ assert request.session['user_id'] == unicode(new_user.id)
## Make sure we get email confirmation, and try verifying
assert len(mail.EMAIL_TEST_INBOX) == 1
@@ -170,7 +171,7 @@ def test_register_views(test_app):
### user should have these same parameters
assert parsed_get_params['userid'] == [
- unicode(new_user._id)]
+ unicode(new_user.id)]
assert parsed_get_params['token'] == [
new_user.verification_key]
@@ -178,7 +179,7 @@ def test_register_views(test_app):
template.clear_test_template_context()
response = test_app.get(
"/auth/verify_email/?userid=%s&token=total_bs" % unicode(
- new_user._id))
+ new_user.id))
response.follow()
context = template.TEMPLATE_TEST_CONTEXT[
'mediagoblin/user_pages/user.html']
@@ -253,7 +254,7 @@ def test_register_views(test_app):
# 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['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
@@ -264,8 +265,8 @@ def test_register_views(test_app):
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_equal(response.status, '404 Not Found')
+ new_user.id), status=404)
+ assert_equal(response.status.split()[0], u'404') # status="404 NOT FOUND"
## Try using an expired token to change password, shouldn't work
template.clear_test_template_context()
@@ -274,7 +275,7 @@ def test_register_views(test_app):
new_user.fp_token_expire = datetime.datetime.now()
new_user.save()
response = test_app.get("%s?%s" % (path, get_params), status=404)
- assert_equal(response.status, '404 Not Found')
+ assert_equal(response.status.split()[0], u'404') # status="404 NOT FOUND"
new_user.fp_token_expire = real_token_expiration
new_user.save()
@@ -310,11 +311,11 @@ def test_register_views(test_app):
'mediagoblin/root.html')
-@setup_fresh_app
-def test_authentication_views(test_app):
+def test_authentication_views():
"""
Test logging in and logging out
"""
+ test_app = get_test_app(dump_old_app=False)
# Make a new user
test_user = fixture_add_user(active_user=False)
@@ -392,7 +393,7 @@ def test_authentication_views(test_app):
# 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)
+ assert session['user_id'] == unicode(test_user.id)
# Successful logout
# -----------------
diff --git a/mediagoblin/tests/test_csrf_middleware.py b/mediagoblin/tests/test_csrf_middleware.py
index ad433fe8..22a0eb04 100644
--- a/mediagoblin/tests/test_csrf_middleware.py
+++ b/mediagoblin/tests/test_csrf_middleware.py
@@ -14,13 +14,12 @@
# 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.tests.tools import setup_fresh_app
+from mediagoblin.tests.tools import get_test_app
from mediagoblin import mg_globals
-@setup_fresh_app
-def test_csrf_cookie_set(test_app):
-
+def test_csrf_cookie_set():
+ test_app = get_test_app(dump_old_app=False)
cookie_name = mg_globals.app_config['csrf_cookie_name']
# get login page
@@ -34,8 +33,11 @@ def test_csrf_cookie_set(test_app):
assert response.headers.get('Vary', False) == 'Cookie'
-@setup_fresh_app
-def test_csrf_token_must_match(test_app):
+def test_csrf_token_must_match():
+ # We need a fresh app for this test on webtest < 1.3.6.
+ # We do not understand why, but it fixes the tests.
+ # If we require webtest >= 1.3.6, we can switch to a non fresh app here.
+ test_app = get_test_app(dump_old_app=True)
# construct a request with no cookie or form token
assert test_app.post('/auth/login/',
@@ -44,7 +46,7 @@ def test_csrf_token_must_match(test_app):
# construct a request with a cookie, but no form token
assert test_app.post('/auth/login/',
- headers={'Cookie': str('%s=foo; ' %
+ headers={'Cookie': str('%s=foo' %
mg_globals.app_config['csrf_cookie_name'])},
extra_environ={'gmg.verify_csrf': True},
expect_errors=True).status_int == 403
@@ -52,7 +54,7 @@ def test_csrf_token_must_match(test_app):
# if both the cookie and form token are provided, they must match
assert test_app.post('/auth/login/',
{'csrf_token': 'blarf'},
- headers={'Cookie': str('%s=foo; ' %
+ headers={'Cookie': str('%s=foo' %
mg_globals.app_config['csrf_cookie_name'])},
extra_environ={'gmg.verify_csrf': True},
expect_errors=True).\
@@ -60,14 +62,13 @@ def test_csrf_token_must_match(test_app):
assert test_app.post('/auth/login/',
{'csrf_token': 'foo'},
- headers={'Cookie': str('%s=foo; ' %
+ headers={'Cookie': str('%s=foo' %
mg_globals.app_config['csrf_cookie_name'])},
extra_environ={'gmg.verify_csrf': True}).\
status_int == 200
-@setup_fresh_app
-def test_csrf_exempt(test_app):
-
+def test_csrf_exempt():
+ test_app = get_test_app(dump_old_app=False)
# monkey with the views to decorate a known endpoint
import mediagoblin.auth.views
from mediagoblin.meddleware.csrf import csrf_exempt
diff --git a/mediagoblin/tests/test_edit.py b/mediagoblin/tests/test_edit.py
index 353a7eb9..4bea9243 100644
--- a/mediagoblin/tests/test_edit.py
+++ b/mediagoblin/tests/test_edit.py
@@ -14,83 +14,122 @@
# 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 nose.tools import assert_equal
+
from mediagoblin import mg_globals
-from mediagoblin.tests.tools import setup_fresh_app, fixture_add_user
+from mediagoblin.db.models import User
+from mediagoblin.tests.tools import get_test_app, fixture_add_user
from mediagoblin.tools import template
from mediagoblin.auth.lib import bcrypt_check_password
-
-@setup_fresh_app
-def test_change_password(test_app):
- """Test changing password correctly and incorrectly"""
- # set up new user
- test_user = fixture_add_user()
-
- test_app.post(
- '/auth/login/', {
- 'username': u'chris',
- 'password': 'toast'})
-
- # test that the password can be changed
- # template.clear_test_template_context()
- test_app.post(
- '/edit/account/', {
- 'old_password': 'toast',
- 'new_password': '123456',
- 'wants_comment_notification': 'y'
- })
-
- # test_user has to be fetched again in order to have the current values
- test_user = mg_globals.database.User.one({'username': u'chris'})
-
- assert bcrypt_check_password('123456', test_user.pw_hash)
-
- # test that the password cannot be changed if the given old_password
- # is wrong
- # template.clear_test_template_context()
- test_app.post(
- '/edit/account/', {
- 'old_password': 'toast',
- 'new_password': '098765',
- })
-
- test_user = mg_globals.database.User.one({'username': u'chris'})
-
- assert not bcrypt_check_password('098765', test_user.pw_hash)
-
-
-@setup_fresh_app
-def change_bio_url(test_app):
- """Test changing bio and URL"""
- # set up new user
- test_user = fixture_add_user()
-
- # test changing the bio and the URL properly
- test_app.post(
- '/edit/profile/', {
- 'bio': u'I love toast!',
- 'url': u'http://dustycloud.org/'})
-
- test_user = mg_globals.database.User.one({'username': u'chris'})
-
- assert test_user.bio == u'I love toast!'
- assert test_user.url == u'http://dustycloud.org/'
-
- # test changing the bio and the URL inproperly
- too_long_bio = 150 * 'T' + 150 * 'o' + 150 * 'a' + 150 * 's' + 150* 't'
-
- test_app.post(
- '/edit/profile/', {
- # more than 500 characters
- 'bio': too_long_bio,
- 'url': 'this-is-no-url'})
-
- test_user = mg_globals.database.User.one({'username': u'chris'})
-
- context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/edit/edit_profile.html']
- form = context['edit_profile_form']
-
- assert form.bio.errors == [u'Field must be between 0 and 500 characters long.']
- assert form.url.errors == [u'Improperly formed URL']
-
- # test changing the url inproperly
+class TestUserEdit(object):
+ def setUp(self):
+ self.app = get_test_app(dump_old_app=False)
+ # set up new user
+ self.user_password = u'toast'
+ self.user = fixture_add_user(password = self.user_password)
+ self.login()
+
+ def login(self):
+ self.app.post(
+ '/auth/login/', {
+ 'username': self.user.username,
+ 'password': self.user_password})
+
+
+ def test_user_deletion(self):
+ """Delete user via web interface"""
+ # Make sure user exists
+ assert User.query.filter_by(username=u'chris').first()
+
+ res = self.app.post('/edit/account/delete/', {'confirmed': 'y'})
+
+ # Make sure user has been deleted
+ assert User.query.filter_by(username=u'chris').first() == None
+
+ #TODO: make sure all corresponding items comments etc have been
+ # deleted too. Perhaps in submission test?
+
+ #Restore user at end of test
+ self.user = fixture_add_user(password = self.user_password)
+ self.login()
+
+
+ def test_change_password(self):
+ """Test changing password correctly and incorrectly"""
+ # test that the password can be changed
+ # template.clear_test_template_context()
+ res = self.app.post(
+ '/edit/account/', {
+ 'old_password': 'toast',
+ 'new_password': '123456',
+ 'wants_comment_notification': 'y'
+ })
+
+ # Check for redirect on success
+ assert_equal(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)
+ # 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()
+ self.app.post(
+ '/edit/account/', {
+ '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)
+
+
+
+ def test_change_bio_url(self):
+ """Test changing bio and URL"""
+ # Test if legacy profile editing URL redirects correctly
+ res = self.app.post(
+ '/edit/profile/', {
+ 'bio': u'I love toast!',
+ 'url': u'http://dustycloud.org/'}, expect_errors=True)
+
+ # Should redirect to /u/chris/edit/
+ assert_equal (res.status_int, 302)
+ assert res.headers['Location'].endswith("/u/chris/edit/")
+
+ res = self.app.post(
+ '/u/chris/edit/', {
+ 'bio': u'I love toast!',
+ 'url': u'http://dustycloud.org/'})
+
+ test_user = User.query.filter_by(username=u'chris').first()
+ assert_equal(test_user.bio, u'I love toast!')
+ assert_equal(test_user.url, u'http://dustycloud.org/')
+
+ # change a different user than the logged in (should fail with 403)
+ fixture_add_user(username=u"foo")
+ res = self.app.post(
+ '/u/foo/edit/', {
+ 'bio': u'I love toast!',
+ 'url': u'http://dustycloud.org/'}, expect_errors=True)
+ assert_equal(res.status_int, 403)
+
+ # test changing the bio and the URL inproperly
+ too_long_bio = 150 * 'T' + 150 * 'o' + 150 * 'a' + 150 * 's' + 150* 't'
+
+ self.app.post(
+ '/u/chris/edit/', {
+ # more than 500 characters
+ 'bio': too_long_bio,
+ 'url': 'this-is-no-url'})
+
+ # Check form errors
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/edit/edit_profile.html']
+ form = context['form']
+
+ assert_equal(form.bio.errors, [u'Field must be between 0 and 500 characters long.'])
+ assert_equal(form.url.errors, [u'This address contains errors'])
+
+# test changing the url inproperly
diff --git a/mediagoblin/tests/test_exif.py b/mediagoblin/tests/test_exif.py
index ed95045c..100d17f0 100644
--- a/mediagoblin/tests/test_exif.py
+++ b/mediagoblin/tests/test_exif.py
@@ -58,10 +58,10 @@ def test_exif_extraction():
gps = get_gps_data(result)
# Do we have the result?
- assert len(result) == 108
+ assert len(result) == 56
# Do we have clean data?
- assert len(clean) == 105
+ assert len(clean) == 53
# GPS data?
assert gps == {}
@@ -70,7 +70,7 @@ def test_exif_extraction():
assert useful == {
'EXIF Flash': {
'field_type': 3,
- 'printable': 'No',
+ 'printable': u'Flash did not fire',
'field_offset': 380,
'tag': 37385,
'values': [0],
@@ -123,18 +123,7 @@ def test_exif_extraction():
'field_offset': 708,
'tag': 33437,
'values': [[10, 1]],
- 'field_length': 8},
- 'EXIF UserComment': {
- 'field_type': 7,
- 'printable': 'Joar Wandborg ',
- 'field_offset': 26180,
- 'tag': 37510,
- 'values': [
- 65, 83, 67, 73, 73, 0, 0, 0, 74, 111, 97, 114, 32, 87,
- 97, 110, 100, 98, 111, 114, 103, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32],
- 'field_length': 44}}
+ 'field_length': 8}}
def test_exif_image_orientation():
diff --git a/mediagoblin/tests/test_globals.py b/mediagoblin/tests/test_globals.py
index 98f6a436..303f89e2 100644
--- a/mediagoblin/tests/test_globals.py
+++ b/mediagoblin/tests/test_globals.py
@@ -18,23 +18,20 @@ from nose.tools import assert_raises
from mediagoblin import mg_globals
+
class TestGlobals(object):
def setUp(self):
- self.old_connection = mg_globals.db_connection
self.old_database = mg_globals.database
def tearDown(self):
- mg_globals.db_connection = self.old_connection
mg_globals.database = self.old_database
def test_setup_globals(self):
mg_globals.setup_globals(
- db_connection='my favorite db_connection!',
database='my favorite database!',
public_store='my favorite public_store!',
queue_store='my favorite queue_store!')
- assert mg_globals.db_connection == 'my favorite db_connection!'
assert mg_globals.database == 'my favorite database!'
assert mg_globals.public_store == 'my favorite public_store!'
assert mg_globals.queue_store == 'my favorite queue_store!'
diff --git a/mediagoblin/tests/test_http_callback.py b/mediagoblin/tests/test_http_callback.py
index d769af1e..0f6e489f 100644
--- a/mediagoblin/tests/test_http_callback.py
+++ b/mediagoblin/tests/test_http_callback.py
@@ -27,11 +27,11 @@ from mediagoblin.tests import test_oauth as oauth
class TestHTTPCallback(object):
def setUp(self):
- self.app = get_test_app()
+ self.app = get_test_app(dump_old_app=False)
self.db = mg_globals.database
- self.user_password = 'secret'
- self.user = fixture_add_user('call_back', self.user_password)
+ self.user_password = u'secret'
+ self.user = fixture_add_user(u'call_back', self.user_password)
self.login()
diff --git a/mediagoblin/tests/test_messages.py b/mediagoblin/tests/test_messages.py
index d3b84828..c587e599 100644
--- a/mediagoblin/tests/test_messages.py
+++ b/mediagoblin/tests/test_messages.py
@@ -15,30 +15,31 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from mediagoblin.messages import fetch_messages, add_message
-from mediagoblin.tests.tools import setup_fresh_app
+from mediagoblin.tests.tools import get_test_app
from mediagoblin.tools import template
-@setup_fresh_app
-def test_messages(test_app):
+
+def test_messages():
"""
Added messages should show up in the request.session,
fetched messages should be the same as the added ones,
and fetching should clear the message list.
"""
+ test_app = get_test_app(dump_old_app=False)
# Aquire a request object
test_app.get('/')
context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html']
request = context['request']
-
+
# The message queue should be empty
assert request.session.get('messages', []) == []
-
+
# Adding a message should modify the session accordingly
add_message(request, 'herp_derp', 'First!')
test_msg_queue = [{'text': 'First!', 'level': 'herp_derp'}]
assert request.session['messages'] == test_msg_queue
-
+
# fetch_messages should return and empty the queue
assert fetch_messages(request) == test_msg_queue
assert request.session.get('messages') == []
diff --git a/mediagoblin/tests/test_mgoblin_app.ini b/mediagoblin/tests/test_mgoblin_app.ini
index cde61a70..42d3785a 100644
--- a/mediagoblin/tests/test_mgoblin_app.ini
+++ b/mediagoblin/tests/test_mgoblin_app.ini
@@ -35,3 +35,5 @@ BROKER_HOST = "sqlite:///%(here)s/test_user_dev/kombu.db"
[plugins]
[[mediagoblin.plugins.api]]
[[mediagoblin.plugins.oauth]]
+[[mediagoblin.plugins.httpapiauth]]
+
diff --git a/mediagoblin/tests/test_misc.py b/mediagoblin/tests/test_misc.py
index 94ae5a51..8a96e7d0 100644
--- a/mediagoblin/tests/test_misc.py
+++ b/mediagoblin/tests/test_misc.py
@@ -16,11 +16,9 @@
from nose.tools import assert_equal
-from mediagoblin.tests.tools import setup_fresh_app
+from mediagoblin.tests.tools import get_test_app
-
-@setup_fresh_app
-def test_404_for_non_existent(test_app):
- assert_equal(test_app.get('/does-not-exist/',
- expect_errors=True).status_int,
- 404)
+def test_404_for_non_existent():
+ test_app = get_test_app(dump_old_app=False)
+ res = test_app.get('/does-not-exist/', expect_errors=True)
+ assert_equal(res.status_int, 404)
diff --git a/mediagoblin/tests/test_oauth.py b/mediagoblin/tests/test_oauth.py
index db4e226a..a72f766e 100644
--- a/mediagoblin/tests/test_oauth.py
+++ b/mediagoblin/tests/test_oauth.py
@@ -34,8 +34,8 @@ class TestOAuth(object):
self.pman = pluginapi.PluginManager()
- self.user_password = '4cc355_70k3N'
- self.user = fixture_add_user('joauth', self.user_password)
+ self.user_password = u'4cc355_70k3N'
+ self.user = fixture_add_user(u'joauth', self.user_password)
self.login()
@@ -59,13 +59,13 @@ class TestOAuth(object):
def test_1_public_client_registration_without_redirect_uri(self):
''' Test 'public' OAuth client registration without any redirect uri '''
- response = self.register_client('OMGOMGOMG', 'public',
+ response = self.register_client(u'OMGOMGOMG', 'public',
'OMGOMG Apache License v2')
ctx = self.get_context('oauth/client/register.html')
client = self.db.OAuthClient.query.filter(
- self.db.OAuthClient.name == 'OMGOMGOMG').first()
+ self.db.OAuthClient.name == u'OMGOMGOMG').first()
assert response.status_int == 200
@@ -78,23 +78,23 @@ class TestOAuth(object):
def test_2_successful_public_client_registration(self):
''' Successfully register a public client '''
self.login()
- self.register_client('OMGOMG', 'public', 'OMG!',
+ self.register_client(u'OMGOMG', 'public', 'OMG!',
'http://foo.example')
client = self.db.OAuthClient.query.filter(
- self.db.OAuthClient.name == 'OMGOMG').first()
+ self.db.OAuthClient.name == u'OMGOMG').first()
# Client should have been registered
assert client
def test_3_successful_confidential_client_reg(self):
''' Register a confidential OAuth client '''
- response = self.register_client('GMOGMO', 'confidential', 'NO GMO!')
+ response = self.register_client(u'GMOGMO', 'confidential', 'NO GMO!')
assert response.status_int == 302
client = self.db.OAuthClient.query.filter(
- self.db.OAuthClient.name == 'GMOGMO').first()
+ self.db.OAuthClient.name == u'GMOGMO').first()
# Client should have been registered
assert client
@@ -103,6 +103,7 @@ class TestOAuth(object):
def test_4_authorize_confidential_client(self):
''' Authorize a confidential client as a logged in user '''
+
client = self.test_3_successful_confidential_client_reg()
client_identifier = client.identifier
diff --git a/mediagoblin/tests/test_sql_migrations.py b/mediagoblin/tests/test_sql_migrations.py
index e3b55634..2fc4c043 100644
--- a/mediagoblin/tests/test_sql_migrations.py
+++ b/mediagoblin/tests/test_sql_migrations.py
@@ -25,8 +25,8 @@ from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.sql import select, insert
from migrate import changeset
-from mediagoblin.db.sql.base import GMGTableBase
-from mediagoblin.db.sql.util import MigrationManager, RegisterMigration
+from mediagoblin.db.base import GMGTableBase
+from mediagoblin.db.migration_tools import MigrationManager, RegisterMigration
from mediagoblin.tools.common import CollectingPrinter
@@ -322,6 +322,28 @@ def creature_power_hitpower_to_float(db_conn):
creature_power.c.hitpower.alter(type=Float)
+@RegisterMigration(8, FULL_MIGRATIONS)
+def creature_power_name_creature_unique(db_conn):
+ """
+ Add a unique constraint to name and creature on creature_power.
+
+ We don't want multiple creature powers with the same name per creature!
+ """
+ # Note: We don't actually check to see if this constraint is set
+ # up because at present there's no way to do so in sqlalchemy :\
+
+ metadata = MetaData(bind=db_conn.bind)
+
+ creature_power = Table(
+ 'creature_power', metadata,
+ autoload=True, autoload_with=db_conn.bind)
+
+ cons = changeset.constraint.UniqueConstraint(
+ 'name', 'creature', table=creature_power)
+
+ cons.create()
+
+
def _insert_migration1_objects(session):
"""
Test objects to insert for the first set of things
@@ -660,7 +682,7 @@ def test_set1_to_set3():
u'__main__', SET3_MODELS, SET3_MIGRATIONS, Session(),
printer)
- assert migration_manager.latest_migration == 7
+ assert migration_manager.latest_migration == 8
assert migration_manager.database_current_migration == 0
# Migrate
@@ -679,14 +701,15 @@ def test_set1_to_set3():
+ Running migration 5, "level_exit_index_from_and_to_level"... done.
+ Running migration 6, "creature_power_index_creature"... done.
+ Running migration 7, "creature_power_hitpower_to_float"... done.
+ + Running migration 8, "creature_power_name_creature_unique"... done.
"""
# Make sure version matches expected
migration_manager = MigrationManager(
u'__main__', SET3_MODELS, SET3_MIGRATIONS, Session(),
printer)
- assert migration_manager.latest_migration == 7
- assert migration_manager.database_current_migration == 7
+ assert migration_manager.latest_migration == 8
+ assert migration_manager.database_current_migration == 8
# Check all things in database match expected
diff --git a/mediagoblin/tests/test_storage.py b/mediagoblin/tests/test_storage.py
index 6fc2e57c..61326ae9 100644
--- a/mediagoblin/tests/test_storage.py
+++ b/mediagoblin/tests/test_storage.py
@@ -18,7 +18,7 @@
import os
import tempfile
-from nose.tools import assert_raises
+from nose.tools import assert_raises, assert_equal, assert_true
from werkzeug.utils import secure_filename
from mediagoblin import storage
@@ -78,9 +78,10 @@ def test_storage_system_from_config():
'garbage_arg': 'garbage_arg',
'storage_class':
'mediagoblin.tests.test_storage:FakeStorageSystem'})
- assert this_storage.foobie == 'eiboof'
- assert this_storage.blech == 'hcelb'
- assert this_storage.__class__ is FakeStorageSystem
+ assert_equal(this_storage.foobie, 'eiboof')
+ assert_equal(this_storage.blech, 'hcelb')
+ assert_equal(unicode(this_storage.__class__),
+ u'mediagoblin.tests.test_storage.FakeStorageSystem')
##########################
diff --git a/mediagoblin/tests/test_submission.py b/mediagoblin/tests/test_submission.py
index b7b0e574..53330c48 100644
--- a/mediagoblin/tests/test_submission.py
+++ b/mediagoblin/tests/test_submission.py
@@ -28,7 +28,7 @@ from mediagoblin.tests.tools import get_test_app, \
fixture_add_user
from mediagoblin import mg_globals
from mediagoblin.tools import template
-
+from mediagoblin.media_types.image import MEDIA_MANAGER as img_MEDIA_MANAGER
def resource(filename):
return resource_filename('mediagoblin.tests', 'test_submission/' + filename)
@@ -50,7 +50,7 @@ REQUEST_CONTEXT = ['mediagoblin/user_pages/user.html', 'request']
class TestSubmission:
def setUp(self):
- self.test_app = get_test_app()
+ self.test_app = get_test_app(dump_old_app=False)
# TODO: Possibly abstract into a decorator like:
# @as_authenticated_user('chris')
@@ -132,11 +132,11 @@ class TestSubmission:
def test_tags(self):
# Good tag string
# --------
- response, request = self.do_post({'title': u'Balanced Goblin',
+ response, request = self.do_post({'title': u'Balanced Goblin 2',
'tags': GOOD_TAG_STRING},
*REQUEST_CONTEXT, do_follow=True,
**self.upload_data(GOOD_JPG))
- media = self.check_media(request, {'title': u'Balanced Goblin'}, 1)
+ media = self.check_media(request, {'title': u'Balanced Goblin 2'}, 1)
assert media.tags[0]['name'] == u'yin'
assert media.tags[0]['slug'] == u'yin'
@@ -145,7 +145,7 @@ class TestSubmission:
# Test tags that are too long
# ---------------
- response, form = self.do_post({'title': u'Balanced Goblin',
+ response, form = self.do_post({'title': u'Balanced Goblin 2',
'tags': BAD_TAG_STRING},
*FORM_CONTEXT,
**self.upload_data(GOOD_JPG))
@@ -161,11 +161,17 @@ class TestSubmission:
media = self.check_media(request, {'title': u'Balanced Goblin'}, 1)
media_id = media.id
+ # At least render the edit page
+ edit_url = request.urlgen(
+ 'mediagoblin.edit.edit_media',
+ user=self.test_user.username, media_id=media_id)
+ self.test_app.get(edit_url)
+
# Add a comment, so we can test for its deletion later.
self.check_comments(request, media_id, 0)
comment_url = request.urlgen(
'mediagoblin.user_pages.media_post_comment',
- user=self.test_user.username, media=media_id)
+ user=self.test_user.username, media_id=media_id)
response = self.do_post({'comment_content': 'i love this test'},
url=comment_url, do_follow=True)[0]
self.check_comments(request, media_id, 1)
@@ -174,7 +180,7 @@ class TestSubmission:
# ---------------------------------------------------
delete_url = request.urlgen(
'mediagoblin.user_pages.media_confirm_delete',
- user=self.test_user.username, media=media_id)
+ user=self.test_user.username, media_id=media_id)
# Empty data means don't confirm
response = self.do_post({}, do_follow=True, url=delete_url)[0]
media = self.check_media(request, {'title': u'Balanced Goblin'}, 1)
@@ -184,7 +190,7 @@ class TestSubmission:
# ---------------------------------------------------
response, request = self.do_post({'confirm': 'y'}, *REQUEST_CONTEXT,
do_follow=True, url=delete_url)
- self.check_media(request, {'_id': media_id}, 0)
+ self.check_media(request, {'id': media_id}, 0)
self.check_comments(request, media_id, 0)
def test_evil_file(self):
@@ -197,6 +203,19 @@ class TestSubmission:
assert 'Sorry, I don\'t support that file type :(' == \
str(form.file.errors[0])
+
+ def test_get_media_manager(self):
+ """Test if the get_media_manger function returns sensible things
+ """
+ response, request = self.do_post({'title': u'Balanced Goblin'},
+ *REQUEST_CONTEXT, do_follow=True,
+ **self.upload_data(GOOD_JPG))
+ media = self.check_media(request, {'title': u'Balanced Goblin'}, 1)
+
+ assert_equal(media.media_type, u'mediagoblin.media_types.image')
+ assert_equal(media.media_manager, img_MEDIA_MANAGER)
+
+
def test_sniffing(self):
'''
Test sniffing mechanism to assert that regular uploads work as intended
diff --git a/mediagoblin/tests/test_tags.py b/mediagoblin/tests/test_tags.py
index bc657660..73af2eea 100644
--- a/mediagoblin/tests/test_tags.py
+++ b/mediagoblin/tests/test_tags.py
@@ -14,17 +14,17 @@
# 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.tests.tools import setup_fresh_app
+from mediagoblin.tests.tools import get_test_app
from mediagoblin.tools import text
-@setup_fresh_app
-def test_list_of_dicts_conversion(test_app):
+def test_list_of_dicts_conversion():
"""
When the user adds tags to a media entry, the string from the form is
converted into a list of tags, where each tag is stored in the database
as a dict. Each tag dict should contain the tag's name and slug. Another
function performs the reverse operation when populating a form to edit tags.
"""
+ test_app = get_test_app(dump_old_app=False)
# Leading, trailing, and internal whitespace should be removed and slugified
assert text.convert_to_tag_list_of_dicts('sleep , 6 AM, chainsaw! ') == [
{'name': u'sleep', 'slug': u'sleep'},
diff --git a/mediagoblin/tests/test_tests.py b/mediagoblin/tests/test_tests.py
index 20832ac7..d09e8f28 100644
--- a/mediagoblin/tests/test_tests.py
+++ b/mediagoblin/tests/test_tests.py
@@ -14,25 +14,23 @@
# 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.tests.tools import get_test_app
-
from mediagoblin import mg_globals
+from mediagoblin.tests.tools import get_test_app, fixture_add_user
+from mediagoblin.db.models import User
def test_get_test_app_wipes_db():
"""
Make sure we get a fresh database on every wipe :)
"""
- get_test_app()
- assert mg_globals.database.User.find().count() == 0
+ get_test_app(dump_old_app=True)
+ assert User.query.count() == 0
- new_user = mg_globals.database.User()
- new_user.username = u'lolcat'
- new_user.email = u'lol@cats.example.org'
- new_user.pw_hash = u'pretend_this_is_a_hash'
- new_user.save()
- assert mg_globals.database.User.find().count() == 1
+ fixture_add_user()
+ assert User.query.count() == 1
- get_test_app()
+ get_test_app(dump_old_app=False)
+ assert User.query.count() == 1
- assert mg_globals.database.User.find().count() == 0
+ get_test_app(dump_old_app=True)
+ assert User.query.count() == 0
diff --git a/mediagoblin/tests/test_util.py b/mediagoblin/tests/test_util.py
index 452090e1..e4c04b7a 100644
--- a/mediagoblin/tests/test_util.py
+++ b/mediagoblin/tests/test_util.py
@@ -70,13 +70,13 @@ I hope you like unit tests JUST AS MUCH AS I DO!"""
I hope you like unit tests JUST AS MUCH AS I DO!"""
def test_slugify():
- assert url.slugify('a walk in the park') == 'a-walk-in-the-park'
- assert url.slugify('A Walk in the Park') == 'a-walk-in-the-park'
- assert url.slugify('a walk in the park') == 'a-walk-in-the-park'
- assert url.slugify('a walk in-the-park') == 'a-walk-in-the-park'
- assert url.slugify('a w@lk in the park?') == 'a-w-lk-in-the-park'
- assert url.slugify(u'a walk in the par\u0107') == 'a-walk-in-the-parc'
- assert url.slugify(u'\u00E0\u0042\u00E7\u010F\u00EB\u0066') == 'abcdef'
+ assert url.slugify(u'a walk in the park') == u'a-walk-in-the-park'
+ assert url.slugify(u'A Walk in the Park') == u'a-walk-in-the-park'
+ assert url.slugify(u'a walk in the park') == u'a-walk-in-the-park'
+ assert url.slugify(u'a walk in-the-park') == u'a-walk-in-the-park'
+ assert url.slugify(u'a w@lk in the park?') == u'a-w-lk-in-the-park'
+ assert url.slugify(u'a walk in the par\u0107') == u'a-walk-in-the-parc'
+ assert url.slugify(u'\u00E0\u0042\u00E7\u010F\u00EB\u0066') == u'abcdef'
def test_locale_to_lower_upper():
"""
diff --git a/mediagoblin/tests/test_workbench.py b/mediagoblin/tests/test_workbench.py
index 04a74653..9da8eea0 100644
--- a/mediagoblin/tests/test_workbench.py
+++ b/mediagoblin/tests/test_workbench.py
@@ -19,6 +19,8 @@ import tempfile
from mediagoblin import workbench
+from mediagoblin.mg_globals import setup_globals
+from mediagoblin.decorators import get_workbench
from mediagoblin.tests.test_storage import get_tmp_filestorage
@@ -28,19 +30,20 @@ class TestWorkbench(object):
os.path.join(tempfile.gettempdir(), u'mgoblin_workbench_testing'))
def test_create_workbench(self):
- workbench = self.workbench_manager.create_workbench()
+ workbench = self.workbench_manager.create()
assert os.path.isdir(workbench.dir)
assert workbench.dir.startswith(self.workbench_manager.base_workbench_dir)
+ workbench.destroy()
def test_joinpath(self):
- this_workbench = self.workbench_manager.create_workbench()
+ this_workbench = self.workbench_manager.create()
tmpname = this_workbench.joinpath('temp.txt')
assert tmpname == os.path.join(this_workbench.dir, 'temp.txt')
- this_workbench.destroy_self()
+ this_workbench.destroy()
def test_destroy_workbench(self):
# kill a workbench
- this_workbench = self.workbench_manager.create_workbench()
+ this_workbench = self.workbench_manager.create()
tmpfile_name = this_workbench.joinpath('temp.txt')
tmpfile = file(tmpfile_name, 'w')
with tmpfile:
@@ -49,14 +52,14 @@ class TestWorkbench(object):
assert os.path.exists(tmpfile_name)
wb_dir = this_workbench.dir
- this_workbench.destroy_self()
+ this_workbench.destroy()
assert not os.path.exists(tmpfile_name)
assert not os.path.exists(wb_dir)
def test_localized_file(self):
tmpdir, this_storage = get_tmp_filestorage()
- this_workbench = self.workbench_manager.create_workbench()
-
+ this_workbench = self.workbench_manager.create()
+
# Write a brand new file
filepath = ['dir1', 'dir2', 'ourfile.txt']
@@ -78,7 +81,7 @@ class TestWorkbench(object):
filename = this_workbench.localized_file(this_storage, filepath)
assert filename == os.path.join(
this_workbench.dir, 'ourfile.txt')
-
+
# fake remote file storage, filename_if_copying set
filename = this_workbench.localized_file(
this_storage, filepath, 'thisfile')
@@ -91,3 +94,18 @@ class TestWorkbench(object):
this_storage, filepath, 'thisfile.text', False)
assert filename == os.path.join(
this_workbench.dir, 'thisfile.text')
+
+ def test_workbench_decorator(self):
+ """Test @get_workbench decorator and automatic cleanup"""
+ # The decorator needs mg_globals.workbench_manager
+ setup_globals(workbench_manager=self.workbench_manager)
+
+ @get_workbench
+ def create_it(workbench=None):
+ # workbench dir exists?
+ assert os.path.isdir(workbench.dir)
+ return workbench.dir
+
+ benchdir = create_it()
+ # workbench dir has been cleaned up automatically?
+ assert not os.path.isdir(benchdir)
diff --git a/mediagoblin/tests/tools.py b/mediagoblin/tests/tools.py
index d3369831..3e78b2e3 100644
--- a/mediagoblin/tests/tools.py
+++ b/mediagoblin/tests/tools.py
@@ -25,10 +25,11 @@ from paste.deploy import loadapp
from webtest import TestApp
from mediagoblin import mg_globals
+from mediagoblin.db.models import User
from mediagoblin.tools import testing
from mediagoblin.init.config import read_mediagoblin_config
from mediagoblin.db.open import setup_connection_and_db_from_config
-from mediagoblin.db.sql.base import Session
+from mediagoblin.db.base import Session
from mediagoblin.meddleware import BaseMeddleware
from mediagoblin.auth.lib import bcrypt_gen_password_hash
from mediagoblin.gmg_commands.dbupdate import run_dbupdate
@@ -78,7 +79,7 @@ class TestingMeddleware(BaseMeddleware):
def process_response(self, request, response):
# All following tests should be for html only!
- if response.content_type != "text/html":
+ if getattr(response, 'content_type', None) != "text/html":
# Get out early
return
@@ -184,27 +185,30 @@ def assert_db_meets_expected(db, expected):
"""
Assert a database contains the things we expect it to.
- Objects are found via '_id', so you should make sure your document
- has an _id.
+ Objects are found via 'id', so you should make sure your document
+ has an id.
Args:
- db: pymongo or mongokit database connection
- expected: the data we expect. Formatted like:
{'collection_name': [
- {'_id': 'foo',
+ {'id': 'foo',
'some_field': 'some_value'},]}
"""
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.find_one({'id': expected_document['id']})
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='toast',
+def fixture_add_user(username=u'chris', password=u'toast',
active_user=True):
- test_user = mg_globals.database.User()
+ # Reuse existing user or create a new one
+ test_user = User.query.filter_by(username=username).first()
+ if test_user is None:
+ test_user = User()
test_user.username = username
test_user.email = username + u'@example.com'
if password is not None:
@@ -216,10 +220,9 @@ def fixture_add_user(username=u'chris', password='toast',
test_user.save()
# Reload
- test_user = mg_globals.database.User.find_one({'username': username})
+ test_user = User.query.filter_by(username=username).first()
# ... and detach from session:
- from mediagoblin.db.sql.base import Session
Session.expunge(test_user)
return test_user
diff --git a/mediagoblin/themes/airy/assets/css/airy.css b/mediagoblin/themes/airy/assets/css/airy.css
index c63345b2..c4bea5cb 100644
--- a/mediagoblin/themes/airy/assets/css/airy.css
+++ b/mediagoblin/themes/airy/assets/css/airy.css
@@ -33,6 +33,12 @@ header {
margin-right: auto;
}
+@media screen and (max-width: 940px) {
+ header {
+ width: 100%;
+ }
+}
+
footer {
border-top: 1px solid #E4E4E4;
}
diff --git a/mediagoblin/themes/airy/templates/mediagoblin/base.html b/mediagoblin/themes/airy/templates/mediagoblin/base.html
deleted file mode 100644
index db500199..00000000
--- a/mediagoblin/themes/airy/templates/mediagoblin/base.html
+++ /dev/null
@@ -1,94 +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/>.
--#}
-<!doctype html>
-<html>
- <head>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>{% block title %}{{ app_config['html_title'] }}{% endblock %}</title>
- <link rel="stylesheet" type="text/css"
- href="{{ request.staticdirect('/css/extlib/reset.css') }}"/>
- <link rel="stylesheet" type="text/css"
- href="{{ request.staticdirect('/css/base.css') }}"/>
- <link rel="shortcut icon"
- href="{{ request.staticdirect('/images/goblin.ico') }}" />
- <script src="{{ request.staticdirect('/js/extlib/jquery.js') }}"></script>
- <script type="text/javascript"
- src="{{ request.staticdirect('/js/header_dropdown.js') }}"></script>
- <!--[if lt IE 9]>
- <script src="{{ request.staticdirect('/js/extlib/html5shiv.js') }}"></script>
- <![endif]-->
-
- {% include "mediagoblin/extra_head.html" %}
-
- {% block mediagoblin_head %}
- {% endblock mediagoblin_head %}
- </head>
- <body>
- {% block mediagoblin_body %}
- {% block mediagoblin_header %}
- <header>
- {% block mediagoblin_logo %}
- <a class="logo"
- href="{{ request.urlgen('index') }}">
- <img src="{{ request.staticdirect('/images/logo.png', 'theme') }}"
- alt="{% trans %}MediaGoblin logo{% endtrans %}" />
- </a>
- {% endblock mediagoblin_logo %}
- {% block mediagoblin_header_title %}{% endblock %}
- <div class="header_right">
- {% if request.user %}
- <a href="{{ request.urlgen('mediagoblin.user_pages.user_home', user= request.user.username) }}">{{ request.user.username }}</a>{% trans %}'s account{% endtrans %}
- (<a href="{{ request.urlgen('mediagoblin.auth.logout') }}">{% trans %}log out{% endtrans %}</a>)
- {% if request.user and request.user.status == 'active' %}
- <a class="button_action" href="{{ request.urlgen('mediagoblin.submit.start') }}">{% trans %}Add media{% endtrans %}</a>
- {% elif request.user and request.user.status == "needs_email_verification" %}
- {# the following link should only appear when verification is needed #}
- <a href="{{ request.urlgen('mediagoblin.user_pages.user_home',
- user=request.user.username) }}"
- class="button_action_highlight">
- {% trans %}Verify your email!{% endtrans %}</a>
- {% endif %}
- {% else %}
- <a href="{{ request.urlgen('mediagoblin.auth.login') }}">
- {% trans %}Log in{% endtrans %}</a>
- {% endif %}
- </div>
- <div class="clear"></div>
- </header>
- {% endblock %}
- <div class="container">
- <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">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 %}
- {% endblock mediagoblin_body %}
- </div>
- </body>
-</html>
diff --git a/mediagoblin/gmg_commands/mongosql.py b/mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html
index dd53f575..c8500159 100644
--- a/mediagoblin/gmg_commands/mongosql.py
+++ b/mediagoblin/themes/airy/templates/mediagoblin/bits/logo.html
@@ -1,3 +1,4 @@
+{#
# GNU MediaGoblin -- federated, autonomous media hosting
# Copyright (C) 2012 MediaGoblin contributors. See AUTHORS.
#
@@ -13,16 +14,12 @@
#
# 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/>.
+-#}
-
-def mongosql_parser_setup(subparser):
- pass
-
-
-def mongosql(args):
- # First, make sure our mongo migrations are up to date...
- from mediagoblin.gmg_commands.migrate import run_migrate
- run_migrate(args.conf_file)
-
- from mediagoblin.db.sql.convert import run_conversion
- run_conversion(args.conf_file)
+{% block mediagoblin_logo %}
+ <a class="logo"
+ href="{{ request.urlgen('index') }}">
+ <img src="{{ request.staticdirect('/images/logo.png', 'theme') }}"
+ alt="{% trans %}MediaGoblin logo{% endtrans %}" />
+ </a>
+{% endblock mediagoblin_logo -%}
diff --git a/mediagoblin/tools/exif.py b/mediagoblin/tools/exif.py
index 543484c9..4a1afb0f 100644
--- a/mediagoblin/tools/exif.py
+++ b/mediagoblin/tools/exif.py
@@ -73,7 +73,7 @@ def extract_exif(filename):
try:
image = open(filename)
- exif_tags = process_file(image)
+ exif_tags = process_file(image, details=False)
except IOError:
raise BadMediaFail(_('Could not read the image file.'))
@@ -97,7 +97,6 @@ def clean_exif(exif):
for key, value in exif.items():
if not key in disabled_tags:
clean_exif[key] = _ifd_tag_to_dict(value)
-
return clean_exif
diff --git a/mediagoblin/tools/pagination.py b/mediagoblin/tools/pagination.py
index 50e59070..d0f08c94 100644
--- a/mediagoblin/tools/pagination.py
+++ b/mediagoblin/tools/pagination.py
@@ -25,7 +25,7 @@ PAGINATION_DEFAULT_PER_PAGE = 30
class Pagination(object):
"""
- Pagination class for mongodb queries.
+ Pagination class for database queries.
Initialization through __init__(self, cursor, page=1, per_page=2),
get actual data slice through __call__().
@@ -40,8 +40,8 @@ class Pagination(object):
- page: requested page
- per_page: number of objects per page
- cursor: db cursor
- - jump_to_id: ObjectId, sets the page to the page containing the
- object with _id == jump_to_id.
+ - jump_to_id: object id, sets the page to the page containing the
+ object with id == jump_to_id.
"""
self.page = page
self.per_page = per_page
@@ -53,7 +53,7 @@ class Pagination(object):
cursor = copy.copy(self.cursor)
for (doc, increment) in izip(cursor, count(0)):
- if doc._id == jump_to_id:
+ if doc.id == jump_to_id:
self.page = 1 + int(floor(increment / self.per_page))
self.active_id = jump_to_id
@@ -63,8 +63,11 @@ class Pagination(object):
"""
Returns slice of objects for the requested page
"""
- return self.cursor.skip(
- (self.page - 1) * self.per_page).limit(self.per_page)
+ # TODO, return None for out of index so templates can
+ # distinguish between empty galleries and out-of-bound pages???
+ return self.cursor.slice(
+ (self.page - 1) * self.per_page,
+ self.page * self.per_page)
@property
def pages(self):
diff --git a/mediagoblin/tools/request.py b/mediagoblin/tools/request.py
index ae372c92..f7311fac 100644
--- a/mediagoblin/tools/request.py
+++ b/mediagoblin/tools/request.py
@@ -15,7 +15,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import logging
-from mediagoblin.db.util import ObjectId, InvalidId
+from mediagoblin.db.models import User
_log = logging.getLogger(__name__)
@@ -29,17 +29,11 @@ def setup_user_in_request(request):
request.user = None
return
- try:
- oid = ObjectId(request.session['user_id'])
- except InvalidId:
- user = None
- else:
- user = request.db.User.find_one({'_id': oid})
+ request.user = User.query.get(request.session['user_id'])
- if not user:
+ if not request.user:
# Something's wrong... this user doesn't exist? Invalidate
# this session.
_log.warn("Killing session for user id %r", request.session['user_id'])
request.session.invalidate()
- request.user = user
diff --git a/mediagoblin/tools/response.py b/mediagoblin/tools/response.py
index 6d14b8b7..80df1f5a 100644
--- a/mediagoblin/tools/response.py
+++ b/mediagoblin/tools/response.py
@@ -14,9 +14,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/>.
-from webob import Response, exc
+import werkzeug.utils
+from werkzeug.wrappers import Response as wz_Response
from mediagoblin.tools.template import render_template
-from mediagoblin.tools.translate import fake_ugettext_passthrough as _
+from mediagoblin.tools.translate import (lazy_pass_to_ugettext as _,
+ pass_to_ugettext)
+
+class Response(wz_Response):
+ """Set default response mimetype to HTML, otherwise we get text/plain"""
+ default_mimetype = u'text/html'
def render_to_response(request, template, context, status=200):
@@ -41,6 +47,7 @@ def render_error(request, status=500, title=_('Oops!'),
def render_403(request):
"""Render a standard 403 page"""
+ _ = pass_to_ugettext
title = _('Operation not allowed')
err_msg = _("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 "
@@ -49,20 +56,46 @@ def render_403(request):
def render_404(request):
"""Render a standard 404 page."""
+ _ = pass_to_ugettext
err_msg = _("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.")
return render_error(request, 404, err_msg=err_msg)
+
+def render_http_exception(request, exc, description):
+ """Return Response() given a werkzeug.HTTPException
+
+ :param exc: werkzeug.HTTPException or subclass thereof
+ :description: message describing the error."""
+ # If we were passed the HTTPException stock description on
+ # exceptions where we have localized ones, use those:
+ stock_desc = (description == exc.__class__.description)
+
+ if stock_desc and exc.code == 403:
+ return render_403(request)
+ elif stock_desc and exc.code == 404:
+ return render_404(request)
+
+ return render_error(request, title=exc.args[0],
+ err_msg=description,
+ status=exc.code)
+
+
def redirect(request, *args, **kwargs):
- """Returns a HTTPFound(), takes a request and then urlgen params"""
+ """Redirects to an URL, using urlgen params or location string
+
+ :param querystring: querystring to be appended to the URL
+ :param location: If the location keyword is given, redirect to the URL
+ """
+ querystring = kwargs.pop('querystring', None)
- querystring = None
- if kwargs.get('querystring'):
- querystring = kwargs.get('querystring')
- del kwargs['querystring']
+ # Redirect to URL if given by "location=..."
+ if 'location' in kwargs:
+ location = kwargs.pop('location')
+ else:
+ location = request.urlgen(*args, **kwargs)
- return exc.HTTPFound(
- location=''.join([
- request.urlgen(*args, **kwargs),
- querystring if querystring else '']))
+ if querystring:
+ location += querystring
+ return werkzeug.utils.redirect(location)
diff --git a/mediagoblin/tools/routing.py b/mediagoblin/tools/routing.py
new file mode 100644
index 00000000..791cd1e6
--- /dev/null
+++ b/mediagoblin/tools/routing.py
@@ -0,0 +1,66 @@
+# 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 werkzeug.routing import Map, Rule
+from mediagoblin.tools.common import import_component
+
+
+_log = logging.getLogger(__name__)
+
+url_map = Map()
+
+
+class MGRoute(Rule):
+ def __init__(self, endpoint, url, controller):
+ Rule.__init__(self, url, endpoint=endpoint)
+ self.gmg_controller = controller
+
+ def empty(self):
+ new_rule = Rule.empty(self)
+ new_rule.gmg_controller = self.gmg_controller
+ return new_rule
+
+
+def endpoint_to_controller(rule):
+ endpoint = rule.endpoint
+ view_func = rule.gmg_controller
+
+ _log.debug('endpoint: {0} view_func: {1}'.format(endpoint, view_func))
+
+ # import the endpoint, or if it's already a callable, call that
+ if isinstance(view_func, basestring):
+ view_func = import_component(view_func)
+ rule.gmg_controller = view_func
+
+ return view_func
+
+
+def add_route(endpoint, url, controller):
+ """
+ Add a route to the url mapping
+ """
+ url_map.add(MGRoute(endpoint, url, controller))
+
+
+def mount(mountpoint, routes):
+ """
+ Mount a bunch of routes to this mountpoint
+ """
+ for endpoint, url, controller in routes:
+ url = "%s/%s" % (mountpoint.rstrip('/'), url.lstrip('/'))
+ add_route(endpoint, url, controller)
diff --git a/mediagoblin/tools/template.py b/mediagoblin/tools/template.py
index 6f603bab..d9c6e654 100644
--- a/mediagoblin/tools/template.py
+++ b/mediagoblin/tools/template.py
@@ -17,6 +17,8 @@
from math import ceil
import jinja2
from babel.localedata import exists
+from werkzeug.urls import url_quote_plus
+
from mediagoblin import mg_globals
from mediagoblin import messages
from mediagoblin.tools import common
@@ -57,11 +59,11 @@ def get_jinja_env(template_loader, locale):
# ... construct a grid of thumbnails or other media
# ... have access to the global and app config
template_env.globals['fetch_messages'] = messages.fetch_messages
- template_env.globals['gridify_list'] = gridify_list
- template_env.globals['gridify_cursor'] = gridify_cursor
template_env.globals['app_config'] = mg_globals.app_config
template_env.globals['global_config'] = mg_globals.global_config
+ template_env.filters['urlencode'] = url_quote_plus
+
if exists(locale):
SETUP_JINJA_ENVS[locale] = template_env
@@ -96,32 +98,3 @@ def render_template(request, template_path, context):
def clear_test_template_context():
global TEMPLATE_TEST_CONTEXT
TEMPLATE_TEST_CONTEXT = {}
-
-
-def gridify_list(this_list, num_cols=5):
- """
- Generates a list of lists where each sub-list's length depends on
- the number of columns in the list
- """
- grid = []
-
- # Figure out how many rows we should have
- num_rows = int(ceil(float(len(this_list)) / num_cols))
-
- for row_num in range(num_rows):
- slice_min = row_num * num_cols
- slice_max = (row_num + 1) * num_cols
-
- row = this_list[slice_min:slice_max]
-
- grid.append(row)
-
- return grid
-
-
-def gridify_cursor(this_cursor, num_cols=5):
- """
- Generates a list of lists where each sub-list's length depends on
- the number of columns in the list
- """
- return gridify_list(list(this_cursor), num_cols)
diff --git a/mediagoblin/tools/translate.py b/mediagoblin/tools/translate.py
index 28b7aec0..96144538 100644
--- a/mediagoblin/tools/translate.py
+++ b/mediagoblin/tools/translate.py
@@ -27,18 +27,19 @@ from mediagoblin import mg_globals
# Translation tools
###################
-
+AVAILABLE_LOCALES = None
TRANSLATIONS_PATH = pkg_resources.resource_filename(
'mediagoblin', 'i18n')
-def get_available_locales():
- """Return a list of locales for which we have translations"""
- locales=[]
+def set_available_locales():
+ """Set available locales for which we have translations"""
+ global AVAILABLE_LOCALES
+ locales=['en', 'en_US'] # these are available without translations
for locale in localedata.list():
if gettext.find('mediagoblin', TRANSLATIONS_PATH, [locale]):
locales.append(locale)
- return locales
+ AVAILABLE_LOCALES = locales
def locale_to_lower_upper(locale):
@@ -68,28 +69,26 @@ def locale_to_lower_lower(locale):
def get_locale_from_request(request):
"""
- Figure out what target language is most appropriate based on the
- request
+ Return most appropriate language based on prefs/request request
"""
- request_form = request.args or request.form
+ request_args = (request.args, request.form)[request.method=='POST']
- if request_form.has_key('lang'):
- # User explicitely demanded a language
- target_lang = request_form['lang']
+ if request_args.has_key('lang'):
+ # User explicitely demanded a language, normalize lower_uppercase
+ target_lang = locale_to_lower_upper(request_args['lang'])
elif 'target_lang' in request.session:
# TODO: Uh, ohh, this is never ever set anywhere?
target_lang = request.session['target_lang']
else:
- # Pull the first acceptable language or English
- # This picks your favorite browser lingo, falling back to 'en'
+ # Pull the most acceptable language based on browser preferences
+ # This returns one of AVAILABLE_LOCALES which is aready case-normalized.
+ # Note: in our tests request.accept_languages is None, so we need
+ # to explicitely fallback to en here.
+ target_lang = request.accept_languages.best_match(AVAILABLE_LOCALES) \
+ or "en_US"
- # TODO: We need a list of available locales, and match with the list
- # of accepted locales, and serve the best available locale rather than
- # the most preferred, or fall back to 'en' immediately.
- target_lang = request.accept_languages.best_match(
- mg_globals.available_locales) or 'en'
- return locale_to_lower_upper(target_lang)
+ return target_lang
SETUP_GETTEXTS = {}
@@ -130,7 +129,10 @@ def lazy_pass_to_ugettext(*args, **kwargs):
This is useful if you have to define a translation on a module
level but you need it to not translate until the time that it's
- used as a string.
+ used as a string. For example, in:
+ def func(self, message=_('Hello boys and girls'))
+
+ you would want to use the lazy version for _.
"""
return LazyProxy(pass_to_ugettext, *args, **kwargs)
diff --git a/mediagoblin/tools/url.py b/mediagoblin/tools/url.py
index 7477173a..8604ad5f 100644
--- a/mediagoblin/tools/url.py
+++ b/mediagoblin/tools/url.py
@@ -15,7 +15,14 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import re
-import translitcodec
+# This import *is* used; see word.encode('tranlit/long') below.
+from unicodedata import normalize
+
+try:
+ import translitcodec
+ USING_TRANSLITCODEC = True
+except ImportError:
+ USING_TRANSLITCODEC = False
_punct_re = re.compile(r'[\t !"#$%&\'()*\-/<=>?@\[\\\]^_`{|},.]+')
@@ -27,7 +34,11 @@ def slugify(text, delim=u'-'):
"""
result = []
for word in _punct_re.split(text.lower()):
- word = word.encode('translit/long')
+ if USING_TRANSLITCODEC:
+ word = word.encode('translit/long')
+ else:
+ word = normalize('NFKD', word).encode('ascii', 'ignore')
+
if word:
result.append(word)
return unicode(delim.join(result))
diff --git a/mediagoblin/user_pages/lib.py b/mediagoblin/user_pages/lib.py
index a4be14c2..8a064a7c 100644
--- a/mediagoblin/user_pages/lib.py
+++ b/mediagoblin/user_pages/lib.py
@@ -33,7 +33,7 @@ def send_comment_email(user, comment, media, request):
comment_url = request.urlgen(
'mediagoblin.user_pages.media_home.view_comment',
- comment=comment._id,
+ comment=comment.id,
user=media.get_uploader.username,
media=media.slug_or_id,
qualified=True) + '#comment'
diff --git a/mediagoblin/user_pages/routing.py b/mediagoblin/user_pages/routing.py
index 8162e641..a9431405 100644
--- a/mediagoblin/user_pages/routing.py
+++ b/mediagoblin/user_pages/routing.py
@@ -14,7 +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.routing import add_route
+from mediagoblin.tools.routing import add_route
add_route('mediagoblin.user_pages.user_home',
'/u/<string:user>/', 'mediagoblin.user_pages.views:user_home')
@@ -24,11 +24,12 @@ add_route('mediagoblin.user_pages.media_home',
'mediagoblin.user_pages.views:media_home')
add_route('mediagoblin.user_pages.media_confirm_delete',
- '/u/<string:user>/m/<string:media>/confirm-delete/',
+ '/u/<string:user>/m/<int:media_id>/confirm-delete/',
'mediagoblin.user_pages.views:media_confirm_delete')
+# Submission handling of new comments. TODO: only allow for POST methods
add_route('mediagoblin.user_pages.media_post_comment',
- '/u/<string:user>/m/<string:media>/comment/add/',
+ '/u/<string:user>/m/<int:media_id>/comment/add/',
'mediagoblin.user_pages.views:media_post_comment')
add_route('mediagoblin.user_pages.user_gallery',
@@ -47,6 +48,10 @@ add_route('mediagoblin.user_pages.media_collect',
'/u/<string:user>/m/<string:media>/collect/',
'mediagoblin.user_pages.views:media_collect')
+add_route('mediagoblin.user_pages.collection_list',
+ '/u/<string:user>/collections/',
+ 'mediagoblin.user_pages.views:collection_list')
+
add_route('mediagoblin.user_pages.user_collection',
'/u/<string:user>/collection/<string:collection>/',
'mediagoblin.user_pages.views:user_collection')
@@ -73,7 +78,7 @@ add_route('mediagoblin.user_pages.processing_panel',
# Stray edit routes
add_route('mediagoblin.edit.edit_media',
- '/u/<string:user>/m/<string:media>/edit/',
+ '/u/<string:user>/m/<int:media_id>/edit/',
'mediagoblin.edit.views:edit_media')
add_route('mediagoblin.edit.attachments',
diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py
index c26bd340..30c78a38 100644
--- a/mediagoblin/user_pages/views.py
+++ b/mediagoblin/user_pages/views.py
@@ -14,26 +14,25 @@
# 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 webob import exc
import logging
import datetime
from mediagoblin import messages, mg_globals
-from mediagoblin.db.util import DESCENDING, ObjectId
+from mediagoblin.db.models import (MediaEntry, Collection, CollectionItem,
+ User)
from mediagoblin.tools.response import render_to_response, render_404, redirect
from mediagoblin.tools.translate import pass_to_ugettext as _
from mediagoblin.tools.pagination import Pagination
-from mediagoblin.tools.files import delete_media_files
from mediagoblin.user_pages import forms as user_forms
from mediagoblin.user_pages.lib import send_comment_email
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)
+ get_user_collection, get_user_collection_item, active_user_from_url)
from werkzeug.contrib.atom import AtomFeed
-from mediagoblin.media_types import get_media_manager
_log = logging.getLogger(__name__)
_log.setLevel(logging.DEBUG)
@@ -42,8 +41,10 @@ _log.setLevel(logging.DEBUG)
@uses_pagination
def user_home(request, page):
"""'Homepage' of a User()"""
- user = request.db.User.find_one({
- 'username': request.matchdict['user']})
+ # TODO: decide if we only want homepages for active users, we can
+ # then use the @get_active_user decorator and also simplify the
+ # template html.
+ user = User.query.filter_by(username=request.matchdict['user']).first()
if not user:
return render_404(request)
elif user.status != u'active':
@@ -52,9 +53,9 @@ def user_home(request, page):
'mediagoblin/user_pages/user.html',
{'user': user})
- cursor = request.db.MediaEntry.find(
- {'uploader': user._id,
- 'state': u'processed'}).sort('created', DESCENDING)
+ cursor = MediaEntry.query.\
+ filter_by(uploader = user.id,
+ state = u'processed').order_by(MediaEntry.created.desc())
pagination = Pagination(page, cursor)
media_entries = pagination()
@@ -76,30 +77,27 @@ def user_home(request, page):
'pagination': pagination})
+@active_user_from_url
@uses_pagination
-def user_gallery(request, page):
+def user_gallery(request, page, url_user=None):
"""'Gallery' of a User()"""
- user = request.db.User.find_one({
- 'username': request.matchdict['user'],
- 'status': u'active'})
- if not user:
- return render_404(request)
-
- cursor = request.db.MediaEntry.find(
- {'uploader': user._id,
- 'state': u'processed'}).sort('created', DESCENDING)
+ cursor = MediaEntry.query.filter_by(
+ uploader=url_user.id,
+ state=u'processed').order_by(MediaEntry.created.desc())
+ # Paginate gallery
pagination = Pagination(page, cursor)
media_entries = pagination()
#if no data is available, return NotFound
+ # TODO: Should we really also return 404 for empty galleries?
if media_entries == None:
return render_404(request)
return render_to_response(
request,
'mediagoblin/user_pages/gallery.html',
- {'user': user,
+ {'user': url_user,
'media_entries': media_entries,
'pagination': pagination})
@@ -112,12 +110,12 @@ def media_home(request, media, page, **kwargs):
"""
'Homepage' of a MediaEntry()
"""
- if ObjectId(request.matchdict.get('comment')):
+ if request.matchdict.get('comment', None):
pagination = Pagination(
page, media.get_comments(
mg_globals.app_config['comments_ascending']),
MEDIA_COMMENTS_PER_PAGE,
- ObjectId(request.matchdict.get('comment')))
+ request.matchdict.get('comment'))
else:
pagination = Pagination(
page, media.get_comments(
@@ -128,8 +126,7 @@ def media_home(request, media, page, **kwargs):
comment_form = user_forms.MediaCommentForm(request.form)
- media_template_name = get_media_manager(
- media.media_type)['display_template']
+ media_template_name = media.media_manager['display_template']
return render_to_response(
request,
@@ -141,7 +138,7 @@ def media_home(request, media, page, **kwargs):
'app_config': mg_globals.app_config})
-@get_user_media_entry
+@get_media_entry_by_id
@require_active_login
def media_post_comment(request, media):
"""
@@ -172,107 +169,96 @@ def media_post_comment(request, media):
media_uploader.wants_comment_notification):
send_comment_email(media_uploader, comment, media, request)
- return exc.HTTPFound(
- location=media.url_for_self(request.urlgen))
+ return redirect(request, location=media.url_for_self(request.urlgen))
@get_user_media_entry
@require_active_login
def media_collect(request, media):
+ """Add media to collection submission"""
form = user_forms.MediaCollectForm(request.form)
- filt = (request.db.Collection.creator == request.user.id)
- form.collection.query = request.db.Collection.query.filter(
- filt).order_by(request.db.Collection.title)
-
- if request.method == 'POST':
- if form.validate():
-
- collection = None
- collection_item = request.db.CollectionItem()
-
- # If the user is adding a new collection, use that
- if request.form['collection_title']:
- collection = request.db.Collection()
- collection.id = ObjectId()
-
- collection.title = (
- unicode(request.form['collection_title']))
-
- collection.description = unicode(
- request.form.get('collection_description'))
- collection.creator = request.user._id
- 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})
-
- if existing_collection:
- messages.add_message(
- request, messages.ERROR,
- _('You already have a collection called "%s"!'
- % collection.title))
-
- return redirect(request, "mediagoblin.user_pages.media_home",
- user=request.user.username,
- media=media.id)
-
- collection.save(validate=True)
-
- collection_item.collection = collection.id
- # Otherwise, use the collection selected from the drop-down
- else:
- collection = request.db.Collection.find_one({
- '_id': request.form.get('collection')})
- collection_item.collection = collection.id
-
- # Make sure the user actually selected a collection
- if not collection:
- messages.add_message(
- request, messages.ERROR,
- _('You have to select or add a collection'))
- # Check whether media already exists in collection
- elif request.db.CollectionItem.find_one({
- 'media_entry': media.id,
- 'collection': collection_item.collection}):
- messages.add_message(
- request, messages.ERROR,
- _('"%s" already in collection "%s"'
- % (media.title, collection.title)))
- else:
- collection_item.media_entry = media.id
- collection_item.author = request.user.id
- collection_item.note = unicode(request.form['note'])
- collection_item.save(validate=True)
-
- collection.items = collection.items + 1
- collection.save(validate=True)
-
- media.collected = media.collected + 1
- media.save()
-
- messages.add_message(
- request, messages.SUCCESS, _('"%s" added to collection "%s"'
- % (media.title, collection.title)))
+ # A user's own collections:
+ form.collection.query = Collection.query.filter_by(
+ creator = request.user.id).order_by(Collection.title)
+
+ if request.method != 'POST' or not form.validate():
+ # No POST submission, or invalid form
+ if not form.validate():
+ messages.add_message(request, messages.ERROR,
+ _('Please check your entries and try again.'))
+ return render_to_response(
+ request,
+ 'mediagoblin/user_pages/media_collect.html',
+ {'media': media,
+ 'form': form})
+
+ # If we are here, method=POST and the form is valid, submit things.
+ # If the user is adding a new collection, use that:
+ if request.form['collection_title']:
+ # Make sure this user isn't duplicating an existing collection
+ existing_collection = Collection.query.filter_by(
+ creator=request.user.id,
+ title=request.form['collection_title']).first()
+ if existing_collection:
+ messages.add_message(request, messages.ERROR,
+ _('You already have a collection called "%s"!'
+ % collection.title))
return redirect(request, "mediagoblin.user_pages.media_home",
- user=media.get_uploader.username,
+ user=request.user.username,
media=media.id)
- else:
- messages.add_message(
- request, messages.ERROR,
- _('Please check your entries and try again.'))
- return render_to_response(
- request,
- 'mediagoblin/user_pages/media_collect.html',
- {'media': media,
- 'form': form})
+ collection = Collection()
+ collection.title = request.form['collection_title']
+ collection.description = request.form.get('collection_description')
+ collection.creator = request.user.id
+ collection.generate_slug()
+ collection.save()
+ # Otherwise, use the collection selected from the drop-down
+ else:
+ collection = Collection.query.filter_by(
+ id=request.form.get('collection')).first()
-@get_user_media_entry
+ # Make sure the user actually selected a collection
+ if not collection:
+ messages.add_message(
+ request, messages.ERROR,
+ _('You have to select or add a collection'))
+
+ # Check whether media already exists in collection
+ elif CollectionItem.query.filter_by(
+ media_entry=media.id,
+ collection=collection.id).first():
+ messages.add_message(request, messages.ERROR,
+ _('"%s" already in collection "%s"'
+ % (media.title, collection.title)))
+ else: # Add item to collection
+ collection_item = request.db.CollectionItem()
+ collection_item.collection = collection.id
+ collection_item.media_entry = media.id
+ collection_item.author = request.user.id
+ collection_item.note = request.form['note']
+ collection_item.save()
+
+ collection.items = collection.items + 1
+ collection.save()
+
+ media.collected = media.collected + 1
+ media.save()
+
+ messages.add_message(request, messages.SUCCESS,
+ _('"%s" added to collection "%s"'
+ % (media.title, collection.title)))
+
+ return redirect(request, "mediagoblin.user_pages.media_home",
+ user=media.get_uploader.username,
+ media=media.id)
+
+
+#TODO: Why does @user_may_delete_media not implicate @require_active_login?
+@get_media_entry_by_id
@require_active_login
@user_may_delete_media
def media_confirm_delete(request, media):
@@ -282,21 +268,7 @@ def media_confirm_delete(request, media):
if request.method == 'POST' and form.validate():
if form.confirm.data is True:
username = media.get_uploader.username
-
- # Delete all the associated comments
- for comment in media.get_comments():
- comment.delete()
-
- # Delete all files on the public storage
- try:
- delete_media_files(media)
- except OSError, error:
- _log.error('No such files from the user "{1}"'
- ' to delete: {0}'.format(str(error), username))
- messages.add_message(request, messages.ERROR,
- _('Some of the files with this entry seem'
- ' to be missing. Deleting anyway.'))
-
+ # Delete MediaEntry and all related files, comments etc.
media.delete()
messages.add_message(
request, messages.SUCCESS, _('You deleted the media.'))
@@ -307,11 +279,11 @@ def media_confirm_delete(request, media):
messages.add_message(
request, messages.ERROR,
_("The media was not deleted because you didn't check that you were sure."))
- return exc.HTTPFound(
- location=media.url_for_self(request.urlgen))
+ return redirect(request,
+ location=media.url_for_self(request.urlgen))
if ((request.user.is_admin and
- request.user._id != media.uploader)):
+ request.user.id != media.uploader)):
messages.add_message(
request, messages.WARNING,
_("You are about to delete another user's media. "
@@ -324,37 +296,46 @@ def media_confirm_delete(request, media):
'form': form})
+@active_user_from_url
@uses_pagination
-def user_collection(request, page):
+def user_collection(request, page, url_user=None):
"""A User-defined Collection"""
- user = request.db.User.find_one({
- 'username': request.matchdict['user'],
- 'status': u'active'})
- if not user:
- return render_404(request)
-
- collection = request.db.Collection.find_one(
- {'slug': request.matchdict['collection']})
+ collection = Collection.query.filter_by(
+ get_creator=url_user,
+ slug=request.matchdict['collection']).first()
- cursor = request.db.CollectionItem.find(
- {'collection': collection.id})
+ cursor = collection.get_collection_items()
pagination = Pagination(page, cursor)
collection_items = pagination()
- #if no data is available, return NotFound
+ # if no data is available, return NotFound
+ # TODO: Should an empty collection really also return 404?
if collection_items == None:
return render_404(request)
return render_to_response(
request,
'mediagoblin/user_pages/collection.html',
- {'user': user,
+ {'user': url_user,
'collection': collection,
'collection_items': collection_items,
'pagination': pagination})
+@active_user_from_url
+def collection_list(request, url_user=None):
+ """A User-defined Collection"""
+ collections = Collection.query.filter_by(
+ get_creator=url_user)
+
+ return render_to_response(
+ request,
+ 'mediagoblin/user_pages/collection_list.html',
+ {'user': url_user,
+ 'collections': collections})
+
+
@get_user_collection_item
@require_active_login
@user_may_alter_collection
@@ -387,7 +368,7 @@ def collection_item_confirm_remove(request, collection_item):
collection=collection.slug)
if ((request.user.is_admin and
- request.user._id != collection_item.in_collection.creator)):
+ request.user.id != collection_item.in_collection.creator)):
messages.add_message(
request, messages.WARNING,
_("You are about to delete an item from another user's collection. "
@@ -437,7 +418,7 @@ def collection_confirm_delete(request, collection):
collection=collection.slug)
if ((request.user.is_admin and
- request.user._id != collection.creator)):
+ request.user.id != collection.creator)):
messages.add_message(
request, messages.WARNING,
_("You are about to delete another user's collection. "
@@ -457,18 +438,17 @@ def atom_feed(request):
"""
generates the atom feed with the newest images
"""
-
- user = request.db.User.find_one({
- 'username': request.matchdict['user'],
- 'status': u'active'})
+ user = User.query.filter_by(
+ username = request.matchdict['user'],
+ status = u'active').first()
if not user:
return render_404(request)
- cursor = request.db.MediaEntry.find({
- 'uploader': user._id,
- 'state': u'processed'}) \
- .sort('created', DESCENDING) \
- .limit(ATOM_DEFAULT_NR_OF_UPDATED_ITEMS)
+ cursor = MediaEntry.query.filter_by(
+ uploader = user.id,
+ state = u'processed').\
+ order_by(MediaEntry.created.desc()).\
+ limit(ATOM_DEFAULT_NR_OF_UPDATED_ITEMS)
"""
ATOM feed id is a tag URI (see http://en.wikipedia.org/wiki/Tag_URI)
@@ -521,20 +501,19 @@ def collection_atom_feed(request):
"""
generates the atom feed with the newest images from a collection
"""
-
- user = request.db.User.find_one({
- 'username': request.matchdict['user'],
- 'status': u'active'})
+ user = User.query.filter_by(
+ username = request.matchdict['user'],
+ status = u'active').first()
if not user:
return render_404(request)
- collection = request.db.Collection.find_one({
- 'creator': user.id,
- 'slug': request.matchdict['collection']})
+ collection = Collection.query.filter_by(
+ creator=user.id,
+ slug=request.matchdict['collection']).first()
- cursor = request.db.CollectionItem.find({
- 'collection': collection._id}) \
- .sort('added', DESCENDING) \
+ cursor = CollectionItem.query.filter_by(
+ collection=collection.id) \
+ .order_by(CollectionItem.added.desc()) \
.limit(ATOM_DEFAULT_NR_OF_UPDATED_ITEMS)
"""
@@ -592,44 +571,34 @@ def processing_panel(request):
Show to the user what media is still in conversion/processing...
and what failed, and why!
"""
- # Get the user
- user = request.db.User.find_one(
- {'username': request.matchdict['user'],
- 'status': u'active'})
-
- # Make sure the user exists and is active
- if not user:
- return render_404(request)
- elif user.status != u'active':
- return render_to_response(
- request,
- 'mediagoblin/user_pages/user.html',
- {'user': user})
-
- # XXX: Should this be a decorator?
+ user = User.query.filter_by(username=request.matchdict['user']).first()
+ # TODO: XXX: Should this be a decorator?
#
# Make sure we have permission to access this user's panel. Only
# admins and this user herself should be able to do so.
- if not (user._id == request.user._id
- or request.user.is_admin):
- # No? Let's simply redirect to this user's homepage then.
+ if not (user.id == request.user.id or request.user.is_admin):
+ # No? Simply redirect to this user's homepage.
return redirect(
request, 'mediagoblin.user_pages.user_home',
- user=request.matchdict['user'])
+ user=user.username)
# Get media entries which are in-processing
- processing_entries = request.db.MediaEntry.find(
- {'uploader': user._id,
- 'state': u'processing'}).sort('created', DESCENDING)
+ processing_entries = MediaEntry.query.\
+ filter_by(uploader = user.id,
+ state = u'processing').\
+ order_by(MediaEntry.created.desc())
# Get media entries which have failed to process
- failed_entries = request.db.MediaEntry.find(
- {'uploader': user._id,
- 'state': u'failed'}).sort('created', DESCENDING)
-
- processed_entries = request.db.MediaEntry.find(
- {'uploader': user._id,
- 'state': u'processed'}).sort('created', DESCENDING).limit(10)
+ failed_entries = MediaEntry.query.\
+ filter_by(uploader = user.id,
+ state = u'failed').\
+ order_by(MediaEntry.created.desc())
+
+ processed_entries = MediaEntry.query.\
+ filter_by(uploader = user.id,
+ state = u'processed').\
+ order_by(MediaEntry.created.desc()).\
+ limit(10)
# Render to response
return render_to_response(
diff --git a/mediagoblin/views.py b/mediagoblin/views.py
index 9d34750b..6acd7e96 100644
--- a/mediagoblin/views.py
+++ b/mediagoblin/views.py
@@ -15,17 +15,17 @@
# 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.tools.pagination import Pagination
from mediagoblin.tools.response import render_to_response
-from mediagoblin.db.util import DESCENDING
from mediagoblin.decorators import uses_pagination
@uses_pagination
def root_view(request, page):
- cursor = request.db.MediaEntry.find(
- {u'state': u'processed'}).sort('created', DESCENDING)
+ cursor = MediaEntry.query.filter_by(state=u'processed').\
+ order_by(MediaEntry.created.desc())
pagination = Pagination(page, cursor)
media_entries = pagination()
diff --git a/mediagoblin/webfinger/routing.py b/mediagoblin/webfinger/routing.py
index 18f9eb02..eb10509f 100644
--- a/mediagoblin/webfinger/routing.py
+++ b/mediagoblin/webfinger/routing.py
@@ -14,7 +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.routing import add_route
+from mediagoblin.tools.routing import add_route
add_route('mediagoblin.webfinger.host_meta', '/.well-known/host-meta',
'mediagoblin.webfinger.views:host_meta')
diff --git a/mediagoblin/workbench.py b/mediagoblin/workbench.py
index 2331b551..0d4db52b 100644
--- a/mediagoblin/workbench.py
+++ b/mediagoblin/workbench.py
@@ -119,7 +119,7 @@ class Workbench(object):
return full_dest_filename
- def destroy_self(self):
+ def destroy(self):
"""
Destroy this workbench! Deletes the directory and all its contents!
@@ -127,18 +127,33 @@ class Workbench(object):
"""
# just in case
workbench = os.path.abspath(self.dir)
-
shutil.rmtree(workbench)
-
del self.dir
+ def __enter__(self):
+ """Make Workbench a context manager so we can use `with Workbench() as bench:`"""
+ return self
+
+ def __exit__(self, *args):
+ """Clean up context manager, aka ourselves, deleting the workbench"""
+ self.destroy()
+
class WorkbenchManager(object):
"""
A system for generating and destroying workbenches.
- Workbenches are actually just subdirectories of a temporary storage space
- for during the processing stage.
+ Workbenches are actually just subdirectories of a (local) temporary
+ storage space for during the processing stage. The preferred way to
+ create them is to use:
+
+ with workbenchmger.create() as workbench:
+ do stuff...
+
+ This will automatically clean up all temporary directories even in
+ case of an exceptions. Also check the
+ @mediagoblin.decorators.get_workbench decorator for a convenient
+ wrapper.
"""
def __init__(self, base_workbench_dir):
@@ -146,7 +161,7 @@ class WorkbenchManager(object):
if not os.path.exists(self.base_workbench_dir):
os.makedirs(self.base_workbench_dir)
- def create_workbench(self):
+ def create(self):
"""
Create and return the path to a new workbench (directory).
"""
diff --git a/runtests.sh b/runtests.sh
index 94e77da2..a4ceec2e 100755
--- a/runtests.sh
+++ b/runtests.sh
@@ -16,9 +16,19 @@
# 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 [ -f ./bin/nosetests ]; then
- echo "Using ./bin/nosetests";
- export NOSETESTS="./bin/nosetests";
+basedir="`dirname $0`"
+# Directory to seaerch for:
+subdir="mediagoblin/tests"
+[ '!' -d "$basedir/$subdir" ] && basedir="."
+if [ '!' -d "$basedir/$subdir" ]
+then
+ echo "Could not find base directory" >&2
+ exit 1
+fi
+
+if [ -x "$basedir/bin/nosetests" ]; then
+ export NOSETESTS="$basedir/bin/nosetests";
+ echo "Using $NOSETESTS";
elif which nosetests > /dev/null; then
echo "Using nosetests from \$PATH";
export NOSETESTS="nosetests";
@@ -28,4 +38,25 @@ else
exit 1
fi
-CELERY_CONFIG_MODULE=mediagoblin.init.celery.from_tests $NOSETESTS $@
+need_arg=1
+for i in "$@"
+do
+ case "$i" in
+ -*) ;;
+ *) need_arg=0; break ;;
+ esac
+done
+
+CELERY_CONFIG_MODULE=mediagoblin.init.celery.from_tests
+export CELERY_CONFIG_MODULE
+echo "+ CELERY_CONFIG_MODULE=$CELERY_CONFIG_MODULE"
+
+if [ "$need_arg" = 1 ]
+then
+ testdir="$basedir/mediagoblin/tests"
+ set -x
+ exec "$NOSETESTS" "$@" "$testdir"
+else
+ set -x
+ exec "$NOSETESTS" "$@"
+fi
diff --git a/setup.py b/setup.py
index e0f7af7e..12284f26 100644
--- a/setup.py
+++ b/setup.py
@@ -44,7 +44,6 @@ setup(
'setuptools',
'PasteScript',
'beaker',
- 'webob<=1.2a2,>=1.1',
'wtforms',
'py-bcrypt',
'nose',
@@ -54,13 +53,14 @@ setup(
'jinja2',
'sphinx',
'Babel',
- 'translitcodec',
'argparse',
'webtest',
'ConfigObj',
'Markdown',
'sqlalchemy>=0.7.0',
'sqlalchemy-migrate',
+ ## This is optional!
+ # 'translitcodec',
## For now we're expecting that users will install this from
## their package managers.
# 'lxml',
@@ -94,7 +94,7 @@ setup(
classifiers=[
"Development Status :: 3 - Alpha",
"Environment :: Web Environment",
- "License :: OSI Approved :: GNU Affero General Public License",
+ "License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)",
"Operating System :: OS Independent",
"Programming Language :: Python",
'Programming Language :: Python :: 2.6',