aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--AUTHORS2
-rw-r--r--MANIFEST.in5
-rw-r--r--docs/source/about.rst (renamed from docs/source/about_mediagoblin.rst)59
-rw-r--r--docs/source/codebase.rst21
-rw-r--r--docs/source/conf.py4
-rw-r--r--docs/source/configuration.rst105
-rw-r--r--docs/source/contributinghowto.rst215
-rw-r--r--docs/source/deploying.rst264
-rw-r--r--docs/source/deploymenthowto.rst16
-rw-r--r--docs/source/foreword.rst37
-rw-r--r--docs/source/help.rst16
-rw-r--r--docs/source/index.rst10
-rw-r--r--docs/source/theming.rst (renamed from docs/source/theminghowto.rst)8
-rw-r--r--docs/source/vision.rst142
-rwxr-xr-xlazyserver.sh17
-rw-r--r--mediagoblin.ini3
-rw-r--r--mediagoblin/_version.py2
-rw-r--r--mediagoblin/app.py43
-rw-r--r--mediagoblin/auth/forms.py10
-rw-r--r--mediagoblin/auth/lib.py10
-rw-r--r--mediagoblin/auth/routing.py3
-rw-r--r--mediagoblin/auth/views.py56
-rw-r--r--mediagoblin/config_spec.ini8
-rw-r--r--mediagoblin/db/__init__.py2
-rw-r--r--mediagoblin/db/indexes.py5
-rw-r--r--mediagoblin/db/migrations.py41
-rw-r--r--mediagoblin/db/models.py63
-rw-r--r--mediagoblin/db/open.py2
-rw-r--r--mediagoblin/db/util.py7
-rw-r--r--mediagoblin/decorators.py12
-rw-r--r--mediagoblin/edit/__init__.py2
-rw-r--r--mediagoblin/edit/forms.py23
-rw-r--r--mediagoblin/edit/lib.py2
-rw-r--r--mediagoblin/edit/views.py58
-rw-r--r--mediagoblin/gmg_commands/__init__.py25
-rw-r--r--mediagoblin/gmg_commands/import_export.py13
-rw-r--r--mediagoblin/gmg_commands/migrate.py8
-rw-r--r--mediagoblin/gmg_commands/shell.py4
-rw-r--r--mediagoblin/gmg_commands/users.py16
-rw-r--r--mediagoblin/gmg_commands/wipealldata.py6
-rw-r--r--mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.mobin11549 -> 12268 bytes
-rw-r--r--mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.po155
-rw-r--r--mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.mobin0 -> 10826 bytes
-rw-r--r--mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.po520
-rw-r--r--mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.mobin10915 -> 11119 bytes
-rw-r--r--mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.po130
-rw-r--r--mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po101
-rw-r--r--mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.mobin10738 -> 10809 bytes
-rw-r--r--mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.po129
-rw-r--r--mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.mobin11114 -> 11329 bytes
-rw-r--r--mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.po150
-rw-r--r--mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.mobin11232 -> 11583 bytes
-rw-r--r--mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.po177
-rw-r--r--mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.mobin0 -> 10530 bytes
-rw-r--r--mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.po498
-rw-r--r--mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.mobin0 -> 11026 bytes
-rw-r--r--mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.po528
-rw-r--r--mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.mobin11184 -> 11224 bytes
-rw-r--r--mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.po91
-rw-r--r--mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.mobin10655 -> 10695 bytes
-rw-r--r--mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.po91
-rw-r--r--mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.mobin10261 -> 10287 bytes
-rw-r--r--mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.po184
-rw-r--r--mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.mobin10608 -> 10945 bytes
-rw-r--r--mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.po227
-rw-r--r--mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.mobin10955 -> 11067 bytes
-rw-r--r--mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.po139
-rw-r--r--mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.mobin13306 -> 13899 bytes
-rw-r--r--mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.po125
-rw-r--r--mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.mobin0 -> 11267 bytes
-rw-r--r--mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.po541
-rw-r--r--mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.mobin10724 -> 10764 bytes
-rw-r--r--mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.po91
-rw-r--r--mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.mobin10587 -> 10627 bytes
-rw-r--r--mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.po91
-rw-r--r--mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.mobin10836 -> 11015 bytes
-rw-r--r--mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.po136
-rw-r--r--mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.mobin0 -> 10812 bytes
-rw-r--r--mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.po498
-rw-r--r--mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.mobin10463 -> 10509 bytes
-rw-r--r--mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.po131
-rw-r--r--mediagoblin/init/__init__.py22
-rw-r--r--mediagoblin/init/celery/__init__.py12
-rw-r--r--mediagoblin/init/celery/from_celery.py2
-rw-r--r--mediagoblin/init/config.py2
-rw-r--r--mediagoblin/listings/routing.py1
-rw-r--r--mediagoblin/listings/views.py6
-rw-r--r--mediagoblin/messages.py2
-rw-r--r--mediagoblin/middleware/__init__.py1
-rw-r--r--mediagoblin/middleware/csrf.py132
-rw-r--r--mediagoblin/middleware/noop.py1
-rw-r--r--mediagoblin/process_media/__init__.py65
-rw-r--r--mediagoblin/process_media/errors.py11
-rw-r--r--mediagoblin/static/css/base.css81
-rw-r--r--mediagoblin/static/images/empty_back.pngbin0 -> 191 bytes
-rw-r--r--mediagoblin/static/images/icon_comment.pngbin0 -> 283 bytes
-rw-r--r--mediagoblin/static/images/icon_delete.pngbin472 -> 0 bytes
-rw-r--r--mediagoblin/static/images/icon_edit.pngbin297 -> 0 bytes
-rw-r--r--mediagoblin/static/images/logo.pngbin2479 -> 1689 bytes
-rw-r--r--mediagoblin/static/images/logo.svg116
-rw-r--r--mediagoblin/static/images/navigation_end.pngbin718 -> 0 bytes
-rw-r--r--mediagoblin/static/images/navigation_left.pngbin406 -> 0 bytes
-rw-r--r--mediagoblin/static/images/navigation_right.pngbin383 -> 0 bytes
-rw-r--r--mediagoblin/staticdirect.py6
-rw-r--r--mediagoblin/storage/__init__.py16
-rw-r--r--mediagoblin/storage/cloudfiles.py1
-rw-r--r--mediagoblin/storage/filestorage.py14
-rw-r--r--mediagoblin/storage/mountstorage.py2
-rw-r--r--mediagoblin/submit/__init__.py2
-rw-r--r--mediagoblin/submit/forms.py8
-rw-r--r--mediagoblin/submit/security.py2
-rw-r--r--mediagoblin/submit/views.py27
-rw-r--r--mediagoblin/templates/mediagoblin/auth/change_fp.html4
-rw-r--r--mediagoblin/templates/mediagoblin/auth/forgot_password.html9
-rw-r--r--mediagoblin/templates/mediagoblin/auth/fp_changed_success.html4
-rw-r--r--mediagoblin/templates/mediagoblin/auth/fp_email_sent.html4
-rw-r--r--mediagoblin/templates/mediagoblin/auth/login.html25
-rw-r--r--mediagoblin/templates/mediagoblin/auth/register.html3
-rw-r--r--mediagoblin/templates/mediagoblin/base.html10
-rw-r--r--mediagoblin/templates/mediagoblin/edit/attachments.html3
-rw-r--r--mediagoblin/templates/mediagoblin/edit/edit.html3
-rw-r--r--mediagoblin/templates/mediagoblin/edit/edit_profile.html3
-rw-r--r--mediagoblin/templates/mediagoblin/listings/tag.html6
-rw-r--r--mediagoblin/templates/mediagoblin/root.html25
-rw-r--r--mediagoblin/templates/mediagoblin/submit/start.html3
-rw-r--r--mediagoblin/templates/mediagoblin/test_submit.html3
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/gallery.html45
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/media.html74
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html5
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/user.html25
-rw-r--r--mediagoblin/templates/mediagoblin/utils/pagination.html6
-rw-r--r--mediagoblin/templates/mediagoblin/utils/prev_next.html8
-rw-r--r--mediagoblin/templates/mediagoblin/utils/tags.html24
-rw-r--r--mediagoblin/templates/mediagoblin/utils/wtforms.html12
-rw-r--r--mediagoblin/tests/test_auth.py118
-rw-r--r--mediagoblin/tests/test_csrf_middleware.py71
-rw-r--r--mediagoblin/tests/test_edit.py112
-rw-r--r--mediagoblin/tests/test_messages.py4
-rw-r--r--mediagoblin/tests/test_mgoblin_app.ini2
-rw-r--r--mediagoblin/tests/test_migrations.py6
-rw-r--r--mediagoblin/tests/test_paste.ini2
-rw-r--r--mediagoblin/tests/test_storage.py27
-rw-r--r--mediagoblin/tests/test_submission.py48
-rw-r--r--mediagoblin/tests/test_tags.py11
-rw-r--r--mediagoblin/tests/test_util.py57
-rw-r--r--mediagoblin/tests/tools.py58
-rw-r--r--mediagoblin/tools/__init__.py0
-rw-r--r--mediagoblin/tools/common.py38
-rw-r--r--mediagoblin/tools/files.py32
-rw-r--r--mediagoblin/tools/mail.py123
-rw-r--r--mediagoblin/tools/pagination.py111
-rw-r--r--mediagoblin/tools/request.py37
-rw-r--r--mediagoblin/tools/response.py47
-rw-r--r--mediagoblin/tools/template.py122
-rw-r--r--mediagoblin/tools/testing.py45
-rw-r--r--mediagoblin/tools/text.py124
-rw-r--r--mediagoblin/tools/translate.py172
-rw-r--r--mediagoblin/tools/url.py33
-rw-r--r--mediagoblin/user_pages/__init__.py2
-rw-r--r--mediagoblin/user_pages/forms.py2
-rw-r--r--mediagoblin/user_pages/views.py69
-rw-r--r--mediagoblin/util.py698
-rw-r--r--mediagoblin/views.py4
-rw-r--r--mediagoblin/workbench.py4
-rw-r--r--paste.ini38
-rw-r--r--setup.py14
167 files changed, 6437 insertions, 2710 deletions
diff --git a/.gitignore b/.gitignore
index 5f16bd74..9e8d958a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,8 @@ bin/
develop-eggs/
build/
eggs/
+lib/
+include/
parts/
.installed.cfg
mediagoblin.egg-info
diff --git a/AUTHORS b/AUTHORS
index c9fc5c8e..76e16b86 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -13,6 +13,7 @@ Thank you!
* Alex Camelio
* Bernhard Keller
* Caleb Forbes Davis V
+* Corey Farwell
* Chris Moylan
* Christopher Allan Webber
* Daniel Neel
@@ -27,6 +28,7 @@ Thank you!
* Nathan Yergler
* Odin Hørthe Omdal
* Osama Khalid
+* Pablo J. Urbano Santos
* Rasmus Larsson
* Sam Kleinman
* Sebastian Spaeth
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 00000000..b1f93dba
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,5 @@
+recursive-include mediagoblin/templates *.html
+recursive-include mediagoblin/static *.js *.css *.png *.svg
+recursive-include mediagoblin/tests *.ini
+recursive-include docs *.rst *.html
+
diff --git a/docs/source/about_mediagoblin.rst b/docs/source/about.rst
index 71d8b89c..1a2df809 100644
--- a/docs/source/about_mediagoblin.rst
+++ b/docs/source/about.rst
@@ -1,6 +1,6 @@
-=================
- GNU MediaGoblin
-=================
+=======================
+ About GNU MediaGoblin
+=======================
.. contents:: Sections
:local:
@@ -9,55 +9,63 @@
What is GNU MediaGoblin
=======================
-In 2008 a number of free software developers and activists gathered at
-the FSF to attempt to answer the question "What should software
-freedom look like on the participatory web?" Their answer, the
-`Franklin Street Statement <http://autonomo.us/2008/07/franklin-street-statement/>`_,
-has lead to the development of `autonomo.us <http://autonomo.us/>`_
-community, and free software projects including `Identi.ca <http://identi.ca/>`_
-and `Libre.fm <http://libre.fm/>`_.
+In 2008, a number of free software developers and activists gathered
+at the FSF to attempt to answer the question "What should software
+freedom look like on the participatory web?" Their answer, the
+`Franklin Street Statement`_ has lead to the development of
+`autonomo.us`_ community, and free software projects including
+`Identi.ca`_ and `Libre.fm`_.
+
+.. _Franklin Street Statement: http://autonomo.us/2008/07/franklin-street-statement/
+.. _autonomo.us: http://autonomo.us/
+.. _identi.ca: http://identi.ca/
+.. _Libre.fm: http://libre.fm/
Identi.ca and Libre.fm address the need for micro-blogging and music
sharing services and software that respect users' freedom and
-autonomy. GNU MediaGoblin emerges from this milieu to create a
+autonomy. GNU MediaGoblin emerges from this milieu to create a
platform for us to share photos in an environment that respects our
-freedom and independence. In the future MediaGoblin will include
+freedom and independence. In the future MediaGoblin will include
support other media, like video, and provide tools to facilitate
collaboration on media projects.
+
Why Build GNU MediaGoblin
=========================
-The Internet is designed--and works best--as a complex and endlessly
-resilient network. When key services and media outlets are
+The Internet is designed---and works best---as a complex and endlessly
+resilient network. When key services and media outlets are
concentrated in centralized platforms, the network becomes less useful
-and increasingly fragile. As always, the proprietary nature of these
+and increasingly fragile. As always, the proprietary nature of these
systems, hinders users ability to develop, extend, and understand
their software; however, in the case of network services it also means
that users must forfeit control of their data to the service
-providers.
+providers.
Therefore, we believe that network services must be federated to avoid
centralization and that everyone ought to have control over their
-data. In support of this, we've decided to help build the tools to
-make these kinds of services possible. We hope you'll join us, both as
-users and as contributors.
+data. In support of this, we've decided to help build the tools to
+make these kinds of services possible. We hope you'll join us, both
+as users and as contributors.
+
Who Contributes to the Project
==============================
-You do!
+You do!
We are free software activists and folks who have worked on a variety
of other projects including: Libre.fm, GNU Social, Status.net, Miro,
-Miro Community, and OpenHatch among others. We're programmers,
-musicians, writers, and painters. We're friendly and dedicated to
+Miro Community, and OpenHatch among others. We're programmers,
+musicians, writers, and painters. We're friendly and dedicated to
software and network freedom.
+
How Can I Participate?
======================
-See `Get Involved <http://mediagoblin.org/join/>`_ on the website..
+See `Get Involved <http://mediagoblin.org/join/>`_ on the website. We
+eagerly look forward to seeing you!
How is GNU MediaGoblin licensed?
@@ -65,7 +73,7 @@ How is GNU MediaGoblin licensed?
GNU MediaGoblin software is released under an AGPLv3 license.
-See the ``COPYING`` file in the source repository for details.
+See the ``COPYING`` file in the root of the source for details.
Is MedaGobilin an official GNU project? What does that mean?
@@ -73,7 +81,8 @@ Is MedaGobilin an official GNU project? What does that mean?
MediaGoblin is an official GNU project! This status means that we the
meet the GNU Project's rigorous standards for free software. To find
-out more about what that means, check out `the GNU site <http://gnu.org/>`_.
+out more about what that means, check out the `GNU website`_.
Please feel free to contact us with further questions!
+.. _GNU website: http://gnu.org/
diff --git a/docs/source/codebase.rst b/docs/source/codebase.rst
index ba5f1e46..28d73802 100644
--- a/docs/source/codebase.rst
+++ b/docs/source/codebase.rst
@@ -45,7 +45,7 @@ Software Stack
* Web application
- * `Paste Deploy <http://pythonpaste.org/deploy/>`_ and
+ * `Paste Deploy <http://pythonpaste.org/deploy/>`_ and
`Paste Script <http://pythonpaste.org/script/>`_: we'll use this for
configuring and launching the application
@@ -83,22 +83,21 @@ After you've run buildout, you're faced with the following directory
tree::
mediagoblin/
- |- mediagoblin/ #source code
+ |- mediagoblin/ # source code
| |- tests/
| |- templates/
| |- auth/
| \- submit/
- |- docs/ #documentation
+ |- docs/ # documentation
|
- | #the below directories are generated by
- | #buildout.
+ | # the below directories are generated by buildout.
|
- |- bin/ #scripts
+ |- bin/ # scripts
|- develop-eggs/
|- eggs/
|- mediagoblin.egg-info/
|- parts/
- |- user_dev/ #sessions, etc
+ |- user_dev/ # sessions, etc
As you can see, all the code for GNU MediaGoblin is in the
@@ -108,7 +107,7 @@ Here are some interesting files and what they do:
:routing.py: maps url paths to views
:views.py: views handle http requests
-:models.py: holds the mongodb schemas---these are the data structures
+:models.py: holds the mongodb schemas---these are the data structures
we're working with
You'll notice that there are several sub-directories: tests,
@@ -122,9 +121,3 @@ templates, auth, submit, ...
and media item submission. If you look in these directories, you'll
see they have their own ``routing.py``, ``view.py``, and
``models.py`` in addition to some other code.
-
-
-Recipes
-=======
-
-FIXME - write this
diff --git a/docs/source/conf.py b/docs/source/conf.py
index 7ea3a340..eee9900f 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -48,9 +48,9 @@ copyright = u'2011, Free Software Foundation, Inc and contributors'
# built documents.
#
# The short X.Y version.
-version = '0.0.5'
+version = '0.1.0'
# The full version, including alpha/beta/rc tags.
-release = '0.0.5'
+release = '0.1.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/docs/source/configuration.rst b/docs/source/configuration.rst
new file mode 100644
index 00000000..093f492c
--- /dev/null
+++ b/docs/source/configuration.rst
@@ -0,0 +1,105 @@
+.. _configuration-chapter:
+
+========================
+Configuring MediaGoblin
+========================
+
+So! You've got MediaGoblin up and running, but you need to adjust
+some configuration parameters. Well you've come to the right place!
+
+MediaGoblin's config files
+==========================
+
+When configuring MediaGoblin, there are two files you might want to
+make local modified versions of, and one extra file that might be
+helpful to look at. Let's examine these.
+
+mediagoblin.ini
+ This is the config file for MediaGoblin, the application. If you want to
+ tweak settings for MediaGoblin, you'll usually tweak them here.
+
+paste.ini
+ This is primarily a server configuration file, on the python side
+ (specifically, on the wsgi side, via `paste deploy
+ <http://pythonpaste.org/deploy/>`_ / `paste script
+ <http://pythonpaste.org/script/>`_). It also sets up some
+ middleware that you can mostly ignore, except to configure
+ sessions... more on that later. If you are adding a different
+ python server other than fastcgi / plain http, you might configure
+ it here. You probably won't need to change this file very much.
+
+
+There's one more file that you certainly won't change unless you're
+making coding contributions to mediagoblin, but which can be useful to
+read and reference:
+
+mediagoblin/config_spec.ini
+ This file is actually a specification for mediagoblin.ini itself, as
+ a config file! It defines types and defaults. Sometimes it's a
+ good place to look for documentation... or to find that hidden
+ option that we didn't tell you about. :)
+
+
+Making local copies
+===================
+
+Let's assume you're doing the virtualenv setup described elsewhere in this
+manual, and you need to make local tweaks to the config files. How do you do
+that? Let's see.
+
+To make changes to mediagoblin.ini:
+
+ cp mediagoblin.ini mediagoblin_local.ini
+
+To make changes to paste.ini:
+ cp paste.ini paste_local.ini
+
+From here you should be able to make direct adjustments to the files,
+and most of the commands described elsewhere in this manual will "notice"
+your local config files and use those instead of the non-local version.
+
+(Note that all commands provide a way to pass in a specific config
+file also, usually by a -cf flag.)
+
+Common changes
+==============
+
+Enabling email notifications
+----------------------------
+
+You'll almost certainly want to enable sending emails. By default,
+MediaGoblin doesn't really do this... for the sake of developer
+convenience, it runs in "email debug mode". Change this:
+
+ email_debug_mode = false
+
+You can (and should) change the "from" email address by setting
+``email_sender_address``.
+
+Note that you need a mailer daemon running for this to work.
+
+If you have more custom SMTP settings, you also have the following
+options at your disposal, which are all optional, and do exactly what
+they sound like.
+
+ - email_smtp_host
+ - email_smtp_port
+ - email_smtp_user
+ - email_smtp_pass
+
+All other configuration changes
+-------------------------------
+
+To be perfectly honest, there are quite a few options and I'm not
+going to be able to get to documanting them all in time for 0.1.0.
+
+So here's a cop-out section saying that if you get into trouble, hop
+onto IRC and we'll help you out:
+
+ #mediagoblin on irc.freenode.net
+
+Celery
+======
+
+We should point to another celery-specific section of the document
+actually :)
diff --git a/docs/source/contributinghowto.rst b/docs/source/contributinghowto.rst
deleted file mode 100644
index 8eaff5e4..00000000
--- a/docs/source/contributinghowto.rst
+++ /dev/null
@@ -1,215 +0,0 @@
-.. _contributing-howto-chapter:
-
-===================================
-HOWTO Contribute to GNU MediaGoblin
-===================================
-
-.. contents:: Sections
- :local:
-
-.. _join-the-community-section:
-
-Join the community!
-===================
-
-We're **really** glad that you want to join the MediaGoblin community!
-
-There are a variety of ways to help and support MediaGoblin and to
-join the team. If you want to code, great, if not, even better!
-MediaGoblin interested contributors in many different roles: users,
-system administrators, technical writers, testers, evangelists,
-UI/UX and graphics designers, cheerleaders, and dreamers.
-
-This document provides an overview of different ways you can get
-involved with MediaGoblin along with instructions for getting
-started. There is some obvious overlap with `the "join" page on
-mediagoblin.org <http://mediagoblin.org/pages/join.html>`_ at present.
-
-Hang out with the MediaGoblin folk
-----------------------------------
-
-MediaGoblin has a `discussion listserv <http://lists.mediagoblin.org/listinfo/devel>`_,
-and an IRC (``#mediagoblin``) channel on `freenode.net <http://freenode.com>`_.
-
-Don't be afraid to drop by and say "Hi!" And, if you're looking for
-something to do, just ask: there's always work to be done.
-
-File Bugs / Triage Bugs
------------------------
-
-Issue reports are critical for all projects. Identified bugs give
-developers a basis for beginning work, and providing an idea of what
-features and issues are most important to users and the overall
-usability of the software. If you identify errors, flaws, unexpected
-behaviors, or deficits that impede use, file a bug.
-
-See the section on `filing bugs <#filing-bugs>`_ for more information on how to file the best
-and most useful bug reports.
-
-If you want to contribute to MediaGoblin and don't know where to
-start, look at the `bug database <http://bugs.foocorp.net/projects/mediagoblin/issues>`_
-as a starting point.
-
-See the section on `bug triage <#triage-bugs>`_ for suggestions on how
-to most effectively triage and approach the issue queue.
-
-Write/Fix Code
---------------
-
-If you are a coder and you would like to write code, the `repository <https://gitorious.org/mediagoblin>`_
-is hosted on `gitorious <https://gitorious.org/>`_. Clone or fork the
-repository and start poking around. Become familiar with this `manual </>`_
-for an overview of how the software works and is used. Consider the
-`contributor wiki <http://wiki.mediagoblin.org/>`_ for more
-information about the project, our preferred methods, and guides for
-developing MediaGoblin. We even have tips on *becoming* a coder and
-we're willing to help!
-
-Send Encouragement, Spread the Word
------------------------------------
-
-Sometimes, a nice word, simple encouragement, and interest in the work
-we're doing is enough to inspire a tizzy of productive work. Just a
-bit more interest and encouragement can even make the difference
-between a complete feature and limited functionality; between a
-completed milestone and lost momentum.
-
-Similarly, MediaGoblin, and the movement for free network services, is
-always in need of encouragement. Use free network services, understand
-the `principals <http://autonomo.us/2008/07/franklin-street-statement/>`_
-behind the movement, be able to articulate the benefits of free
-network services and the problems with psudo-free applications that
-don't respect the users' freedom.
-
-Write a blog post, post a status update, drop by the `listserv <http://mediagoblin.org/join/>`_
-or join ``#mediagoblin`` on freenode.net and let us know.
-
-Participate in MediaGoblin
-==========================
-
-We're still working on project infrastructure. We hope to have the
-bits in place for these additional things to do in the coming months:
-
-Become a User
--------------
-
-We're building GNU MediaGoblin for us and for you but really
-you're one of us and I am you and we are we and GNU
-MediaGoblin is the walrus.
-
-Sign up for an account. Use the service. Relish in the
-thought that this service comes with a heaping side of Freedom
-and you can salt and pepper it to your liking.
-
-
-Help Others
------------
-
-Have you spent time with GNU MediaGoblin? If so, your
-experience and wisdom are invaluable and you're the best
-person we can think of to help other users with their
-questions.
-
-
-Run your own MediaGoblin Instance
----------------------------------
-
-Are there things about our instance you want to change? Are
-there things about other instances you wish were different?
-Want to test upcoming changes? Want to create patches to
-implement things you need? That's great---you can run your
-own instance!
-
-For more information on deploying your own instance, see
-the `Deployment HOWTO </deploymenthowto.html>`_
-
-.. _translating:
-
-Translate MediaGoblin
----------------------
-
-If you know English and another language and feel comfortable
-translating elements of the interface or even the documentation,
-we'd love to have help translating the software and resources.
-
-Create a Theme
---------------
-
-MedaGoblin development is premised on the idea that the entire
-interface for the platform be completely theme-able. If you have a
-design or theming background, consider developing themes for
-MediaGoblin. New themes help test the theming system, provide
-attractive and appealing interfaces for prospective users. If you want
-to start a new theme but don't know where to start, touch base with
-the development community on the list or in the IRC channel for more
-information.
-
-.. _filing-bugs:
-
-File Bugs
-=========
-
-MediaGoblin uses a bug tracker called `Redmine <http://www.redmine.org>`_.
-
-Our instance is located at `<http://bugs.foocorp.net/projects/mediagoblin>`_.
-
-The most useful bug reports have the following components:
-
-1. A short summary that's 60 characters or less.
-
-2. A description that describes the issue (bug, feature request, ...)
- as well as the context. Consider:
-
- * If you think you've found a bug, can you reproduce it in a
- controlled environment? Is the issue specific to a browser,
- computer, image, media type, or other dimension? All data helps.
-
- * If you're submitting a feature request, are there related links
- on the Internet for more information? Would you be willing to
- help implement or test the feature?
-
-That's it!
-
-The better the issue report, the easier it is to address the bug, and
-the more likely that the developers will be able to resolve the
-issue. If someone has questions about the bug report, they may reach
-out to the reporter directly.
-
-If you get a response after a couple of weeks, find someone on IRC.
-
-.. _triage-bugs:
-
-Triage Bugs
-===========
-
-The triage process involves reviewing bugs, removing duplicates,
-validating that the issues described are reproducible, ensuring that
-the exact behavior is properly documented, diagnosing the cause of
-each issue, and working with developers to ensure that critical bugs
-get addressed. In many cases, developers do this kind of work as a
-matter of course, but one need not be able to code in order to help
-working with bugs.
-
-To triage bugs, go to the `bug tracker <http://bugs.foocorp.net/projects/mediagoblin>`_
-and begin reviewing the open issues. If you are able, attempt to:
-
-- ensure that one or two people in addition to the initial reporter
- have been able to reproduce the issue.
-
-- document the issue more clearly. If you had any trouble reproducing
- the issue, provide any elucidating information that you can to help
- others solve the problem more effectively.
-
-- find a way to resolve the problem or provide a workaround.
-
-For help, instructions, and suggestions be in touch with the
-development community on the list or in the IRC channel for more
-information. With many eyes, all bugs are shallow.
-
-How to Get Help with MediaGoblin
-================================
-
-The usual channels, the IRC channel, the listserv, the bug tracker,
-are all great ways to be in touch with us. Check the `web site <http://mediagoblin.org/pages/join.html>`_
-for more specific contact information.
-
diff --git a/docs/source/deploying.rst b/docs/source/deploying.rst
new file mode 100644
index 00000000..b944a3d3
--- /dev/null
+++ b/docs/source/deploying.rst
@@ -0,0 +1,264 @@
+=====================
+Deploying MediaGoblin
+=====================
+
+GNU MediaGoblin is fairly new and so at the time of writing, there
+aren't easy package-manager-friendly methods to install MediaGoblin.
+However, doing a basic install isn't too complex in and of itself.
+
+There's an almost infinite way to deploy things... for now, we'll keep
+it simple with some assumptions and use a setup that combines
+mediagoblin + virtualenv + fastcgi + nginx on a .deb or .rpm based
+GNU/Linux distro.
+
+Note: these tools are for administrators wanting to deploy a fresh
+install. If instead you want to join in as a contributor, see our
+`Hacking HOWTO <http://wiki.mediagoblin.org/HackingHowto>`_ instead.
+
+Prepare System
+--------------
+
+Dependencies
+~~~~~~~~~~~~
+
+MediaGoblin has the following core dependencies:
+
+- Python 2.6 or 2.7
+- `python-lxml <http://lxml.de/>`_
+- `git <http://git-scm.com/>`_
+- `MongoDB <http://www.mongodb.org/>`_
+- `Python Imaging Library <http://www.pythonware.com/products/pil/>`_ (PIL)
+- `virtualenv <http://www.virtualenv.org/>`_
+
+On a DEB-based system (e.g Debian, gNewSense, Trisquel, Ubuntu, and
+derivatives) issue the following command: ::
+
+ sudo apt-get install mongodb git-core python python-dev python-lxml python-imaging python-virtualenv
+
+On a RPM-based system (e.g. Fedora, RedHat, and derivatives) issue the
+following command: ::
+
+ yum install mongodb-server python-paste-deploy python-paste-script git-core python python-devel python-lxml python-imaging python-virtualenv
+
+Configure MongoDB
+~~~~~~~~~~~~~~~~~
+
+After installing MongoDB some preliminary database configuration may
+be necessary.
+
+Ensure that MongoDB `journaling <http://www.mongodb.org/display/DOCS/Journaling>`_
+is enabled. Journaling is enabled by default in version 2.0 and later
+64-bit MongoDB instances. Check your deployment, and consider enabling
+journaling if you're running 32-bit systems or earlier version.
+
+.. warning::
+
+ Running MongoDB without journaling risks general data corruption
+ and raises the possibility of losing data within a 60-second
+ window when the server restarts.
+
+ MediaGoblin recommends enabling MongoDB's journaling feature by
+ adding a ``--journal`` flag to the command line or a "``journal:
+ true``" option to the configuration file.
+
+MongoDB can take a lot of space by default. If you're planning on
+running a smaller instance, consider the `scaling down guide
+<http://wiki.mediagoblin.org/Scaling_Down>`_ for some appropriate
+tradeoffs to conserve space.
+
+Drop Privileges for MediaGoblin
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+As MediaGoblin does not require special permissions or elevated
+access, you should run MediaGoblin under an existing non-root user or
+preferably create a dedicated user for the purpose of running
+MediaGoblin. Consult your distribution's documentation on how to
+create "system account" or dedicated service user. Ensure that it is
+not possible to log in to your system with as this user.
+
+You should create a working directory for MediaGoblin. This document
+assumes your local git repository will be located at ``/srv/mediagoblin.example.org/mediagoblin/``
+for this documentation. Substitute your prefer ed local deployment path
+as needed.
+
+This document assumes that all operations are performed as this
+user. To drop privileges to this user, run the following command: ::
+
+
+ su - [mediagoblin]``
+
+Where, "``[mediagoblin]`` is the username of the system user that will
+run MediaGoblin.
+
+Install MediaGoblin and Virtualenv
+----------------------------------
+
+As of |version|, MediaGoblin has a rapid development pace. As a result
+the following instructions recommend installing from the ``master``
+branch of the git repository. Eventually production deployments will
+want to transition to running from more consistent releases.
+
+Issue the following commands, to create and change the working
+directory. Modify these commands to reflect your own environment: ::
+
+ mkdir -p /srv/mediagoblin.example.org/
+ cd /srv/mediagoblin.example.org/
+
+Clone the MediaGoblin repository: ::
+
+ git clone git://gitorious.org/mediagoblin/mediagoblin.git
+
+And setup the in-package virtualenv: ::
+
+ cd mediagoblin
+ virtualenv . && ./bin/python setup.py develop
+
+.. note::
+
+ If you have problems here, consider trying to install virtualenv
+ with the ``--distribute`` or ``--no-site-packages`` options. If
+ your system's default Python is in the 3.x series you man need to
+ run ``virtualenv`` with the ``--python=python2.7`` or
+ ``--python=python2.6`` options.
+
+The above provides an in-package install of ``virtualenv``. While this
+is counter to the conventional ``virtualenv`` configuration, it is
+more reliable and considerably easier to configure and illustrate. If
+you're familiar with Python packaging you may consider deploying with
+your preferred the method.
+
+Assuming you are going to deploy with fastcgi, you should also install
+flup: ::
+
+ ./bin/easy_install flup
+
+This concludes the initial configuration of the development
+environment. In the future, if at any point you want update your
+codebase, you should also run: ::
+
+ ./bin/python setup.py develop --upgrade && ./bin/gmg migrate.
+
+Deploy MediaGoblin Services
+---------------------------
+
+Test the Server
+~~~~~~~~~~~~~~~
+
+At this point MediaGoblin should be properly installed. You can
+test the deployment with the following command: ::
+
+ ./lazyserver.sh --server-name=broadcast
+
+You should be able to connect to the machine on port 6543 in your
+browser to confirm that the service is operable.
+
+Connect the Webserver to MediaGoblin with FastCGI
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This section describes how to configure MediaGoblin to work via
+fastcgi. Our configuration example will use nginx, however, you may
+use any webserver of your choice as long as it supports the FastCGI
+protocol. If you do not already have a web server, consider nginx, as
+the configuration files may be more clear than the
+alternatives.
+
+Create a configuration file at
+``/srv/mediagoblin.example.org/nginx.conf`` and create a symbolic link
+into a directory that will be included in your ``nginx`` configuration
+(e.g. "``/etc/nginx/sites-enabled`` or ``/etc/nginx/conf.d``) with
+one of the following commands (as the root user:) ::
+
+ ln -s /srv/mediagoblin.example.org/nginx.conf /etc/nginx/conf.d/
+ ln -s /srv/mediagoblin.example.org/nginx.conf /etc/nginx/sites-enabled/
+
+Modify these commands and locations depending on your preferences and
+the existing configuration of your nginx instance. The contents of
+this ``nginx.conf`` file should be modeled on the following: ::
+
+ server {
+ #################################################
+ # Stock useful config options, but ignore them :)
+ #################################################
+ include /etc/nginx/mime.types;
+
+ autoindex off;
+ default_type application/octet-stream;
+ sendfile on;
+
+ # Gzip
+ gzip on;
+ gzip_min_length 1024;
+ gzip_buffers 4 32k;
+ gzip_types text/plain text/html application/x-javascript text/javascript text/xml text/css;
+
+ #####################################
+ # Mounting MediaGoblin stuff
+ # This is the section you should read
+ #####################################
+
+ server_name mediagoblin.example.org www.mediagoblin.example.org;
+ access_log /var/log/nginx/mediagoblin.example.access.log;
+ error_log /var/log/nginx/mediagoblin.example.error.log;
+
+ # MediaGoblin's stock static files: CSS, JS, etc.
+ location /mgoblin_static/ {
+ alias /srv/mediagoblin.example.org/mediagoblin/mediagoblin/static/;
+ }
+
+ # Instance specific media:
+ location /mgoblin_media/ {
+ alias /srv/mediagoblin.example.org/mediagoblin/user_dev/media/public/;
+ }
+
+ # Mounting MediaGoblin itself via fastcgi.
+ location / {
+ fastcgi_pass 127.0.0.1:26543;
+ include /etc/nginx/fastcgi_params;
+
+ # our understanding vs nginx's handling of script_name vs
+ # path_info don't match :)
+ fastcgi_param PATH_INFO $fastcgi_script_name;
+ fastcgi_param SCRIPT_NAME "";
+ }
+ }
+
+Now, nginx instance is configured to serve the MediaGoblin
+application. Perform a quick test to ensure that this configuration
+works. Restart nginx so it picks up your changes, with a command that
+resembles one of the following (as the root user:) ::
+
+ sudo /etc/init.d/nginx restart
+ sudo /etc/rc.d/nginx restart
+
+Now start MediaGoblin. Use the following command sequence as an
+example: ::
+
+ cd /srv/mediagoblin.example.org/mediagoblin/
+ ./lazyserver.sh --server-name=fcgi fcgi_host=127.0.0.1 fcgi_port=26543
+
+Visit the site you've set up in your browser by visiting
+<http://mediagobilin.example.org>. You should see MediaGoblin!
+
+Production MediaGoblin Deployments with Paste
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The instance configured with ``lazyserver`` is not ideal for a
+production MediaGoblin deployment. Ideally, you should be able to use
+a a control script (i.e. init script.) to launch and restart the
+MediaGoblin process.
+
+Use the following command as the basis for such a script: ::
+
+ CELERY_ALWAYS_EAGER=true \
+ /srv/mediagoblin.example.org/mediagoblin/bin/paster serve \
+ /srv/mediagoblin.example.org/mediagoblin/paste.ini \
+ --pid-file=/tmp/mediagoblin.pid \
+ --server-name=fcgi fcgi_host=127.0.0.1 fcgi_port=26543 \
+
+.. note::
+
+ The above configuration places MediaGoblin in "always eager" mode
+ with Celery. This is fine for development and smaller
+ deployments. However, if you're getting into the really large
+ deployment category, consider reading the section of this manual on
+ Celery.
diff --git a/docs/source/deploymenthowto.rst b/docs/source/deploymenthowto.rst
deleted file mode 100644
index f3093a60..00000000
--- a/docs/source/deploymenthowto.rst
+++ /dev/null
@@ -1,16 +0,0 @@
-.. _deployment-howto:
-
-==================
- Deployment HOWTO
-==================
-
-Step 1: Write code that can be deployed.
-
-Step 2: ?
-
-Step 3: Write the deployment guide and profit!
-
-But seriously, this is a stub since we're not quite there (yet) but if
-you want to see where we are now, you can try to run the latest
-development version by following the instructions on
-`the wiki <http://wiki.mediagoblin.org/>`_.
diff --git a/docs/source/foreword.rst b/docs/source/foreword.rst
index c525d002..835a7e7a 100644
--- a/docs/source/foreword.rst
+++ b/docs/source/foreword.rst
@@ -5,25 +5,15 @@ Foreword
About the MediaGoblin Manual
============================
-Welcome to the GNU MediaGoblin manual. This document targets several
-classes of users, including:
+This is the user manual for MediaGoblin. It covers how to set up and
+configure MediaGoblin and the kind of information that someone running
+MediaGoblin would need to know.
-* users who would like to try the software locally,
-* systems administrators who want to deploy and administer the
- software in "production environments," and
-* anyone who wants to learn how MediaGoblin works.
+We have other documentation at:
-Some information relevant to the MediaGoblin community members,
-including how to get involved (We want and love contributors!) To join
-as a contributor please see the following pages:
-
-* http://mediagoblin.org/pages/join.html for general "join us" information
+* http://mediagoblin.org/join/ for general "join us" information
* http://wiki.mediagoblin.org/ for our contributor-focused wiki
-If you suspect that documentation on http://docs.mediagoblin.org is
-out of date, it might be. The documentation is updated regularly and
-the "living" version of this resource resides in the ``mediagoblin``
-repository with the project's source code the ``docs/`` directory.
Improving the MediaGobiin Manual
================================
@@ -31,16 +21,15 @@ Improving the MediaGobiin Manual
There are a few ways---please pick whichever method is convenient for
you!
-1. Write up a bug report in the bug tracker at http://bugs.foocorp.net/projects/mediagoblin/issues
+1. Write up a bug report in the bug tracker
2. Tell someone on IRC ``#mediagoblin`` on Freenode.
-3. Send an email to Will ``willg at bluesock dot org``, or Sam at
- ``sam@cyborginstitute.com``
+3. Write an email to the devel mailing list.
+
+Information about the bugtracker, IRC and the mailing list is all on
+the `join page`_.
-When you tell us about your issue, please let us know:
+.. _join page: http://mediagoblin.org/join/
-* where you are looking (in git? url of the web-page?)
-* what the issue is, and
-* your thoughts on how to resolve it.
+Patches are the most helpful, but even feedback on what you think
+could be improved and how to improve it is also helpful.
-We hope these materials are useful and we look forward to any and all
-feedback.
diff --git a/docs/source/help.rst b/docs/source/help.rst
new file mode 100644
index 00000000..34d4f37e
--- /dev/null
+++ b/docs/source/help.rst
@@ -0,0 +1,16 @@
+==================================
+ How to Get Help with MediaGoblin
+==================================
+
+There are a couple of ways to get help with problems with MediaGoblin:
+
+1. ask for help on IRC
+
+2. ask for help on the devel mailing list
+
+Details for both IRC and the mailing list are on the `join page`_ of the
+website.
+
+.. _join page: http://mediagoblin.org/join/
+
+
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 93b2a942..e9f3993e 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -12,12 +12,12 @@ Table of Contents:
:maxdepth: 2
foreword
- about_mediagoblin
- deploymenthowto
- theminghowto
- contributinghowto
+ about
+ deploying
+ configuration
+ help
+ theming
codebase
- vision
Indices and tables
diff --git a/docs/source/theminghowto.rst b/docs/source/theming.rst
index 7b40685f..2f4fcb4c 100644
--- a/docs/source/theminghowto.rst
+++ b/docs/source/theming.rst
@@ -1,8 +1,8 @@
-.. _theming-howto:
+.. _theming-chapter:
-===============
- Theming HOWTO
-===============
+=====================
+ Theming MediaGoblin
+=====================
We haven't implemented the necessary scaffolding to allow for theming
yet. Thus, this chapter is a stub.
diff --git a/docs/source/vision.rst b/docs/source/vision.rst
deleted file mode 100644
index fad248df..00000000
--- a/docs/source/vision.rst
+++ /dev/null
@@ -1,142 +0,0 @@
-=========================================
- Design Document: GNU MediaGoblin vision
-=========================================
-
-.. Note::
-
- When we get a wiki, this will get moved there. It's here for now
- mostly because we didn't have a better place for it.
-
-.. Note::
-
- By the time you read this, it's very likely it'll be out of date.
-
-
-This document attempts to describe the envisioned workflow of GNU
-MediaGoblin, from a structural standpoint. For now, *nothing* in this
-document is probably the eventual, final way that things will work.
-Eventually as things come to exist, this document will hopefully be
-refactored to describe how things *do* work.
-
-This documented on hopes, dreams, rainbows, and unicorns. And it will
-come to fulfillment through a lot of hard work. Your hard work and my
-hard work.
-
-
-Look and feel
-=============
-
-Default look and feel
----------------------
-
-Mairin Duffy made mockups for something called Design Hub. That
-project did a number of things differently than the way we intend to
-go, but it's probably a good idea to steal a good number of ideas from
-here.
-
-http://mairin.wordpress.com/2010/03/09/another-design-hub-mockup/
-
-
-User profile mockup
--------------------
-
-Here's an ascii art mockup on how things might look for a user's page::
-
- _____
- |_( )_| USER NAME
- | | |
- |_/_\_|
-
- Recent artwork:
- ___________________ ___________________________
- | ___ ___ ___ | |_About_User_Name___________|
- | |pic| |pic| |pic| | | |
- | |___| |___| |___| | | Some sort of self- |
- | ___ ___ ___ | | description probably goes |
- < | |pic| |pic| |pic| | > | here |
- | |___| |___| |___| | | |
- | ___ ___ ___ | | |
- | |pic| |pic| |pic| | | |
- | |___| |___| |___| | | |
- |___________________| |___________________________|
-
- ___________________________
- Recent favorites: |_Recent_activity___________|
- ___________________ | New picture: DragonFace |
- | ___ ___ ___ | | 4/2/2010 |
- | |pic| |pic| |pic| | |---------------------------|
- | |___| |___| |___| | | Sup yall this is some kind|
- | ___ ___ ___ | | of mini blogpost. Maybe |
- < | |pic| |pic| |pic| | > | the interface will allow |
- | |___| |___| |___| | | for this? |
- | ___ ___ ___ | |___________________________|
- | |pic| |pic| |pic| |
- | |___| |___| |___| | ___________________________
- |___________________| |_External_comments_here____|
- | Dang! This stuff rocks |
- | - Joe 4/2/2010 |
- |---------------------------|
- | Nice job on the dragon |
- | - Morgan 4/2/2010 |
- '---------------------------'
-
-So there's this type of interface that puts a lot of different types
-of info on the same screen. I'm not sure that I like it. It's
-possible we'll go with something much more minimalist. Maybe we'll go
-with something "tabbed" the way statusnet / http://identi.ca is on
-user pages.
-
-It's possible that we could support multiple profile styles here,
-and you could load whatever profile style you want as set by user
-preferences?
-
-
-Uploading mockup
-----------------
-
-Here's an uploading mockup::
-
- Upload an image
-
- [ Title ]
-
- Upload: [ ] [Browse]
- ___________________________________________
- | |
- | |
- | o0O |
- | o ' |
- | o_.' |
- | |
- | Uploading... OK | <-,
- | Resizing... OK | |
- | | Area replaced w/ resized
- | | image when done
- |___________________________________________|
- ________________
- License |_CC BY-SA_____|V|
- ___________________________________________
- | Description goes here. |
- | You can type it up in here and everything |
- | and it'll show up under the image. |
- | |
- | Possibly we should allow some kind of |
- | markup... maybe markdown? |
- '___________________________________________'
-
- __________________________________________
- |> Advanced |
- ------------------------------------------
-
-
-Customizability
----------------
-
-General site theming customizability is pretty easy! Since we're
-using `Jinja <http://jinja.pocoo.org/docs/>`_ we can just set up
-user-overriding directories.
-
-We'll also figure out some sort of way to provide theming "packages",
-eventually.
-
-
diff --git a/lazyserver.sh b/lazyserver.sh
index e4afdaa5..63818a6a 100755
--- a/lazyserver.sh
+++ b/lazyserver.sh
@@ -18,13 +18,24 @@
if [ "$1" = "-h" ]
then
- echo "$0 [-h] [-c paste.ini] ARGS_to_paster"
+ echo "$0 [-h] [-c paste.ini] [ARGS_to_paster ...]"
+ echo ""
echo " For example:"
- echo " $0 -c fcgi.ini port_number=23371"
+ echo " $0 -c fcgi.ini port_number=23371"
+ echo " or: $0 --server-name=fcgi"
+ echo ""
+ echo " The configfile defaults to paste_local.ini,"
+ echo " if that is readable, otherwise paste.ini."
exit 1
fi
PASTE_INI=paste.ini
+
+if [ -r paste_local.ini ]
+then
+ PASTE_INI=paste_local.ini
+fi
+
if [ "$1" = "-c" ]
then
PASTE_INI="$2"
@@ -32,6 +43,8 @@ then
shift
fi
+echo "Using paste config: $PASTE_INI"
+
if [ -f ./bin/paster ]; then
echo "Using ./bin/paster";
export PASTER="./bin/paster";
diff --git a/mediagoblin.ini b/mediagoblin.ini
index c22d12d7..728ab2f2 100644
--- a/mediagoblin.ini
+++ b/mediagoblin.ini
@@ -1,3 +1,6 @@
+# If you want to make changes to this file, first copy it to
+# mediagoblin_local.ini, then make the changes there.
+
[mediagoblin]
direct_remote_path = /mgoblin_static/
email_sender_address = "notice@mediagoblin.example.org"
diff --git a/mediagoblin/_version.py b/mediagoblin/_version.py
index df212faf..d6c6e20d 100644
--- a/mediagoblin/_version.py
+++ b/mediagoblin/_version.py
@@ -14,4 +14,4 @@
# 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/>.
-__version__ = "0.0.5"
+__version__ = "0.1.0"
diff --git a/mediagoblin/app.py b/mediagoblin/app.py
index dd5f0b89..ce4b0bec 100644
--- a/mediagoblin/app.py
+++ b/mediagoblin/app.py
@@ -20,7 +20,10 @@ import urllib
import routes
from webob import Request, exc
-from mediagoblin import routing, util, middleware
+from mediagoblin import routing, middleware
+from mediagoblin.tools import common, translate, template
+from mediagoblin.tools.response import render_404
+from mediagoblin.tools import request as mg_request
from mediagoblin.mg_globals import setup_globals
from mediagoblin.init.celery import setup_celery_from_config
from mediagoblin.init import (get_jinja_loader, get_staticdirector,
@@ -91,17 +94,16 @@ class MediaGoblinApp(object):
# object.
#######################################################
- setup_globals(app = self)
+ setup_globals(app=self)
# Workbench *currently* only used by celery, so this only
# matters in always eager mode :)
setup_workbench()
# instantiate application middleware
- self.middleware = [util.import_component(m)(self)
+ self.middleware = [common.import_component(m)(self)
for m in middleware.ENABLED_MIDDLEWARE]
-
def __call__(self, environ, start_response):
request = Request(environ)
@@ -115,6 +117,17 @@ class MediaGoblinApp(object):
path_info = request.path_info
route_match = self.routing.match(path_info)
+ # By using fcgi, mediagoblin can run under a base path
+ # like /mediagoblin/. request.path_info contains the
+ # path inside mediagoblin. If the something needs the
+ # full path of the current page, that should include
+ # the basepath.
+ # Note: urlgen and routes are fine!
+ request.full_path = environ["SCRIPT_NAME"] + request.path_info
+ # python-routes uses SCRIPT_NAME. So let's use that too.
+ # The other option would be:
+ # request.full_path = environ["SCRIPT_URL"]
+
## Attach utilities to the request object
request.matchdict = route_match
request.urlgen = routes.URLGenerator(self.routing, environ)
@@ -123,14 +136,14 @@ class MediaGoblinApp(object):
# Attach self as request.app
# Also attach a few utilities from request.app for convenience?
request.app = self
- request.locale = util.get_locale_from_request(request)
+ request.locale = translate.get_locale_from_request(request)
- request.template_env = util.get_jinja_env(
+ request.template_env = template.get_jinja_env(
self.template_loader, request.locale)
request.db = self.db
request.staticdirect = self.staticdirector
- util.setup_user_in_request(request)
+ mg_request.setup_user_in_request(request)
# No matching page?
if route_match is None:
@@ -148,9 +161,9 @@ class MediaGoblinApp(object):
# Okay, no matches. 404 time!
request.matchdict = {} # in case our template expects it
- return util.render_404(request)(environ, start_response)
+ return render_404(request)(environ, start_response)
- controller = util.import_component(route_match['controller'])
+ controller = common.import_component(route_match['controller'])
request.start_response = start_response
# get the response from the controller
@@ -164,6 +177,16 @@ class MediaGoblinApp(object):
def paste_app_factory(global_config, **app_config):
- mgoblin_app = MediaGoblinApp(app_config['config'])
+ configs = app_config['config'].split()
+ mediagoblin_config = None
+ for config in configs:
+ if os.path.exists(config) and os.access(config, os.R_OK):
+ mediagoblin_config = config
+ break
+
+ if not mediagoblin_config:
+ raise IOError("Usable mediagoblin config not found.")
+
+ mgoblin_app = MediaGoblinApp(mediagoblin_config)
return mgoblin_app
diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py
index 6339b4a3..dcb6766c 100644
--- a/mediagoblin/auth/forms.py
+++ b/mediagoblin/auth/forms.py
@@ -17,7 +17,7 @@
import wtforms
import re
-from mediagoblin.util import fake_ugettext_passthrough as _
+from mediagoblin.tools.translate import fake_ugettext_passthrough as _
class RegistrationForm(wtforms.Form):
@@ -59,9 +59,10 @@ class ForgotPassForm(wtforms.Form):
'Username or email',
[wtforms.validators.Required()])
- def validate_username(form,field):
- if not (re.match(r'^\w+$',field.data) or
- re.match(r'^.+@[^.].*\.[a-z]{2,10}$',field.data, re.IGNORECASE)):
+ def validate_username(form, field):
+ if not (re.match(r'^\w+$', field.data) or
+ re.match(r'^.+@[^.].*\.[a-z]{2,10}$', field.data,
+ re.IGNORECASE)):
raise wtforms.ValidationError(u'Incorrect input')
@@ -82,4 +83,3 @@ class ChangePassForm(wtforms.Form):
token = wtforms.HiddenField(
'',
[wtforms.validators.Required()])
-
diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py
index d7d351a5..cf4a2b83 100644
--- a/mediagoblin/auth/lib.py
+++ b/mediagoblin/auth/lib.py
@@ -19,7 +19,8 @@ import random
import bcrypt
-from mediagoblin.util import send_email, render_template
+from mediagoblin.tools.mail import send_email
+from mediagoblin.tools.template import render_template
from mediagoblin import mg_globals
@@ -93,6 +94,7 @@ EMAIL_VERIFICATION_TEMPLATE = (
u"http://{host}{uri}?"
u"userid={userid}&token={verification_key}")
+
def send_verification_email(user, request):
"""
Send the verification email to users to activate their accounts.
@@ -107,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
@@ -127,6 +129,7 @@ EMAIL_FP_VERIFICATION_TEMPLATE = (
u"http://{host}{uri}?"
u"userid={userid}&token={fp_verification_key}")
+
def send_fp_verification_email(user, request):
"""
Send the verification email to users to change their password.
@@ -141,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
@@ -150,4 +153,3 @@ def send_fp_verification_email(user, request):
[user['email']],
'GNU MediaGoblin - Change forgotten password!',
rendered_email)
-
diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py
index 912d89fa..365ccfaa 100644
--- a/mediagoblin/auth/routing.py
+++ b/mediagoblin/auth/routing.py
@@ -33,7 +33,8 @@ auth_routes = [
controller='mediagoblin.views:simple_template_render'),
Route('mediagoblin.auth.forgot_password', '/forgot_password/',
controller='mediagoblin.auth.views:forgot_password'),
- Route('mediagoblin.auth.verify_forgot_password', '/forgot_password/verify/',
+ Route('mediagoblin.auth.verify_forgot_password',
+ '/forgot_password/verify/',
controller='mediagoblin.auth.views:verify_forgot_password'),
Route('mediagoblin.auth.fp_changed_success',
'/forgot_password/changed_success/',
diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py
index f67f0588..d01861d1 100644
--- a/mediagoblin/auth/views.py
+++ b/mediagoblin/auth/views.py
@@ -21,8 +21,8 @@ from webob import exc
from mediagoblin import messages
from mediagoblin import mg_globals
-from mediagoblin.util import render_to_response, redirect, render_404
-from mediagoblin.util import pass_to_ugettext as _
+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
@@ -30,6 +30,19 @@ from mediagoblin.auth.lib import send_verification_email, \
send_fp_verification_email
+def email_debug_message(request):
+ """
+ If the server is running in email debug mode (which is
+ the current default), give a debug message to the user
+ so that they have an idea where to find their email.
+ """
+ if mg_globals.app_config['email_debug_mode']:
+ # DEBUG message, no need to translate
+ messages.add_message(request, messages.DEBUG,
+ u"This instance is running in email debug mode. "
+ u"The email will be on the console of the server process.")
+
+
def register(request):
"""
Your classic registration view!
@@ -61,7 +74,7 @@ def register(request):
extra_validation_passes = False
if users_with_email:
register_form.email.errors.append(
- _(u'Sorry, that email address has already been taken.'))
+ _(u'Sorry, a user with that email address already exists.'))
extra_validation_passes = False
if extra_validation_passes:
@@ -74,10 +87,11 @@ def register(request):
user.save(validate=True)
# log the user in
- request.session['user_id'] = unicode(user['_id'])
+ request.session['user_id'] = unicode(user._id)
request.session.save()
# send verification email
+ email_debug_message(request)
send_verification_email(user, request)
# redirect the user to their homepage... there will be a
@@ -108,7 +122,7 @@ def login(request):
if user and user.check_login(request.POST['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.POST.get('next'):
@@ -146,7 +160,7 @@ def verify_email(request):
you are lucky :)
"""
# If we don't have userid and token parameters, we can't do anything; 404
- if not request.GET.has_key('userid') or not request.GET.has_key('token'):
+ if not 'userid' in request.GET or not 'token' in request.GET:
return render_404(request)
user = request.db.User.find_one(
@@ -181,9 +195,27 @@ def resend_activation(request):
Resend the activation email.
"""
+
+ if request.user is None:
+ messages.add_message(
+ request,
+ messages.ERROR,
+ _('You must be logged in so we know who to send the email to!'))
+
+ return redirect(request, 'mediagoblin.auth.login')
+
+ if request.user["email_verified"]:
+ messages.add_message(
+ request,
+ messages.ERROR,
+ _("You've already verified your email address!"))
+
+ return redirect(request, "mediagoblin.user_pages.user_home", user=request.user['username'])
+
request.user[u'verification_key'] = unicode(uuid.uuid4())
request.user.save()
-
+
+ email_debug_message(request)
send_verification_email(request.user, request)
messages.add_message(
@@ -204,6 +236,11 @@ def forgot_password(request):
fp_form = auth_forms.ForgotPassForm(request.POST)
if request.method == 'POST' and fp_form.validate():
+
+ # Here, so it doesn't depend on the actual mail being sent
+ # and thus doesn't reveal, wether mail was sent.
+ email_debug_message(request)
+
# '$or' not available till mongodb 1.5.3
user = request.db.User.find_one(
{'username': request.POST['username']})
@@ -233,8 +270,7 @@ def forgot_password(request):
request, 'mediagoblin.user_pages.user_home',
user=user['username'])
-
- # do not reveal whether or not there is a matching user, just move along
+ # do not reveal whether or not there is a matching user
return redirect(request, 'mediagoblin.auth.fp_email_sent')
return render_to_response(
@@ -308,6 +344,6 @@ def _process_for_token(request):
formdata = {
'vars': formdata_vars,
'has_userid_and_token':
- formdata_vars.has_key('userid') and formdata_vars.has_key('token')}
+ 'userid' in formdata_vars and 'token' in formdata_vars}
return formdata
diff --git a/mediagoblin/config_spec.ini b/mediagoblin/config_spec.ini
index 0801b39e..eef6f6e0 100644
--- a/mediagoblin/config_spec.ini
+++ b/mediagoblin/config_spec.ini
@@ -1,4 +1,7 @@
[mediagoblin]
+# HTML title of the pages
+html_title = string(default="GNU MediaGoblin")
+
# database stuff
db_host = string()
db_name = string(default="mediagoblin")
@@ -27,6 +30,9 @@ allow_registration = boolean(default=True)
tags_delimiter = string(default=",")
tags_max_length = integer(default=50)
+# Whether comments are ascending or descending
+comments_ascending = boolean(default=True)
+
# By default not set, but you might want something like:
# "%(here)s/user_dev/templates/"
local_templates = string()
@@ -41,6 +47,8 @@ celery_setup_elsewhere = boolean(default=False)
# source files for a media file but can also be a HUGE security risk.
allow_attachments = boolean(default=False)
+# Cookie stuff
+csrf_cookie_name = string(default='mediagoblin_csrftoken')
[storage:publicstore]
storage_class = string(default="mediagoblin.storage.filestorage:BasicFileStorage")
diff --git a/mediagoblin/db/__init__.py b/mediagoblin/db/__init__.py
index c5124b1a..27e8a90f 100644
--- a/mediagoblin/db/__init__.py
+++ b/mediagoblin/db/__init__.py
@@ -23,7 +23,7 @@ Database Abstraction/Wrapper Layer
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
diff --git a/mediagoblin/db/indexes.py b/mediagoblin/db/indexes.py
index 75394a31..1dd73f2b 100644
--- a/mediagoblin/db/indexes.py
+++ b/mediagoblin/db/indexes.py
@@ -93,8 +93,9 @@ MEDIAENTRY_INDEXES = {
('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.
+ # 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),
diff --git a/mediagoblin/db/migrations.py b/mediagoblin/db/migrations.py
index 01df7208..cfc01287 100644
--- a/mediagoblin/db/migrations.py
+++ b/mediagoblin/db/migrations.py
@@ -15,7 +15,18 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from mediagoblin.db.util import RegisterMigration
-from mediagoblin.util import cleaned_markdown_conversion
+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)
# Please see mediagoblin/tests/test_migrations.py for some examples of
@@ -70,11 +81,7 @@ def mediaentry_add_queued_task_id(database):
"""
Add the 'queued_task_id' field for entries that don't have it.
"""
- collection = database['media_entries']
- collection.update(
- {'queued_task_id': {'$exists': False}},
- {'$set': {'queued_task_id': None}},
- multi=True)
+ add_table_field(database, 'media_entries', 'queued_task_id', None)
@RegisterMigration(5)
@@ -82,16 +89,8 @@ def mediaentry_add_fail_error_and_metadata(database):
"""
Add 'fail_error' and 'fail_metadata' fields to media entries
"""
- collection = database['media_entries']
- collection.update(
- {'fail_error': {'$exists': False}},
- {'$set': {'fail_error': None}},
- multi=True)
-
- collection.update(
- {'fail_metadata': {'$exists': False}},
- {'$set': {'fail_metadata': {}}},
- multi=True)
+ add_table_field(database, 'media_entries', 'fail_error', None)
+ add_table_field(database, 'media_entries', 'fail_metadata', {})
@RegisterMigration(6)
@@ -99,14 +98,8 @@ def user_add_forgot_password_token_and_expires(database):
"""
Add token and expiration fields to help recover forgotten passwords
"""
- database['users'].update(
- {'fp_verification_key': {'$exists': False}},
- {'$set': {'fp_verification_key': None}},
- multi=True)
- database['users'].update(
- {'fp_token_expire': {'$exists': False}},
- {'$set': {'fp_token_expire': None}},
- multi=True)
+ add_table_field(database, 'users', 'fp_verification_key', None)
+ add_table_field(database, 'users', 'fp_token_expire', None)
@RegisterMigration(7)
diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py
index bbddada6..f13a4457 100644
--- a/mediagoblin/db/models.py
+++ b/mediagoblin/db/models.py
@@ -14,18 +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/>.
-import datetime, uuid
+import datetime
+import uuid
from mongokit import Document
-from mediagoblin import util
from mediagoblin.auth import lib as auth_lib
from mediagoblin import mg_globals
from mediagoblin.db import migrations
from mediagoblin.db.util import ASCENDING, DESCENDING, ObjectId
-from mediagoblin.util import Pagination
-from mediagoblin.util import DISPLAY_IMAGE_FETCHING_ORDER
-
+from mediagoblin.tools.pagination import Pagination
+from mediagoblin.tools import url, common
###################
# Custom validators
@@ -64,22 +63,23 @@ class User(Document):
- bio_html: biography of the user converted to proper HTML.
"""
__collection__ = 'users'
+ use_dot_notation = True
structure = {
'username': unicode,
'email': unicode,
'created': datetime.datetime,
- 'plugin_data': dict, # plugins can dump stuff here.
+ 'plugin_data': dict, # plugins can dump stuff here.
'pw_hash': unicode,
'email_verified': bool,
'status': unicode,
'verification_key': unicode,
'is_admin': bool,
- 'url' : unicode,
- 'bio' : unicode, # May contain markdown
- 'bio_html': unicode, # May contain plaintext, or HTML
- 'fp_verification_key': unicode, # forgotten password verification key
- 'fp_token_expire': datetime.datetime
+ 'url': unicode,
+ 'bio': unicode, # May contain markdown
+ 'bio_html': unicode, # May contain plaintext, or HTML
+ 'fp_verification_key': unicode, # forgotten password verification key
+ 'fp_token_expire': datetime.datetime,
}
required_fields = ['username', 'created', 'pw_hash', 'email']
@@ -174,21 +174,22 @@ class MediaEntry(Document):
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:
+ - 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
- 'description_html': unicode, # May contain plaintext, or HTML
+ 'description': unicode, # May contain markdown/up
+ 'description_html': unicode, # May contain plaintext, or HTML
'media_type': unicode,
- 'media_data': dict, # extra data relevant to this media_type
- 'plugin_data': dict, # plugins can dump stuff here.
+ 'media_data': dict, # extra data relevant to this media_type
+ 'plugin_data': dict, # plugins can dump stuff here.
'tags': [dict],
'state': unicode,
@@ -216,11 +217,17 @@ class MediaEntry(Document):
'created': datetime.datetime.utcnow,
'state': u'unprocessed'}
- def get_comments(self):
+ def get_comments(self, ascending=False):
+ if ascending:
+ order = ASCENDING
+ else:
+ order = DESCENDING
+
return self.db.MediaComment.find({
- 'media_entry': self['_id']}).sort('created', DESCENDING)
+ 'media_entry': self._id}).sort('created', order)
- def get_display_media(self, media_map, fetch_order=DISPLAY_IMAGE_FETCHING_ORDER):
+ def get_display_media(self, media_map,
+ fetch_order=common.DISPLAY_IMAGE_FETCHING_ORDER):
"""
Find the best media for display.
@@ -234,7 +241,7 @@ class MediaEntry(Document):
"""
media_sizes = media_map.keys()
- for media_size in DISPLAY_IMAGE_FETCHING_ORDER:
+ for media_size in common.DISPLAY_IMAGE_FETCHING_ORDER:
if media_size in media_sizes:
return media_map[media_size]
@@ -242,13 +249,13 @@ class MediaEntry(Document):
pass
def generate_slug(self):
- self['slug'] = util.slugify(self['title'])
+ self['slug'] = url.slugify(self['title'])
duplicate = mg_globals.database.media_entries.find_one(
{'slug': self['slug']})
if duplicate:
- self['slug'] = "%s-%s" % (self['_id'], self['slug'])
+ self['slug'] = "%s-%s" % (self._id, self['slug'])
def url_for_self(self, urlgen):
"""
@@ -267,13 +274,13 @@ class MediaEntry(Document):
return urlgen(
'mediagoblin.user_pages.media_home',
user=uploader['username'],
- media=unicode(self['_id']))
+ media=unicode(self._id))
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']},
+ cursor = self.db.MediaEntry.find({'_id': {"$gt": self._id},
'uploader': self['uploader'],
'state': 'processed'}).sort(
'_id', ASCENDING).limit(1)
@@ -286,7 +293,7 @@ class MediaEntry(Document):
"""
Provide a url to the next entry from this user, if there is one
"""
- cursor = self.db.MediaEntry.find({'_id' : {"$lt": self['_id']},
+ cursor = self.db.MediaEntry.find({'_id': {"$lt": self._id},
'uploader': self['uploader'],
'state': 'processed'}).sort(
'_id', DESCENDING).limit(1)
@@ -304,7 +311,7 @@ class MediaEntry(Document):
Get the exception that's appropriate for this error
"""
if self['fail_error']:
- return util.import_component(self['fail_error'])
+ return common.import_component(self['fail_error'])
class MediaComment(Document):
@@ -321,6 +328,7 @@ class MediaComment(Document):
"""
__collection__ = 'media_comments'
+ use_dot_notation = True
structure = {
'media_entry': ObjectId,
@@ -353,4 +361,3 @@ def register_models(connection):
Register all models in REGISTER_MODELS with this connection.
"""
connection.register(REGISTER_MODELS)
-
diff --git a/mediagoblin/db/open.py b/mediagoblin/db/open.py
index e73b6258..e677ba12 100644
--- a/mediagoblin/db/open.py
+++ b/mediagoblin/db/open.py
@@ -29,7 +29,7 @@ def connect_database_from_config(app_config, use_pymongo=False):
port = app_config.get('db_port')
if port:
port = asint(port)
-
+
if use_pymongo:
connection = pymongo.Connection(
app_config.get('db_host'), port)
diff --git a/mediagoblin/db/util.py b/mediagoblin/db/util.py
index 84a6cbce..52e97f6d 100644
--- a/mediagoblin/db/util.py
+++ b/mediagoblin/db/util.py
@@ -118,11 +118,12 @@ def remove_deprecated_indexes(database, deprecated_indexes=DEPRECATED_INDEXES):
#################
# 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
+class MissingCurrentMigration(Exception):
+ pass
MIGRATIONS = {}
@@ -147,7 +148,7 @@ class RegisterMigration(object):
"""
def __init__(self, migration_number, migration_registry=MIGRATIONS):
assert migration_number > 0, "Migration number must be > 0!"
- assert not migration_registry.has_key(migration_number), \
+ assert migration_number not in migration_registry, \
"Duplicate migration numbers detected! That's not allowed!"
self.migration_number = migration_number
diff --git a/mediagoblin/decorators.py b/mediagoblin/decorators.py
index 7d5978fc..8f7532ec 100644
--- a/mediagoblin/decorators.py
+++ b/mediagoblin/decorators.py
@@ -17,7 +17,7 @@
from webob import exc
-from mediagoblin.util import redirect, render_404
+from mediagoblin.tools.response import redirect, render_404
from mediagoblin.db.util import ObjectId, InvalidId
@@ -45,7 +45,7 @@ def require_active_login(controller):
return exc.HTTPFound(
location="%s?next=%s" % (
request.urlgen("mediagoblin.auth.login"),
- request.path_info))
+ request.full_path))
return controller(request, *args, **kwargs)
@@ -60,7 +60,7 @@ def user_may_delete_media(controller):
uploader = request.db.MediaEntry.find_one(
{'_id': ObjectId(request.matchdict['media'])}).uploader()
if not (request.user['is_admin'] or
- request.user['_id'] == uploader['_id']):
+ request.user._id == uploader._id):
return exc.HTTPForbidden()
return controller(request, *args, **kwargs)
@@ -99,7 +99,7 @@ def get_user_media_entry(controller):
media = request.db.MediaEntry.find_one(
{'slug': request.matchdict['media'],
'state': 'processed',
- 'uploader': user['_id']})
+ 'uploader': user._id})
# no media via slug? Grab it via ObjectId
if not media:
@@ -107,7 +107,7 @@ def get_user_media_entry(controller):
media = request.db.MediaEntry.find_one(
{'_id': ObjectId(request.matchdict['media']),
'state': 'processed',
- 'uploader': user['_id']})
+ 'uploader': user._id})
except InvalidId:
return render_404(request)
@@ -119,6 +119,7 @@ def get_user_media_entry(controller):
return _make_safe(wrapper, controller)
+
def get_media_entry_by_id(controller):
"""
Pass in a MediaEntry based off of a url component
@@ -138,4 +139,3 @@ def get_media_entry_by_id(controller):
return controller(request, media=media, *args, **kwargs)
return _make_safe(wrapper, controller)
-
diff --git a/mediagoblin/edit/__init__.py b/mediagoblin/edit/__init__.py
index 576bd0f5..ba347c69 100644
--- a/mediagoblin/edit/__init__.py
+++ b/mediagoblin/edit/__init__.py
@@ -13,5 +13,3 @@
#
# 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/>.
-
-
diff --git a/mediagoblin/edit/forms.py b/mediagoblin/edit/forms.py
index f81d58b2..93934be7 100644
--- a/mediagoblin/edit/forms.py
+++ b/mediagoblin/edit/forms.py
@@ -14,12 +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/>.
-
import wtforms
-from mediagoblin.util import tag_length_validator, TOO_LONG_TAG_WARNING
-from mediagoblin.util import fake_ugettext_passthrough as _
-
+from mediagoblin.tools.text import tag_length_validator, TOO_LONG_TAG_WARNING
+from mediagoblin.tools.translate import fake_ugettext_passthrough as _
class EditForm(wtforms.Form):
title = wtforms.TextField(
@@ -28,7 +26,9 @@ class EditForm(wtforms.Form):
description = wtforms.TextAreaField('Description of this work')
tags = wtforms.TextField(
_('Tags'),
- [tag_length_validator])
+ [tag_length_validator],
+ description=_(
+ "Seperate tags by commas or spaces."))
slug = wtforms.TextField(
_('Slug'),
[wtforms.validators.Required(message=_("The slug can't be empty"))],
@@ -45,6 +45,19 @@ class EditProfileForm(wtforms.Form):
_('Website'),
[wtforms.validators.Optional(),
wtforms.validators.URL(message='Improperly formed URL')])
+ old_password = wtforms.PasswordField(
+ _('Old password'),
+ [wtforms.validators.Optional()])
+ new_password = wtforms.PasswordField(
+ _('New Password'),
+ [wtforms.validators.Optional(),
+ wtforms.validators.Length(min=6, max=30),
+ wtforms.validators.EqualTo(
+ 'confirm_password',
+ 'Passwords must match.')])
+ confirm_password = wtforms.PasswordField(
+ 'Confirm password',
+ [wtforms.validators.Optional()])
class EditAttachmentsForm(wtforms.Form):
diff --git a/mediagoblin/edit/lib.py b/mediagoblin/edit/lib.py
index b722e9c1..458b704e 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/views.py b/mediagoblin/edit/views.py
index 15edfdd6..673409bd 100644
--- a/mediagoblin/edit/views.py
+++ b/mediagoblin/edit/views.py
@@ -25,14 +25,16 @@ from werkzeug.utils import secure_filename
from mediagoblin import messages
from mediagoblin import mg_globals
-from mediagoblin.util import (
- render_to_response, redirect, clean_html, convert_to_tag_list_of_dicts,
- media_tags_as_string, cleaned_markdown_conversion)
-from mediagoblin.util import pass_to_ugettext as _
+
+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
-
+from mediagoblin.tools.response import render_to_response, redirect
+from mediagoblin.tools.translate import pass_to_ugettext as _
+from mediagoblin.tools.text import (
+ clean_html, convert_to_tag_list_of_dicts,
+ media_tags_as_string, cleaned_markdown_conversion)
@get_user_media_entry
@require_active_login
@@ -56,7 +58,7 @@ def edit_media(request, media):
existing_user_slug_entries = request.db.MediaEntry.find(
{'slug': request.POST['slug'],
'uploader': media['uploader'],
- '_id': {'$ne': media['_id']}}).count()
+ '_id': {'$ne': media._id}}).count()
if existing_user_slug_entries:
form.slug.errors.append(
@@ -77,7 +79,7 @@ def edit_media(request, media):
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,
@@ -103,7 +105,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',
secure_filename(request.POST['attachment_file'].filename)])
attachment_public_file = mg_globals.public_store.get_file(
@@ -119,7 +121,7 @@ def edit_attachments(request, media):
name=request.POST['attachment_name'] \
or request.POST['attachment_file'].filename,
filepath=attachment_public_filepath,
- created=datetime.utcnow()
+ created=datetime.utcnow(),
))
media.save()
@@ -160,19 +162,37 @@ def edit_profile(request):
bio=user.get('bio'))
if request.method == 'POST' and form.validate():
- user['url'] = unicode(request.POST['url'])
- user['bio'] = unicode(request.POST['bio'])
+ password_matches = auth_lib.bcrypt_check_password(
+ request.POST['old_password'],
+ user['pw_hash'])
+
+ if (request.POST['old_password'] or request.POST['new_password']) and not \
+ password_matches:
+ form.old_password.errors.append(_('Wrong password'))
+
+ return render_to_response(
+ request,
+ 'mediagoblin/edit/edit_profile.html',
+ {'user': user,
+ 'form': form})
+
+ user['url'] = unicode(request.POST['url'])
+ user['bio'] = unicode(request.POST['bio'])
+
+ if password_matches:
+ user['pw_hash'] = auth_lib.bcrypt_gen_password_hash(
+ request.POST['new_password'])
- user['bio_html'] = cleaned_markdown_conversion(user['bio'])
+ user['bio_html'] = cleaned_markdown_conversion(user['bio'])
- user.save()
+ user.save()
- messages.add_message(request,
- messages.SUCCESS,
- 'Profile edited!')
- return redirect(request,
- 'mediagoblin.user_pages.user_home',
- user=edit_username)
+ messages.add_message(request,
+ messages.SUCCESS,
+ _("Profile edited!"))
+ return redirect(request,
+ 'mediagoblin.user_pages.user_home',
+ user=user['username'])
return render_to_response(
request,
diff --git a/mediagoblin/gmg_commands/__init__.py b/mediagoblin/gmg_commands/__init__.py
index 0071c65b..04187ff2 100644
--- a/mediagoblin/gmg_commands/__init__.py
+++ b/mediagoblin/gmg_commands/__init__.py
@@ -15,8 +15,9 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import argparse
+import os
-from mediagoblin import util as mg_util
+from mediagoblin.tools.common import import_component
SUBCOMMAND_MAP = {
@@ -28,7 +29,7 @@ SUBCOMMAND_MAP = {
'setup': 'mediagoblin.gmg_commands.migrate:migrate_parser_setup',
'func': 'mediagoblin.gmg_commands.migrate:migrate',
'help': 'Apply all unapplied bulk migrations to the database'},
- 'adduser':{
+ 'adduser': {
'setup': 'mediagoblin.gmg_commands.users:adduser_parser_setup',
'func': 'mediagoblin.gmg_commands.users:adduser',
'help': 'Creates an user'},
@@ -58,26 +59,38 @@ SUBCOMMAND_MAP = {
def main_cli():
parser = argparse.ArgumentParser(
description='GNU MediaGoblin utilities.')
+ parser.add_argument(
+ '-cf', '--conf_file', default=None,
+ help=(
+ "Config file used to set up environment. "
+ "Default to mediagoblin_local.ini if readable, "
+ "otherwise mediagoblin.ini"))
subparsers = parser.add_subparsers(help='sub-command help')
for command_name, command_struct in SUBCOMMAND_MAP.iteritems():
- if command_struct.has_key('help'):
+ if 'help' in command_struct:
subparser = subparsers.add_parser(
command_name, help=command_struct['help'])
else:
subparser = subparsers.add_parser(command_name)
- setup_func = mg_util.import_component(command_struct['setup'])
- exec_func = mg_util.import_component(command_struct['func'])
+ setup_func = import_component(command_struct['setup'])
+ exec_func = import_component(command_struct['func'])
setup_func(subparser)
subparser.set_defaults(func=exec_func)
args = parser.parse_args()
+ if args.conf_file is None:
+ if os.path.exists('mediagoblin_local.ini') \
+ and os.access('mediagoblin_local.ini', os.R_OK):
+ args.conf_file = 'mediagoblin_local.ini'
+ else:
+ args.conf_file = 'mediagoblin.ini'
+
args.func(args)
if __name__ == '__main__':
main_cli()
-
diff --git a/mediagoblin/gmg_commands/import_export.py b/mediagoblin/gmg_commands/import_export.py
index fefbdb4e..4ec17d47 100644
--- a/mediagoblin/gmg_commands/import_export.py
+++ b/mediagoblin/gmg_commands/import_export.py
@@ -16,7 +16,6 @@
from mediagoblin import mg_globals
from mediagoblin.db.open import setup_connection_and_db_from_config
-from mediagoblin.init.config import read_mediagoblin_config
from mediagoblin.storage.filestorage import BasicFileStorage
from mediagoblin.init import setup_storage, setup_global_and_app_config
@@ -40,9 +39,6 @@ def import_export_parse_setup(subparser):
subparser.add_argument(
'tar_file')
subparser.add_argument(
- '-cf', '--conf_file', default='mediagoblin.ini',
- help='Config file used to set up environment')
- subparser.add_argument(
'--mongodump_path', default='mongodump',
help='mongodump binary')
subparser.add_argument(
@@ -91,7 +87,7 @@ def _import_database(db, args):
args.mongorestore_path,
'-d', db.name,
os.path.join(args._cache_path['database'], db.name)])
-
+
p.wait()
_log.info('...Database imported')
@@ -212,7 +208,7 @@ def _export_media(db, args):
for entry in db.media_entries.find():
for name, path in entry['media_files'].items():
- _log.info('Exporting {0} - {1}'.format(
+ _log.info(u'Exporting {0} - {1}'.format(
entry['title'],
name))
try:
@@ -231,7 +227,8 @@ def env_export(args):
'''
if args.cache_path:
if os.path.exists(args.cache_path):
- _log.error('The cache directory must not exist before you run this script')
+ _log.error('The cache directory must not exist '
+ 'before you run this script')
_log.error('Cache directory: {0}'.format(args.cache_path))
return False
@@ -247,7 +244,7 @@ def env_export(args):
globa_config, app_config = setup_global_and_app_config(args.conf_file)
setup_storage()
-
+
connection, db = setup_connection_and_db_from_config(
app_config, use_pymongo=True)
diff --git a/mediagoblin/gmg_commands/migrate.py b/mediagoblin/gmg_commands/migrate.py
index 1a597188..beea109d 100644
--- a/mediagoblin/gmg_commands/migrate.py
+++ b/mediagoblin/gmg_commands/migrate.py
@@ -25,9 +25,7 @@ from mediagoblin.db import migrations
def migrate_parser_setup(subparser):
- subparser.add_argument(
- '-cf', '--conf_file', default='mediagoblin.ini',
- help="Config file used to set up environment")
+ pass
def _print_started_migration(migration_number, migration_func):
@@ -55,13 +53,13 @@ def migrate(args):
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)
diff --git a/mediagoblin/gmg_commands/shell.py b/mediagoblin/gmg_commands/shell.py
index 2a380c7b..910560a0 100644
--- a/mediagoblin/gmg_commands/shell.py
+++ b/mediagoblin/gmg_commands/shell.py
@@ -22,9 +22,7 @@ from mediagoblin.gmg_commands import util as commands_util
def shell_parser_setup(subparser):
- subparser.add_argument(
- '-cf', '--conf_file', default='mediagoblin.ini',
- help="Config file used to set up environment")
+ pass
SHELL_BANNER = """\
diff --git a/mediagoblin/gmg_commands/users.py b/mediagoblin/gmg_commands/users.py
index 5421907d..4c4b0c1b 100644
--- a/mediagoblin/gmg_commands/users.py
+++ b/mediagoblin/gmg_commands/users.py
@@ -29,9 +29,6 @@ def adduser_parser_setup(subparser):
subparser.add_argument(
'email',
help="Email to recieve notifications")
- subparser.add_argument(
- '-cf', '--conf_file', default='mediagoblin.ini',
- help="Config file used to set up environment")
def adduser(args):
@@ -41,7 +38,7 @@ def adduser(args):
db = mg_globals.database
users_with_username = \
db.User.find({
- 'username': args.username.lower()
+ 'username': args.username.lower(),
}).count()
if users_with_username:
@@ -64,9 +61,6 @@ def makeadmin_parser_setup(subparser):
subparser.add_argument(
'username',
help="Username to give admin level")
- subparser.add_argument(
- '-cf', '--conf_file', default='mediagoblin.ini',
- help="Config file used to set up environment")
def makeadmin(args):
@@ -74,7 +68,7 @@ def makeadmin(args):
db = mg_globals.database
- user = db.User.one({'username':unicode(args.username.lower())})
+ user = db.User.one({'username': unicode(args.username.lower())})
if user:
user['is_admin'] = True
user.save()
@@ -90,9 +84,6 @@ def changepw_parser_setup(subparser):
subparser.add_argument(
'password',
help="Your NEW supersecret word to login")
- subparser.add_argument(
- '-cf', '--conf_file', default='mediagoblin.ini',
- help="Config file used to set up environment")
def changepw(args):
@@ -100,11 +91,10 @@ def changepw(args):
db = mg_globals.database
- user = db.User.one({'username':unicode(args.username.lower())})
+ user = db.User.one({'username': unicode(args.username.lower())})
if user:
user['pw_hash'] = auth_lib.bcrypt_gen_password_hash(args.password)
user.save()
print 'Password successfully changed'
else:
print 'The user doesn\'t exist'
-
diff --git a/mediagoblin/gmg_commands/wipealldata.py b/mediagoblin/gmg_commands/wipealldata.py
index dc5d6cf7..cddbab38 100644
--- a/mediagoblin/gmg_commands/wipealldata.py
+++ b/mediagoblin/gmg_commands/wipealldata.py
@@ -30,6 +30,10 @@ def wipe(args):
print ""
print "Running this will destroy your mediagoblin database,"
print "remove all your media files in user_dev/, etc."
+ print ""
+ print "ALSO: This command is currently a hack and will only remove"
+ print " things properly on the default setup! If you've customized"
+ print " your mediagoblin configs, it won't work (for now)."
drop_it = raw_input(
'Are you **SURE** you want to destroy your environment? '
@@ -48,4 +52,4 @@ def wipe(args):
print "nixing %s...." % directory
shutil.rmtree(directory)
- print "removed all your stuff! okay, now re-run ./bin/buildout"
+ print "removed all your stuff!"
diff --git a/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.mo
index 146a588f..4e4e8863 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 eb1c5f2d..548e971f 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://bugs.foocorp.net/projects/mediagoblin/issues\n"
-"POT-Creation-Date: 2011-09-11 16:16-0500\n"
-"PO-Revision-Date: 2011-09-11 21:16+0000\n"
+"POT-Creation-Date: 2011-11-01 23:14-0500\n"
+"PO-Revision-Date: 2011-11-02 04:13+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
@@ -45,19 +45,19 @@ msgstr "اكتبها مرة أخرى هنا للتأكد من عدم وجود أ
msgid "Email address"
msgstr "عنوان البريد الإلكتروني"
-#: mediagoblin/auth/views.py:42
+#: mediagoblin/auth/views.py:55
msgid "Sorry, registration is disabled on this instance."
msgstr "عفوًا، التسجيل غير متاح هنا."
-#: mediagoblin/auth/views.py:60
+#: mediagoblin/auth/views.py:73
msgid "Sorry, a user with that name already exists."
msgstr "عذرًا، لقد اختار مستخدم آخر هذا الاسم."
-#: mediagoblin/auth/views.py:64
+#: mediagoblin/auth/views.py:77
msgid "Sorry, that email address has already been taken."
msgstr "عفوًا، هذا العنوان البريدي مستخدم."
-#: mediagoblin/auth/views.py:165
+#: mediagoblin/auth/views.py:179
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
@@ -65,60 +65,64 @@ msgstr ""
"تم التحقق من بريدك الإلكتروني. يمكنك الآن الولوج، وتحرير ملفك الشخصي، ونشر "
"الصور!"
-#: mediagoblin/auth/views.py:171
+#: mediagoblin/auth/views.py:185
msgid "The verification key or user id is incorrect"
msgstr "مفتاح التحقق أو معرف المستخدم خاطئ"
-#: mediagoblin/auth/views.py:192
+#: mediagoblin/auth/views.py:207
msgid "Resent your verification email."
msgstr "أعدنا إرسال رسالة التحقق."
-#: mediagoblin/auth/views.py:228
+#: mediagoblin/auth/views.py:248
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr ""
+"تعذر إرسال رسالة استعادة كلمة السر لأن اسم المستخدم معطل أو لأننا لم نتحقق "
+"من بريدك الإلكتروني."
-#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+#: mediagoblin/edit/forms.py:24 mediagoblin/submit/forms.py:27
msgid "Title"
msgstr "العنوان"
-#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:32
msgid "Tags"
msgstr "الوسوم"
-#: mediagoblin/edit/forms.py:33
+#: mediagoblin/edit/forms.py:31
msgid "Slug"
-msgstr ""
+msgstr "المسار"
-#: mediagoblin/edit/forms.py:34
+#: mediagoblin/edit/forms.py:32
msgid "The slug can't be empty"
-msgstr ""
+msgstr "لا يمكن ترك المسار فارغًا"
-#: mediagoblin/edit/forms.py:35
+#: mediagoblin/edit/forms.py:33
msgid ""
"The title part of this media's URL. You usually don't need to change this."
msgstr ""
+"الجزء الذي يمثل عنوان الملف في المسار. لا حاجة إلى تغيير محتوى هذه الخانة "
+"عادةً."
-#: mediagoblin/edit/forms.py:42
+#: mediagoblin/edit/forms.py:40
msgid "Bio"
msgstr "السيرة"
-#: mediagoblin/edit/forms.py:45
+#: mediagoblin/edit/forms.py:43
msgid "Website"
msgstr "الموقع الإلكتروني"
-#: mediagoblin/edit/views.py:63
+#: mediagoblin/edit/views.py:64
msgid "An entry with that slug already exists for this user."
-msgstr ""
+msgstr "يوجد ملف آخر بهذا المسار لدى هذى المستخدم."
-#: mediagoblin/edit/views.py:84
+#: mediagoblin/edit/views.py:85
msgid "You are editing another user's media. Proceed with caution."
-msgstr ""
+msgstr "أنت تحرّر وسائط مستخدم آخر. كن حذرًا أثناء العملية."
-#: mediagoblin/edit/views.py:154
+#: mediagoblin/edit/views.py:155
msgid "You are editing a user's profile. Proceed with caution."
-msgstr ""
+msgstr "أنت تحرّر ملف مستخدم آخر. كن حذرًا أثناء العملية."
#: mediagoblin/process_media/errors.py:44
msgid "Invalid file given for media type."
@@ -130,23 +134,23 @@ msgstr "الملف"
#: mediagoblin/submit/forms.py:30
msgid "Description of this work"
-msgstr ""
+msgstr "وصف هذا العمل."
-#: mediagoblin/submit/views.py:47
+#: mediagoblin/submit/views.py:46
msgid "You must provide a file."
msgstr "يجب أن تضع ملفًا."
-#: mediagoblin/submit/views.py:50
+#: mediagoblin/submit/views.py:49
msgid "The file doesn't seem to be an image!"
msgstr "لا يبدو أن هذا الملف صورة!"
-#: mediagoblin/submit/views.py:122
+#: mediagoblin/submit/views.py:121
msgid "Woohoo! Submitted!"
msgstr "يا سلام! نُشرَت!"
#: mediagoblin/templates/mediagoblin/404.html:21
msgid "Oops!"
-msgstr ""
+msgstr "ويحي!"
#: mediagoblin/templates/mediagoblin/404.html:24
msgid "There doesn't seem to be a page at this address. Sorry!"
@@ -161,7 +165,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/404.html:32
msgid "Image of 404 goblin stressing out"
-msgstr ""
+msgstr "صورة قزم مرتبك"
#: mediagoblin/templates/mediagoblin/base.html:22
msgid "GNU MediaGoblin"
@@ -180,8 +184,8 @@ msgid "verify your email!"
msgstr "أكّد بريدك"
#: mediagoblin/templates/mediagoblin/base.html:73
-#: mediagoblin/templates/mediagoblin/auth/login.html:26
-#: mediagoblin/templates/mediagoblin/auth/login.html:34
+#: mediagoblin/templates/mediagoblin/auth/login.html:27
+#: mediagoblin/templates/mediagoblin/auth/login.html:35
msgid "Log in"
msgstr "لِج"
@@ -242,38 +246,34 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:39
#, python-format
msgid ""
-"\n"
-" <a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
" or\n"
-" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>\n"
-" "
+" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
msgstr ""
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">أنشئ حسابًا مجانيًا</a>\n"
+" أو\n"
+" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">ركّب ميدياغوبلن على خادومك الخاص</a>"
#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Most recent media"
-msgstr ""
+msgstr "أحدث الوسائط"
-#: mediagoblin/templates/mediagoblin/auth/change_fp.html:27
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:29
msgid "Enter your new password"
-msgstr ""
+msgstr "أدخل كلمة سرك الجديدة"
-#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29
msgid "Enter your username or email"
-msgstr ""
+msgstr "أدخل اسم المستخدم أو بريدك الإلكتروني"
#: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22
-msgid ""
-"\n"
-" Your password has been changed. Try to log in now.\n"
-" "
-msgstr ""
+msgid "Your password has been changed. Try to log in now."
+msgstr "لقد غُيرت كلمة سرك. جرّب الولوج الآن."
#: mediagoblin/templates/mediagoblin/auth/fp_email_sent.html:22
msgid ""
-"\n"
-" Check your inbox. We sent an email with a URL for changing your password.\n"
-" "
-msgstr ""
+"Check your inbox. We sent an email with a URL for changing your password."
+msgstr "تفقد بريدك الإلكتروني. لقد أرسلنا رسالة بها وصلة لتغيير كلمة سرك."
#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19
#, python-format
@@ -288,32 +288,39 @@ msgid ""
"If you think this is an error, just ignore this email and continue being\n"
"a happy goblin!"
msgstr ""
+"مرحبًا يا %(username)s،\n"
+"\n"
+"إن أردت تغيير كلمة سرك في غنو ميدياغوبلن فافتح الوصلة التالية في متصفحك:\n"
+"\n"
+"%(verification_url)s\n"
+"\n"
+"إن كنت ترى أن هذه الرسالة وصلتك خطأً فتجاهلها واستمتع بحياتك!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:29
+#: mediagoblin/templates/mediagoblin/auth/login.html:30
msgid "Logging in failed!"
msgstr "فشل الولوج!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:42
+#: mediagoblin/templates/mediagoblin/auth/login.html:43
msgid "Don't have an account yet?"
msgstr "ألا تملك حسابًا بعد؟"
-#: mediagoblin/templates/mediagoblin/auth/login.html:45
+#: mediagoblin/templates/mediagoblin/auth/login.html:46
msgid "Create one here!"
msgstr "أنشئ حسابًا هنا!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:48
+#: mediagoblin/templates/mediagoblin/auth/login.html:49
msgid "Forgot your password?"
-msgstr ""
+msgstr "أنسيت كلمة سرك؟"
-#: mediagoblin/templates/mediagoblin/auth/login.html:51
+#: mediagoblin/templates/mediagoblin/auth/login.html:52
msgid "Change it!"
-msgstr ""
+msgstr "غيّرها!"
#: mediagoblin/templates/mediagoblin/auth/register.html:27
msgid "Create an account!"
msgstr "أنشئ حسابًا!"
-#: mediagoblin/templates/mediagoblin/auth/register.html:30
+#: mediagoblin/templates/mediagoblin/auth/register.html:31
msgid "Create"
msgstr "أنشئ"
@@ -362,7 +369,7 @@ msgstr "الوسائط الموسومة ب‍"
msgid "Submit yer media"
msgstr "انشر وسائطك"
-#: mediagoblin/templates/mediagoblin/submit/start.html:29
+#: mediagoblin/templates/mediagoblin/submit/start.html:30
msgid "Submit"
msgstr "أرسل"
@@ -379,11 +386,11 @@ msgstr "عذرًا، تعذر العثور على مستخدم بهذا الاس
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
msgid "Really delete %(title)s?"
-msgstr ""
+msgstr "أتود حقًا حذف %(title)s?"
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
msgid "Delete Permanently"
-msgstr ""
+msgstr "احذف نهائيًا"
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:22
msgid "Media processing panel"
@@ -392,19 +399,19 @@ msgstr "لوحة معالجة الوسائط"
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:25
msgid ""
"You can track the state of media being processed for your gallery here."
-msgstr ""
+msgstr "يمكنك متابعة عملية معالجة وسائط معرضك من هنا."
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:28
msgid "Media in-processing"
-msgstr ""
+msgstr "توجد وسائط تحت المعالجة"
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:46
msgid "No media in-processing"
-msgstr ""
+msgstr "لا توجد وسائط تحت المعالجة"
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:50
msgid "These uploads failed to process:"
-msgstr ""
+msgstr "فشلت معالجة هذه الملفات:"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:39
#: mediagoblin/templates/mediagoblin/user_pages/user.html:59
@@ -459,7 +466,7 @@ msgstr "حرِّر الملف الشخصي"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:96
msgid "This user hasn't filled in their profile (yet)."
-msgstr ""
+msgstr "لم يعبئ هذا العضو بيانات ملفه بعد."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:122
#, python-format
@@ -490,11 +497,11 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/utils/pagination.html:40
msgid "Newer"
-msgstr ""
+msgstr "الأحدث"
#: mediagoblin/templates/mediagoblin/utils/pagination.html:46
msgid "Older"
-msgstr ""
+msgstr "الأقدم"
#: mediagoblin/user_pages/forms.py:24
msgid "Comment"
@@ -502,10 +509,18 @@ msgstr "علِّق"
#: mediagoblin/user_pages/forms.py:30
msgid "I am sure I want to delete this"
+msgstr "أنا متأكد من رغبتي بحذف هذا العمل"
+
+#: mediagoblin/user_pages/views.py:142
+msgid "Empty comments are not allowed."
msgstr ""
-#: mediagoblin/user_pages/views.py:175
-msgid "You are about to delete another user's media. Proceed with caution."
+#: mediagoblin/user_pages/views.py:148
+msgid "Comment posted!"
msgstr ""
+#: mediagoblin/user_pages/views.py:181
+msgid "You are about to delete another user's media. Proceed with caution."
+msgstr "أنت على وشك حذف وسائط مستخدم آخر. كن حذرًا أثناء العملية."
+
diff --git a/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.mo
new file mode 100644
index 00000000..9b9e7e3b
--- /dev/null
+++ 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
new file mode 100644
index 00000000..e2cd8342
--- /dev/null
+++ b/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.po
@@ -0,0 +1,520 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+#
+# Translators:
+# <devaleitzer@aim.com>, 2011.
+msgid ""
+msgstr ""
+"Project-Id-Version: GNU MediaGoblin\n"
+"Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n"
+"POT-Creation-Date: 2011-11-01 23:14-0500\n"
+"PO-Revision-Date: 2011-11-02 04:13+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: ca\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+
+#: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:49
+msgid "Username"
+msgstr "Nom d'usuari"
+
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:53
+msgid "Password"
+msgstr "Contrasenya"
+
+#: mediagoblin/auth/forms.py:35
+msgid "Passwords must match."
+msgstr "Les contrasenyes han de coincidir"
+
+#: mediagoblin/auth/forms.py:37
+msgid "Confirm password"
+msgstr "Confirmeu la contrasenya"
+
+#: mediagoblin/auth/forms.py:39
+msgid "Type it again here to make sure there are no spelling mistakes."
+msgstr ""
+
+#: mediagoblin/auth/forms.py:42
+msgid "Email address"
+msgstr "Adreça electrònica"
+
+#: mediagoblin/auth/views.py:55
+msgid "Sorry, registration is disabled on this instance."
+msgstr "Ho sentim, el registre està desactivat en aquest cas."
+
+#: mediagoblin/auth/views.py:73
+msgid "Sorry, a user with that name already exists."
+msgstr "Lamentablement aquest usuari ja existeix."
+
+#: mediagoblin/auth/views.py:77
+msgid "Sorry, that email address has already been taken."
+msgstr "Disculpeu, aquesta adreça electrònica ja s'està utilitzant."
+
+#: mediagoblin/auth/views.py:179
+msgid ""
+"Your email address has been verified. You may now login, edit your profile, "
+"and submit images!"
+msgstr ""
+"Ja s'ha verificat la vostra adreça electrònica. Ara podeu entrar, editar el "
+"vostre perfil i penjar imatge!"
+
+#: mediagoblin/auth/views.py:185
+msgid "The verification key or user id is incorrect"
+msgstr ""
+"La clau de verificació o la identificació de l'usuari no són correctes."
+
+#: mediagoblin/auth/views.py:207
+msgid "Resent your verification email."
+msgstr "Torna'm a enviar el correu de verificació"
+
+#: mediagoblin/auth/views.py:248
+msgid ""
+"Could not send password recovery email as your username is inactive or your "
+"account's email address has not been verified."
+msgstr ""
+
+#: mediagoblin/edit/forms.py:24 mediagoblin/submit/forms.py:27
+msgid "Title"
+msgstr "Títol"
+
+#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:32
+msgid "Tags"
+msgstr "Etiquetes"
+
+#: mediagoblin/edit/forms.py:31
+msgid "Slug"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:32
+msgid "The slug can't be empty"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:33
+msgid ""
+"The title part of this media's URL. You usually don't need to change this."
+msgstr ""
+
+#: mediagoblin/edit/forms.py:40
+msgid "Bio"
+msgstr "Biografia"
+
+#: mediagoblin/edit/forms.py:43
+msgid "Website"
+msgstr "Lloc web"
+
+#: mediagoblin/edit/views.py:64
+msgid "An entry with that slug already exists for this user."
+msgstr ""
+
+#: mediagoblin/edit/views.py:85
+msgid "You are editing another user's media. Proceed with caution."
+msgstr "Esteu editant fitxers d'un altre usuari. Aneu amb compte."
+
+#: mediagoblin/edit/views.py:155
+msgid "You are editing a user's profile. Proceed with caution."
+msgstr "Esteu editant el perfil d'un usuari. Aneu amb compte"
+
+#: mediagoblin/process_media/errors.py:44
+msgid "Invalid file given for media type."
+msgstr "Aquest tipus de fitxer no és vàlid."
+
+#: mediagoblin/submit/forms.py:25
+msgid "File"
+msgstr "Fitxer"
+
+#: mediagoblin/submit/forms.py:30
+msgid "Description of this work"
+msgstr ""
+
+#: mediagoblin/submit/views.py:46
+msgid "You must provide a file."
+msgstr "Heu d'escollir un fitxer."
+
+#: mediagoblin/submit/views.py:49
+msgid "The file doesn't seem to be an image!"
+msgstr "El fitxer no és una imatge"
+
+#: mediagoblin/submit/views.py:121
+msgid "Woohoo! Submitted!"
+msgstr "Visca! S'ha enviat!"
+
+#: mediagoblin/templates/mediagoblin/404.html:21
+msgid "Oops!"
+msgstr "Ups!"
+
+#: mediagoblin/templates/mediagoblin/404.html:24
+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:26
+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/404.html:32
+msgid "Image of 404 goblin stressing out"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/base.html:22
+msgid "GNU MediaGoblin"
+msgstr "GNU MediaGoblin"
+
+#: mediagoblin/templates/mediagoblin/base.html:47
+msgid "MediaGoblin logo"
+msgstr "Logo de mediagoblin"
+
+#: mediagoblin/templates/mediagoblin/base.html:52
+msgid "Submit media"
+msgstr "Envia fitxers"
+
+#: mediagoblin/templates/mediagoblin/base.html:63
+msgid "verify your email!"
+msgstr "verifiqueu el correu electrònic"
+
+#: mediagoblin/templates/mediagoblin/base.html:73
+#: mediagoblin/templates/mediagoblin/auth/login.html:27
+#: mediagoblin/templates/mediagoblin/auth/login.html:35
+msgid "Log in"
+msgstr "Entra"
+
+#: mediagoblin/templates/mediagoblin/base.html:89
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
+"href=\"http://gnu.org/\">GNU</a> project"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:24
+msgid "Explore"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:27
+msgid "Hi there, media lover! MediaGoblin is..."
+msgstr "Ei, fanàtic multimèdia! MediaGoblin és..."
+
+#: mediagoblin/templates/mediagoblin/root.html:29
+msgid "The perfect place for your media!"
+msgstr "El lloc fitxer pels teus fitxers!"
+
+#: mediagoblin/templates/mediagoblin/root.html:30
+msgid ""
+"A place for people to collaborate and show off original and derived "
+"creations!"
+msgstr ""
+"Un lloc en el qual les persones poden col·laborar i mostrar les seves "
+"creacions originals o obres derivades."
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid ""
+"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project, "
+"after all.)"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:32
+msgid ""
+"Aiming to make the world a better place through decentralization and "
+"(eventually, coming soon!) federation!"
+msgstr ""
+"Amb l'objectiu de fer del món un lloc millor a través de la "
+"descentralització i (eventualment, aviat disponible!) La federació!"
+
+#: mediagoblin/templates/mediagoblin/root.html:33
+msgid ""
+"Built for extensibility. (Multiple media types coming soon to the software,"
+" including video support!)"
+msgstr ""
+"Construït per l'ampliació. (Múltiples tipus de fitxers en breu amb el "
+"programari, incloent el suport de vídeo!)"
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid ""
+"Powered by people like you. (<a "
+"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve this"
+" software!</a>)"
+msgstr ""
+"Desenvolupat per persones com vostè. ( <a "
+"href=\"http://mediagoblin.org/pages/join.html\"> Podeu ajudar a millorar "
+"aquest programari!</a> )"
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+msgid "Excited to join us?"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:39
+#, python-format
+msgid ""
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
+" or\n"
+" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:53
+msgid "Most recent media"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:29
+msgid "Enter your new password"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29
+msgid "Enter your username or email"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22
+msgid "Your password has been changed. Try to log in now."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/fp_email_sent.html:22
+msgid ""
+"Check your inbox. We sent an email with a URL for changing your password."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19
+#, python-format
+msgid ""
+"Hi %(username)s,\n"
+"\n"
+"to change your GNU MediaGoblin password, open the following URL in \n"
+"your web browser:\n"
+"\n"
+"%(verification_url)s\n"
+"\n"
+"If you think this is an error, just ignore this email and continue being\n"
+"a happy goblin!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:30
+msgid "Logging in failed!"
+msgstr "Inici de sessió ha fallat!"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:43
+msgid "Don't have an account yet?"
+msgstr "Encara no teniu un compte?"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:46
+msgid "Create one here!"
+msgstr "Creeu-ne un aquí!"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:49
+msgid "Forgot your password?"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:52
+msgid "Change it!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:27
+msgid "Create an account!"
+msgstr "Creeu un compte!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:31
+msgid "Create"
+msgstr "Crea"
+
+#: 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 ""
+"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"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:29
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "Edició %(media_title)s "
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:36
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+msgid "Cancel"
+msgstr "Cancel·la"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:37
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
+msgid "Save changes"
+msgstr "Desa els canvis"
+
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:29
+#, python-format
+msgid "Editing %(username)s's profile"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/listings/tag.html:31
+msgid "Media tagged with:"
+msgstr "Etiquetat amb:"
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:26
+msgid "Submit yer media"
+msgstr "Envieu els vostres fitxers"
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:30
+msgid "Submit"
+msgstr "Envia"
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media"
+msgstr "<a href=\"%(user_url)s\">%(username)s</a>'s media"
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:32
+msgid "Sorry, no such user found."
+msgstr "Lamentablement no s'ha trobat l'usuari que cercàveu."
+
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
+#, python-format
+msgid "Really delete %(title)s?"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+msgid "Delete Permanently"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:22
+msgid "Media processing panel"
+msgstr "Quadre de processament de fitxers"
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:25
+msgid ""
+"You can track the state of media being processed for your gallery here."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:28
+msgid "Media in-processing"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:46
+msgid "No media in-processing"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:50
+msgid "These uploads failed to process:"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:39
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:59
+msgid "Email verification needed"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:42
+msgid "Almost done! Your account still needs to be activated."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:47
+msgid ""
+"An email should arrive in a few moments with instructions on how to do so."
+msgstr "Us hauria d'arribar un correu amb les instruccions per a fer-ho."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:51
+msgid "In case it doesn't:"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:54
+msgid "Resend verification email"
+msgstr "Torna'm a enviar el correu de verificació"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:62
+msgid ""
+"Someone has registered an account with this username, but it still has to be"
+" activated."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:68
+#, 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 ""
+"Si siu aqeust usuari però heu perdut el correu de verificació, podeu <a "
+"href=\"%(login_url)s\">entrar</a> i tornar-lo a enviar."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:78
+#, python-format
+msgid "%(username)s's profile"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:85
+msgid "Here's a spot to tell others about yourself."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:90
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:108
+msgid "Edit profile"
+msgstr "Edita el perfil"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:96
+msgid "This user hasn't filled in their profile (yet)."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:122
+#, 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:135
+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:141
+msgid "Add media"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:147
+msgid "There doesn't seem to be any media here yet..."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
+msgid "feed icon"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/utils/feed_link.html:23
+msgid "Atom feed"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/utils/pagination.html:40
+msgid "Newer"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/utils/pagination.html:46
+msgid "Older"
+msgstr ""
+
+#: mediagoblin/user_pages/forms.py:24
+msgid "Comment"
+msgstr "Comentari"
+
+#: mediagoblin/user_pages/forms.py:30
+msgid "I am sure I want to delete this"
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:142
+msgid "Empty comments are not allowed."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:148
+msgid "Comment posted!"
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:181
+msgid "You are about to delete another user's media. Proceed with caution."
+msgstr ""
+
+
diff --git a/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.mo
index bb7538c2..056e3eca 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 3aaabce0..5c4ef0d0 100644
--- a/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.po
@@ -7,6 +7,7 @@
# <cwebber@dustycloud.org>, 2011.
# Elrond <elrond+mediagoblin.org@samba-tng.org>, 2011.
# Jan-Christoph Borchardt <JanCBorchardt@fsfe.org>, 2011.
+# <kyoo@kyoo.ch>, 2011.
# <mediagoblin.org@samba-tng.org>, 2011.
# Rafael Maguiña <rafael.maguina@gmail.com>, 2011.
# Vinzenz Vietzke <vinz@fedoraproject.org>, 2011.
@@ -14,9 +15,9 @@ msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n"
-"POT-Creation-Date: 2011-09-11 16:16-0500\n"
-"PO-Revision-Date: 2011-09-11 21:16+0000\n"
-"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
+"POT-Creation-Date: 2011-11-01 23:14-0500\n"
+"PO-Revision-Date: 2011-11-02 15:18+0000\n"
+"Last-Translator: piratenpanda <benjamin@lebsanft.org>\n"
"Language-Team: German (http://www.transifex.net/projects/p/mediagoblin/team/de/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -49,19 +50,19 @@ msgstr "Hier nochmal eintragen, um Tippfehler zu verhindern."
msgid "Email address"
msgstr "Email-Adresse"
-#: mediagoblin/auth/views.py:42
+#: mediagoblin/auth/views.py:55
msgid "Sorry, registration is disabled on this instance."
msgstr "Registrierung ist auf dieser Instanz leider deaktiviert."
-#: mediagoblin/auth/views.py:60
+#: mediagoblin/auth/views.py:73
msgid "Sorry, a user with that name already exists."
msgstr "Leider gibt es bereits einen Benutzer mit diesem Namen."
-#: mediagoblin/auth/views.py:64
+#: mediagoblin/auth/views.py:77
msgid "Sorry, that email address has already been taken."
msgstr "Tut und Leid, aber diese Email-Adresse wird bereits verwendet."
-#: mediagoblin/auth/views.py:165
+#: mediagoblin/auth/views.py:179
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
@@ -69,60 +70,62 @@ msgstr ""
"Deine Email-Adresse wurde bestätigt. Du kannst dich nun anmelden, Dein "
"Profil bearbeiten und Bilder hochladen!"
-#: mediagoblin/auth/views.py:171
+#: mediagoblin/auth/views.py:185
msgid "The verification key or user id is incorrect"
msgstr "Der Bestätigungssschlüssel oder die Nutzernummer ist falsch."
-#: mediagoblin/auth/views.py:192
+#: mediagoblin/auth/views.py:207
msgid "Resent your verification email."
msgstr "Bestätigungs-Email wurde erneut versandt."
-#: mediagoblin/auth/views.py:228
+#: mediagoblin/auth/views.py:248
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr ""
+"Konnte Email zur Wiederherstellung des Passworts nicht senden, weil dein "
+"Benutzername inaktiv oder deine Email-Adresse noch nicht verifiziert ist."
-#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+#: mediagoblin/edit/forms.py:24 mediagoblin/submit/forms.py:27
msgid "Title"
msgstr "Titel"
-#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:32
msgid "Tags"
msgstr "Markierungen"
-#: mediagoblin/edit/forms.py:33
+#: mediagoblin/edit/forms.py:31
msgid "Slug"
msgstr "Kurztitel"
-#: mediagoblin/edit/forms.py:34
+#: mediagoblin/edit/forms.py:32
msgid "The slug can't be empty"
msgstr "Bitte gib einen Kurztitel ein"
-#: mediagoblin/edit/forms.py:35
+#: mediagoblin/edit/forms.py:33
msgid ""
"The title part of this media's URL. You usually don't need to change this."
msgstr ""
"Der Titelteil der Medienadresse. Normalerweise muss hier nichts geändert "
"werden."
-#: mediagoblin/edit/forms.py:42
+#: mediagoblin/edit/forms.py:40
msgid "Bio"
msgstr "Biographie"
-#: mediagoblin/edit/forms.py:45
+#: mediagoblin/edit/forms.py:43
msgid "Website"
msgstr "Webseite"
-#: mediagoblin/edit/views.py:63
+#: mediagoblin/edit/views.py:64
msgid "An entry with that slug already exists for this user."
msgstr "Diesen Kurztitel hast du bereits vergeben."
-#: mediagoblin/edit/views.py:84
+#: mediagoblin/edit/views.py:85
msgid "You are editing another user's media. Proceed with caution."
msgstr "Du bearbeitest die Medien eines Anderen. Bitte sei vorsichtig."
-#: mediagoblin/edit/views.py:154
+#: mediagoblin/edit/views.py:155
msgid "You are editing a user's profile. Proceed with caution."
msgstr "Du bearbeitest das Profil eines Anderen. Bitte sei vorsichtig."
@@ -138,15 +141,15 @@ msgstr "Datei"
msgid "Description of this work"
msgstr "Beschreibung des Werkes"
-#: mediagoblin/submit/views.py:47
+#: mediagoblin/submit/views.py:46
msgid "You must provide a file."
msgstr "Du musst eine Datei angeben."
-#: mediagoblin/submit/views.py:50
+#: mediagoblin/submit/views.py:49
msgid "The file doesn't seem to be an image!"
msgstr "Diese Datei scheint kein Bild zu sein!"
-#: mediagoblin/submit/views.py:122
+#: mediagoblin/submit/views.py:121
msgid "Woohoo! Submitted!"
msgstr "Yeeeaaah! Geschafft!"
@@ -187,8 +190,8 @@ msgid "verify your email!"
msgstr "Bitte bestätige deine Email-Adresse!"
#: mediagoblin/templates/mediagoblin/base.html:73
-#: mediagoblin/templates/mediagoblin/auth/login.html:26
-#: mediagoblin/templates/mediagoblin/auth/login.html:34
+#: mediagoblin/templates/mediagoblin/auth/login.html:27
+#: mediagoblin/templates/mediagoblin/auth/login.html:35
msgid "Log in"
msgstr "Anmelden"
@@ -202,7 +205,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:24
msgid "Explore"
-msgstr ""
+msgstr "Entdecke"
#: mediagoblin/templates/mediagoblin/root.html:27
msgid "Hi there, media lover! MediaGoblin is..."
@@ -256,43 +259,41 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:38
msgid "Excited to join us?"
-msgstr ""
+msgstr "Neugierig dich uns anzuschließen?"
#: mediagoblin/templates/mediagoblin/root.html:39
#, python-format
msgid ""
-"\n"
-" <a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
" or\n"
-" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>\n"
-" "
+" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
msgstr ""
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Gratis ein Konto einrichten</a>\n"
+" or\n"
+" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">MediaGoblin auf deinem eigenen Server einrichten</a>"
#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Most recent media"
-msgstr ""
+msgstr "Neuste Medien"
-#: mediagoblin/templates/mediagoblin/auth/change_fp.html:27
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:29
msgid "Enter your new password"
-msgstr ""
+msgstr "Neues Passwort eingeben"
-#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29
msgid "Enter your username or email"
-msgstr ""
+msgstr "Benutzername oder Email-Adresse eingeben"
#: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22
-msgid ""
-"\n"
-" Your password has been changed. Try to log in now.\n"
-" "
-msgstr ""
+msgid "Your password has been changed. Try to log in now."
+msgstr "Dein Passwort wurde geändert. Versuche dich jetzt einzuloggen."
#: mediagoblin/templates/mediagoblin/auth/fp_email_sent.html:22
msgid ""
-"\n"
-" Check your inbox. We sent an email with a URL for changing your password.\n"
-" "
+"Check your inbox. We sent an email with a URL for changing your password."
msgstr ""
+"Prüfe deinen Posteingang. Wir haben dir eine Email mit einem Link geschickt,"
+" mit dem du dein Passwort ändern kannst."
#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19
#, python-format
@@ -307,32 +308,39 @@ msgid ""
"If you think this is an error, just ignore this email and continue being\n"
"a happy goblin!"
msgstr ""
+"Hi %(username)s,\n"
+"\n"
+"um dein GNU MediaGoblin Passwort zu ändern, öffne folgende URL in deinem Webbrowser:\n"
+"\n"
+"%(verification_url)s\n"
+"\n"
+"Wenn du denkst, dass das ein Fehler ist, ignoriere einfach diese Email und bleib ein glücklicher Goblin!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:29
+#: mediagoblin/templates/mediagoblin/auth/login.html:30
msgid "Logging in failed!"
msgstr "Anmeldevorgang fehlgeschlagen!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:42
+#: mediagoblin/templates/mediagoblin/auth/login.html:43
msgid "Don't have an account yet?"
msgstr "Hast du noch kein Konto?"
-#: mediagoblin/templates/mediagoblin/auth/login.html:45
+#: mediagoblin/templates/mediagoblin/auth/login.html:46
msgid "Create one here!"
-msgstr "Registriere dich!"
+msgstr "Registriere dich hier!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:48
+#: mediagoblin/templates/mediagoblin/auth/login.html:49
msgid "Forgot your password?"
-msgstr ""
+msgstr "Passwort vergessen?"
-#: mediagoblin/templates/mediagoblin/auth/login.html:51
+#: mediagoblin/templates/mediagoblin/auth/login.html:52
msgid "Change it!"
-msgstr ""
+msgstr "Wechsle es!"
#: mediagoblin/templates/mediagoblin/auth/register.html:27
msgid "Create an account!"
msgstr "Neues Konto registrieren!"
-#: mediagoblin/templates/mediagoblin/auth/register.html:30
+#: mediagoblin/templates/mediagoblin/auth/register.html:31
msgid "Create"
msgstr "Registrieren"
@@ -370,7 +378,7 @@ msgstr "Änderungen speichern"
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:29
#, python-format
msgid "Editing %(username)s's profile"
-msgstr "%(username)ss Profil barbeiten"
+msgstr "%(username)ss Profil bearbeiten"
#: mediagoblin/templates/mediagoblin/listings/tag.html:31
msgid "Media tagged with:"
@@ -380,7 +388,7 @@ msgstr "Medien markiert mit:"
msgid "Submit yer media"
msgstr "Medien hochladen"
-#: mediagoblin/templates/mediagoblin/submit/start.html:29
+#: mediagoblin/templates/mediagoblin/submit/start.html:30
msgid "Submit"
msgstr "Bestätigen"
@@ -424,7 +432,7 @@ msgstr "Keine Medien in Bearbeitung"
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:50
msgid "These uploads failed to process:"
-msgstr "Die folgenden Uploads sind fehlgeschlagen"
+msgstr "Die folgenden Uploads sind fehlgeschlagen:"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:39
#: mediagoblin/templates/mediagoblin/user_pages/user.html:59
@@ -529,7 +537,15 @@ msgstr "Kommentar"
msgid "I am sure I want to delete this"
msgstr "Ja, wirklich löschen"
-#: mediagoblin/user_pages/views.py:175
+#: mediagoblin/user_pages/views.py:142
+msgid "Empty comments are not allowed."
+msgstr "Leere Kommentare sind nicht erlaubt."
+
+#: mediagoblin/user_pages/views.py:148
+msgid "Comment posted!"
+msgstr "Kommentar hinzugefügt!"
+
+#: mediagoblin/user_pages/views.py:181
msgid "You are about to delete another user's media. Proceed with caution."
msgstr "Du versuchst Medien eines anderen Nutzers zu löschen. Sei vorsichtig."
diff --git a/mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po
index 6ff8e8df..f3e0c100 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: 2011-09-11 16:16-0500\n"
+"POT-Creation-Date: 2011-11-01 23:14-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -41,75 +41,83 @@ msgstr ""
msgid "Email address"
msgstr ""
-#: mediagoblin/auth/views.py:42
+#: mediagoblin/auth/views.py:55
msgid "Sorry, registration is disabled on this instance."
msgstr ""
-#: mediagoblin/auth/views.py:60
+#: mediagoblin/auth/views.py:73
msgid "Sorry, a user with that name already exists."
msgstr ""
-#: mediagoblin/auth/views.py:64
+#: mediagoblin/auth/views.py:77
msgid "Sorry, that email address has already been taken."
msgstr ""
-#: mediagoblin/auth/views.py:165
+#: mediagoblin/auth/views.py:179
msgid ""
"Your email address has been verified. You may now login, edit your "
"profile, and submit images!"
msgstr ""
-#: mediagoblin/auth/views.py:171
+#: mediagoblin/auth/views.py:185
msgid "The verification key or user id is incorrect"
msgstr ""
-#: mediagoblin/auth/views.py:192
+#: mediagoblin/auth/views.py:203
+msgid "You must be logged in so we know who to send the email to!"
+msgstr ""
+
+#: mediagoblin/auth/views.py:211
+msgid "You've already verified your email address!"
+msgstr ""
+
+#: mediagoblin/auth/views.py:224
msgid "Resent your verification email."
msgstr ""
-#: mediagoblin/auth/views.py:228
+#: mediagoblin/auth/views.py:265
msgid ""
"Could not send password recovery email as your username is inactive or "
"your account's email address has not been verified."
msgstr ""
-#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+#: mediagoblin/edit/forms.py:24 mediagoblin/submit/forms.py:27
msgid "Title"
msgstr ""
-#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:32
msgid "Tags"
msgstr ""
-#: mediagoblin/edit/forms.py:33
+#: mediagoblin/edit/forms.py:31
msgid "Slug"
msgstr ""
-#: mediagoblin/edit/forms.py:34
+#: mediagoblin/edit/forms.py:32
msgid "The slug can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:35
+#: mediagoblin/edit/forms.py:33
msgid "The title part of this media's URL. You usually don't need to change this."
msgstr ""
-#: mediagoblin/edit/forms.py:42
+#: mediagoblin/edit/forms.py:40
msgid "Bio"
msgstr ""
-#: mediagoblin/edit/forms.py:45
+#: mediagoblin/edit/forms.py:43
msgid "Website"
msgstr ""
-#: mediagoblin/edit/views.py:63
+#: mediagoblin/edit/views.py:64
msgid "An entry with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:84
+#: mediagoblin/edit/views.py:85
msgid "You are editing another user's media. Proceed with caution."
msgstr ""
-#: mediagoblin/edit/views.py:154
+#: mediagoblin/edit/views.py:155
msgid "You are editing a user's profile. Proceed with caution."
msgstr ""
@@ -125,15 +133,15 @@ msgstr ""
msgid "Description of this work"
msgstr ""
-#: mediagoblin/submit/views.py:47
+#: mediagoblin/submit/views.py:46
msgid "You must provide a file."
msgstr ""
-#: mediagoblin/submit/views.py:50
+#: mediagoblin/submit/views.py:49
msgid "The file doesn't seem to be an image!"
msgstr ""
-#: mediagoblin/submit/views.py:122
+#: mediagoblin/submit/views.py:121
msgid "Woohoo! Submitted!"
msgstr ""
@@ -172,8 +180,8 @@ msgid "verify your email!"
msgstr ""
#: mediagoblin/templates/mediagoblin/base.html:73
-#: mediagoblin/templates/mediagoblin/auth/login.html:26
-#: mediagoblin/templates/mediagoblin/auth/login.html:34
+#: mediagoblin/templates/mediagoblin/auth/login.html:27
+#: mediagoblin/templates/mediagoblin/auth/login.html:35
msgid "Log in"
msgstr ""
@@ -233,41 +241,32 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:39
#, python-format
msgid ""
-"\n"
-" <a class=\"header_submit_highlight\" "
-"href=\"%(register_url)s\">Create a free account</a>\n"
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a "
+"free account</a>\n"
" or\n"
" <a class=\"header_submit\" "
"href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on "
-"your own server</a>\n"
-" "
+"your own server</a>"
msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Most recent media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/change_fp.html:27
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:29
msgid "Enter your new password"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29
msgid "Enter your username or email"
msgstr ""
#: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22
-msgid ""
-"\n"
-" Your password has been changed. Try to log in now.\n"
-" "
+msgid "Your password has been changed. Try to log in now."
msgstr ""
#: mediagoblin/templates/mediagoblin/auth/fp_email_sent.html:22
-msgid ""
-"\n"
-" Check your inbox. We sent an email with a URL for changing your "
-"password.\n"
-" "
+msgid "Check your inbox. We sent an email with a URL for changing your password."
msgstr ""
#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19
@@ -284,23 +283,23 @@ msgid ""
"a happy goblin!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/login.html:29
+#: mediagoblin/templates/mediagoblin/auth/login.html:30
msgid "Logging in failed!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/login.html:42
+#: mediagoblin/templates/mediagoblin/auth/login.html:43
msgid "Don't have an account yet?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/login.html:45
+#: mediagoblin/templates/mediagoblin/auth/login.html:46
msgid "Create one here!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/login.html:48
+#: mediagoblin/templates/mediagoblin/auth/login.html:49
msgid "Forgot your password?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/login.html:51
+#: mediagoblin/templates/mediagoblin/auth/login.html:52
msgid "Change it!"
msgstr ""
@@ -308,7 +307,7 @@ msgstr ""
msgid "Create an account!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/register.html:30
+#: mediagoblin/templates/mediagoblin/auth/register.html:31
msgid "Create"
msgstr ""
@@ -351,7 +350,7 @@ msgstr ""
msgid "Submit yer media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/submit/start.html:29
+#: mediagoblin/templates/mediagoblin/submit/start.html:30
msgid "Submit"
msgstr ""
@@ -489,7 +488,15 @@ msgstr ""
msgid "I am sure I want to delete this"
msgstr ""
-#: mediagoblin/user_pages/views.py:175
+#: mediagoblin/user_pages/views.py:142
+msgid "Empty comments are not allowed."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:148
+msgid "Comment posted!"
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:181
msgid "You are about to delete another user's media. Proceed with caution."
msgstr ""
diff --git a/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.mo
index b260cb16..c537c65e 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 296f1b4b..f6bb1cce 100644
--- a/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.po
@@ -10,8 +10,8 @@ msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n"
-"POT-Creation-Date: 2011-09-11 16:16-0500\n"
-"PO-Revision-Date: 2011-09-11 21:16+0000\n"
+"POT-Creation-Date: 2011-11-01 23:14-0500\n"
+"PO-Revision-Date: 2011-11-02 04:13+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
@@ -45,19 +45,19 @@ msgstr "Retajpu ĝin por certigi, ke ne okazis mistajpoj."
msgid "Email address"
msgstr "Retpoŝtadreso"
-#: mediagoblin/auth/views.py:42
+#: mediagoblin/auth/views.py:55
msgid "Sorry, registration is disabled on this instance."
msgstr "Bedaŭrinde, registrado estas malaktivigita en tiu ĉi instalaĵo."
-#: mediagoblin/auth/views.py:60
+#: mediagoblin/auth/views.py:73
msgid "Sorry, a user with that name already exists."
msgstr "Bedaŭrinde, uzanto kun tiu nomo jam ekzistas."
-#: mediagoblin/auth/views.py:64
+#: mediagoblin/auth/views.py:77
msgid "Sorry, that email address has already been taken."
msgstr "Tiu retpoŝtadreso jam estas uzata."
-#: mediagoblin/auth/views.py:165
+#: mediagoblin/auth/views.py:179
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
@@ -65,60 +65,62 @@ msgstr ""
"Via retpoŝtadreso estas konfirmita. Vi povas nun ensaluti, redakti vian "
"profilon, kaj alŝuti bildojn!"
-#: mediagoblin/auth/views.py:171
+#: mediagoblin/auth/views.py:185
msgid "The verification key or user id is incorrect"
msgstr "La kontrol-kodo aŭ la uzantonomo ne estas korekta"
-#: mediagoblin/auth/views.py:192
+#: mediagoblin/auth/views.py:207
msgid "Resent your verification email."
msgstr "Resendi vian kontrol-mesaĝon."
-#: mediagoblin/auth/views.py:228
+#: mediagoblin/auth/views.py:248
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr ""
+"Ni ne povas sendi pasvortsavan retleteron, ĉar aŭ via konto estas neaktiva, "
+"aŭ ĝia retpoŝtadreso ne estis konfirmita."
-#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+#: mediagoblin/edit/forms.py:24 mediagoblin/submit/forms.py:27
msgid "Title"
msgstr "Titolo"
-#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:32
msgid "Tags"
msgstr "Etikedoj"
-#: mediagoblin/edit/forms.py:33
+#: mediagoblin/edit/forms.py:31
msgid "Slug"
msgstr "La distingiga adresparto"
-#: mediagoblin/edit/forms.py:34
+#: mediagoblin/edit/forms.py:32
msgid "The slug can't be empty"
msgstr "La distingiga adresparto ne povas esti malplena"
-#: mediagoblin/edit/forms.py:35
+#: mediagoblin/edit/forms.py:33
msgid ""
"The title part of this media's URL. You usually don't need to change this."
msgstr ""
"La parto de la dosieradreso, bazita sur la dosiertitolo. Ordinare ne necesas"
" ĝin ŝanĝi."
-#: mediagoblin/edit/forms.py:42
+#: mediagoblin/edit/forms.py:40
msgid "Bio"
msgstr "Bio"
-#: mediagoblin/edit/forms.py:45
+#: mediagoblin/edit/forms.py:43
msgid "Website"
msgstr "Retejo"
-#: mediagoblin/edit/views.py:63
+#: mediagoblin/edit/views.py:64
msgid "An entry with that slug already exists for this user."
msgstr "Ĉi tiu uzanto jam havas dosieron kun tiu distingiga adresparto."
-#: mediagoblin/edit/views.py:84
+#: mediagoblin/edit/views.py:85
msgid "You are editing another user's media. Proceed with caution."
msgstr "Vi priredaktas dosieron de alia uzanto. Agu singardeme."
-#: mediagoblin/edit/views.py:154
+#: mediagoblin/edit/views.py:155
msgid "You are editing a user's profile. Proceed with caution."
msgstr "Vi redaktas profilon de alia uzanto. Agu singardeme."
@@ -134,15 +136,15 @@ msgstr "Dosiero"
msgid "Description of this work"
msgstr "Priskribo de ĉi tiu verko"
-#: mediagoblin/submit/views.py:47
+#: mediagoblin/submit/views.py:46
msgid "You must provide a file."
msgstr "Vi devas provizi dosieron."
-#: mediagoblin/submit/views.py:50
+#: mediagoblin/submit/views.py:49
msgid "The file doesn't seem to be an image!"
msgstr "La dosiero ŝajnas ne esti bildo!"
-#: mediagoblin/submit/views.py:122
+#: mediagoblin/submit/views.py:121
msgid "Woohoo! Submitted!"
msgstr "Hura! Alŝutitas!"
@@ -183,8 +185,8 @@ msgid "verify your email!"
msgstr "konfirmu vian retpoŝtadreson! "
#: mediagoblin/templates/mediagoblin/base.html:73
-#: mediagoblin/templates/mediagoblin/auth/login.html:26
-#: mediagoblin/templates/mediagoblin/auth/login.html:34
+#: mediagoblin/templates/mediagoblin/auth/login.html:27
+#: mediagoblin/templates/mediagoblin/auth/login.html:35
msgid "Log in"
msgstr "Ensaluti"
@@ -193,8 +195,8 @@ msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project"
msgstr ""
-"Funkcias per &lt;a href=\"http://mediagoblin.org\"&gt;MediaGoblin&lt;/a&gt;,"
-" unu el la &lt;a href=\"http://gnu.org/\"&gt;projektoj de GNU&lt;/a&gt;"
+"Funkcias per <a href=\"http://mediagoblin.org\">MediaGoblin</a>, unu el la "
+"<a href=\"http://gnu.org/\">projektoj de GNU</a>"
#: mediagoblin/templates/mediagoblin/root.html:24
msgid "Explore"
@@ -244,49 +246,47 @@ msgid ""
"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve this"
" software!</a>)"
msgstr ""
-"Vivanta per homoj kiel vi. (&lt;a "
-"href=\"http://mediagoblin.org/pages/join.html\"&gt;Vi povas helpi al ni "
-"plibonigi la programon!&lt;/a&gt;)"
+"Vivanta per homoj kiel vi. (<a "
+"href=\"http://mediagoblin.org/pages/join.html\">Vi povas helpi al ni "
+"plibonigi la programon!</a>)"
#: mediagoblin/templates/mediagoblin/root.html:38
msgid "Excited to join us?"
-msgstr ""
+msgstr "Ĉu vi deziregas aliĝi nin?"
#: mediagoblin/templates/mediagoblin/root.html:39
#, python-format
msgid ""
-"\n"
-" <a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
" or\n"
-" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>\n"
-" "
+" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
msgstr ""
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Kreu senpagan"
+" konton</a>⏎ aŭ⏎ <a class=\"header_submit\" "
+"href=\"http://wiki.mediagoblin.org/HackingHowto\">Kreu senpagan konton</a>"
#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Most recent media"
-msgstr ""
+msgstr "Plej nove aldonitaj dosieroj"
-#: mediagoblin/templates/mediagoblin/auth/change_fp.html:27
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:29
msgid "Enter your new password"
-msgstr ""
+msgstr "Enigu vian novan pasvorton"
-#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29
msgid "Enter your username or email"
-msgstr ""
+msgstr "Enigu vian salutnomon aŭ retpoŝtadreson"
#: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22
-msgid ""
-"\n"
-" Your password has been changed. Try to log in now.\n"
-" "
-msgstr ""
+msgid "Your password has been changed. Try to log in now."
+msgstr "Via pasvorto estis ŝanĝita. Nun provu ensaluti."
#: mediagoblin/templates/mediagoblin/auth/fp_email_sent.html:22
msgid ""
-"\n"
-" Check your inbox. We sent an email with a URL for changing your password.\n"
-" "
+"Check your inbox. We sent an email with a URL for changing your password."
msgstr ""
+"Kontrolu vian retleterujon. Ni sendis retleteron kun retadreso por ŝanĝo de "
+"via pasvorto."
#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19
#, python-format
@@ -301,32 +301,39 @@ msgid ""
"If you think this is an error, just ignore this email and continue being\n"
"a happy goblin!"
msgstr ""
+"Saluton, %(username)s,\n"
+"\n"
+"por ŝanĝi vian pasvorton ĉe GNUa MediaGoblin, sekvu la jenan retadreson per via TTT-legilo:\n"
+"\n"
+"%(verification_url)s\n"
+"\n"
+"Se vi pensas, ke ĉi tiu retletero estas sendita erare, simple ignoru ĝin kaj plu restu feliĉa koboldo!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:29
+#: mediagoblin/templates/mediagoblin/auth/login.html:30
msgid "Logging in failed!"
msgstr "Ensaluto malsukcesis!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:42
+#: mediagoblin/templates/mediagoblin/auth/login.html:43
msgid "Don't have an account yet?"
msgstr "Ĉu ankoraŭ sen konto?"
-#: mediagoblin/templates/mediagoblin/auth/login.html:45
+#: mediagoblin/templates/mediagoblin/auth/login.html:46
msgid "Create one here!"
msgstr "Kreu ĝin ĉi tie!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:48
+#: mediagoblin/templates/mediagoblin/auth/login.html:49
msgid "Forgot your password?"
-msgstr ""
+msgstr "Ĉu vi forgesis vian pasvorton?"
-#: mediagoblin/templates/mediagoblin/auth/login.html:51
+#: mediagoblin/templates/mediagoblin/auth/login.html:52
msgid "Change it!"
-msgstr ""
+msgstr "Ŝanĝu ĝin!"
#: mediagoblin/templates/mediagoblin/auth/register.html:27
msgid "Create an account!"
msgstr "Kreu konton!"
-#: mediagoblin/templates/mediagoblin/auth/register.html:30
+#: mediagoblin/templates/mediagoblin/auth/register.html:31
msgid "Create"
msgstr "Krei"
@@ -374,7 +381,7 @@ msgstr "Dosieroj markitaj per:"
msgid "Submit yer media"
msgstr "Alŝutu vian aŭd-vid-dosieron"
-#: mediagoblin/templates/mediagoblin/submit/start.html:29
+#: mediagoblin/templates/mediagoblin/submit/start.html:30
msgid "Submit"
msgstr "Alŝuti"
@@ -522,7 +529,15 @@ msgstr "Komento"
msgid "I am sure I want to delete this"
msgstr "Mi estas certa, ke mi volas forigi ĉi tion"
-#: mediagoblin/user_pages/views.py:175
+#: mediagoblin/user_pages/views.py:142
+msgid "Empty comments are not allowed."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:148
+msgid "Comment posted!"
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:181
msgid "You are about to delete another user's media. Proceed with caution."
msgstr "Vi estas forigonta dosieron de alia uzanto. Estu singardema."
diff --git a/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.mo
index 7c7dea0d..2d2b9243 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 85da5dbe..a3c9939b 100644
--- a/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.po
@@ -3,17 +3,19 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
+# <deletesoftware@yandex.ru>, 2011.
# <ekenbrand@hotmail.com>, 2011.
# <jacobo@gnu.org>, 2011.
# Javier Di Mauro <javierdimauro@gmail.com>, 2011.
# <juangsub@gmail.com>, 2011.
+# <juanma@kde.org.ar>, 2011.
# Mario Rodriguez <msrodriguez00@gmail.com>, 2011.
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n"
-"POT-Creation-Date: 2011-09-11 16:16-0500\n"
-"PO-Revision-Date: 2011-09-11 21:16+0000\n"
+"POT-Creation-Date: 2011-11-01 23:14-0500\n"
+"PO-Revision-Date: 2011-11-02 04:13+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: Spanish (Castilian) (http://www.transifex.net/projects/p/mediagoblin/team/es/)\n"
"MIME-Version: 1.0\n"
@@ -25,7 +27,7 @@ msgstr ""
#: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:49
msgid "Username"
-msgstr "Nombre de Usuario"
+msgstr "Nombre de usuario"
#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:53
msgid "Password"
@@ -48,19 +50,19 @@ msgstr ""
msgid "Email address"
msgstr "Dirección de correo electrónico"
-#: mediagoblin/auth/views.py:42
+#: mediagoblin/auth/views.py:55
msgid "Sorry, registration is disabled on this instance."
-msgstr "Lo sentimos, la registración está deshabilitado en este momento."
+msgstr "Lo sentimos, el registro está deshabilitado en este momento."
-#: mediagoblin/auth/views.py:60
+#: mediagoblin/auth/views.py:73
msgid "Sorry, a user with that name already exists."
msgstr "Lo sentimos, ya existe un usuario con ese nombre."
-#: mediagoblin/auth/views.py:64
+#: mediagoblin/auth/views.py:77
msgid "Sorry, that email address has already been taken."
msgstr "Lo sentimos, esa dirección de correo electrónico ya ha sido tomada."
-#: mediagoblin/auth/views.py:165
+#: mediagoblin/auth/views.py:179
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
@@ -68,61 +70,64 @@ msgstr ""
"Tu dirección de correo electrónico ha sido verificada. ¡Ahora puedes "
"ingresar, editar tu perfil, y enviar imágenes!"
-#: mediagoblin/auth/views.py:171
+#: mediagoblin/auth/views.py:185
msgid "The verification key or user id is incorrect"
msgstr ""
"La clave de verificación o la identificación de usuario son incorrectas"
-#: mediagoblin/auth/views.py:192
+#: mediagoblin/auth/views.py:207
msgid "Resent your verification email."
msgstr "Se reenvió tu correo electrónico de verificación."
-#: mediagoblin/auth/views.py:228
+#: mediagoblin/auth/views.py:248
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr ""
+"No se pudo enviar un correo electrónico de recuperación de contraseñas "
+"porque su nombre de usuario está inactivo o la dirección de su cuenta de "
+"correo electrónico no ha sido verificada."
-#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+#: mediagoblin/edit/forms.py:24 mediagoblin/submit/forms.py:27
msgid "Title"
msgstr "Título"
-#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:32
msgid "Tags"
msgstr "Etiquetas"
-#: mediagoblin/edit/forms.py:33
+#: mediagoblin/edit/forms.py:31
msgid "Slug"
msgstr "Ficha"
-#: mediagoblin/edit/forms.py:34
+#: mediagoblin/edit/forms.py:32
msgid "The slug can't be empty"
msgstr "La ficha no puede estar vacía"
-#: mediagoblin/edit/forms.py:35
+#: mediagoblin/edit/forms.py:33
msgid ""
"The title part of this media's URL. You usually don't need to change this."
msgstr ""
"La parte del título de la URL de este contenido. Normalmente no necesitas "
"cambiar esto."
-#: mediagoblin/edit/forms.py:42
+#: mediagoblin/edit/forms.py:40
msgid "Bio"
msgstr "Bio"
-#: mediagoblin/edit/forms.py:45
+#: mediagoblin/edit/forms.py:43
msgid "Website"
msgstr "Sitio web"
-#: mediagoblin/edit/views.py:63
+#: mediagoblin/edit/views.py:64
msgid "An entry with that slug already exists for this user."
msgstr "Una entrada con esa ficha ya existe para este usuario."
-#: mediagoblin/edit/views.py:84
+#: mediagoblin/edit/views.py:85
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:154
+#: mediagoblin/edit/views.py:155
msgid "You are editing a user's profile. Proceed with caution."
msgstr "Estás editando un perfil de usuario. Proceder con precaución."
@@ -138,15 +143,15 @@ msgstr "Archivo"
msgid "Description of this work"
msgstr "Descripción de esta obra"
-#: mediagoblin/submit/views.py:47
+#: mediagoblin/submit/views.py:46
msgid "You must provide a file."
msgstr "Debes proporcionar un archivo."
-#: mediagoblin/submit/views.py:50
+#: mediagoblin/submit/views.py:49
msgid "The file doesn't seem to be an image!"
msgstr "¡El archivo no parece ser una imagen!"
-#: mediagoblin/submit/views.py:122
+#: mediagoblin/submit/views.py:121
msgid "Woohoo! Submitted!"
msgstr "¡Woohoo! ¡Enviado!"
@@ -184,11 +189,11 @@ msgstr "Enviar contenido"
#: mediagoblin/templates/mediagoblin/base.html:63
msgid "verify your email!"
-msgstr "Verifica tu correo electrónico!"
+msgstr "¡Verifica tu correo electrónico!"
#: mediagoblin/templates/mediagoblin/base.html:73
-#: mediagoblin/templates/mediagoblin/auth/login.html:26
-#: mediagoblin/templates/mediagoblin/auth/login.html:34
+#: mediagoblin/templates/mediagoblin/auth/login.html:27
+#: mediagoblin/templates/mediagoblin/auth/login.html:35
msgid "Log in"
msgstr "Conectarse"
@@ -197,25 +202,27 @@ msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project"
msgstr ""
+"Potenciado por <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
+"href=\"http://gnu.org/\">GNU</a> project"
#: mediagoblin/templates/mediagoblin/root.html:24
msgid "Explore"
-msgstr ""
+msgstr "Explorar"
#: mediagoblin/templates/mediagoblin/root.html:27
msgid "Hi there, media lover! MediaGoblin is..."
-msgstr "Hola, amante de los contenidos! MediaGoblin es ..."
+msgstr "¡Hola, amante de los contenidos! MediaGoblin es ..."
#: mediagoblin/templates/mediagoblin/root.html:29
msgid "The perfect place for your media!"
-msgstr "El lugar ideal para tus contenidos!"
+msgstr "¡El lugar ideal para tus contenidos!"
#: mediagoblin/templates/mediagoblin/root.html:30
msgid ""
"A place for people to collaborate and show off original and derived "
"creations!"
msgstr ""
-"Un lugar para colaborar y exhibir tus creaciones orignales y derivadas!"
+"¡Un lugar para colaborar y exhibir tus creaciones originales y derivadas!"
#: mediagoblin/templates/mediagoblin/root.html:31
msgid ""
@@ -238,8 +245,8 @@ msgid ""
"Built for extensibility. (Multiple media types coming soon to the software,"
" including video support!)"
msgstr ""
-"Pensado para la ser extensible. (Prontamente soporte para multiples "
-"formatos, incluyendo video!)"
+"Pensado para ser extensible. (Prontamente soporte para multiples formatos, "
+"incluyendo video!)"
#: mediagoblin/templates/mediagoblin/root.html:34
msgid ""
@@ -253,43 +260,42 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:38
msgid "Excited to join us?"
-msgstr ""
+msgstr "Te gustaría unirte a nosotros?"
#: mediagoblin/templates/mediagoblin/root.html:39
#, python-format
msgid ""
-"\n"
-" <a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
" or\n"
-" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>\n"
-" "
+" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
msgstr ""
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Crea una "
+"cuenta gratuita</a> o <a class=\"header_submit\" "
+"href=\"http://wiki.mediagoblin.org/HackingHowto\">Establece MediaGoblin en "
+"tu propio servidor</a>"
#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Most recent media"
-msgstr ""
+msgstr "El contenido más reciente"
-#: mediagoblin/templates/mediagoblin/auth/change_fp.html:27
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:29
msgid "Enter your new password"
-msgstr ""
+msgstr "Ingrese su nueva contraseña"
-#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29
msgid "Enter your username or email"
-msgstr ""
+msgstr "Introduzca su nombre de usuario o correo electrónico"
#: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22
-msgid ""
-"\n"
-" Your password has been changed. Try to log in now.\n"
-" "
-msgstr ""
+msgid "Your password has been changed. Try to log in now."
+msgstr "Se cambió tu contraseña. Intenta iniciar sesión ahora."
#: mediagoblin/templates/mediagoblin/auth/fp_email_sent.html:22
msgid ""
-"\n"
-" Check your inbox. We sent an email with a URL for changing your password.\n"
-" "
+"Check your inbox. We sent an email with a URL for changing your password."
msgstr ""
+"Revisa tu bandeja de entrada. Te enviamos un correo electrónico con una URL "
+"para cambiar tu contraseña."
#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19
#, python-format
@@ -304,32 +310,36 @@ msgid ""
"If you think this is an error, just ignore this email and continue being\n"
"a happy goblin!"
msgstr ""
+"Hola %(username)s , para cambiar su contraseña de GNU MediaGoblin, abra la "
+"siguiente URL en su navegador: %(verification_url)s Si usted piensa que "
+"esto es un error, simplemente ignore este mensaje y siga siendo un duende "
+"feliz!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:29
+#: mediagoblin/templates/mediagoblin/auth/login.html:30
msgid "Logging in failed!"
-msgstr "Falló el inicio de sesión!"
+msgstr "¡Falló el inicio de sesión!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:42
+#: mediagoblin/templates/mediagoblin/auth/login.html:43
msgid "Don't have an account yet?"
msgstr "¿No tienes una cuenta?"
-#: mediagoblin/templates/mediagoblin/auth/login.html:45
+#: mediagoblin/templates/mediagoblin/auth/login.html:46
msgid "Create one here!"
msgstr "¡Crea una aquí!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:48
+#: mediagoblin/templates/mediagoblin/auth/login.html:49
msgid "Forgot your password?"
-msgstr ""
+msgstr "¿Olvidaste tu contraseña?"
-#: mediagoblin/templates/mediagoblin/auth/login.html:51
+#: mediagoblin/templates/mediagoblin/auth/login.html:52
msgid "Change it!"
-msgstr ""
+msgstr "Cambiarlo!"
#: mediagoblin/templates/mediagoblin/auth/register.html:27
msgid "Create an account!"
msgstr "¡Crea una cuenta!"
-#: mediagoblin/templates/mediagoblin/auth/register.html:30
+#: mediagoblin/templates/mediagoblin/auth/register.html:31
msgid "Create"
msgstr "Crear"
@@ -377,7 +387,7 @@ msgstr "Contenido etiquetado con:"
msgid "Submit yer media"
msgstr "Envía tu contenido"
-#: mediagoblin/templates/mediagoblin/submit/start.html:29
+#: mediagoblin/templates/mediagoblin/submit/start.html:30
msgid "Submit"
msgstr "Enviar"
@@ -413,7 +423,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:28
msgid "Media in-processing"
-msgstr "Contenido siendo procesado"
+msgstr "Procesando contenido"
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:46
msgid "No media in-processing"
@@ -426,7 +436,7 @@ msgstr "Estos archivos no pudieron ser procesados:"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:39
#: mediagoblin/templates/mediagoblin/user_pages/user.html:59
msgid "Email verification needed"
-msgstr "Correo electrónico de verificación necesario"
+msgstr "Es necesario un correo electrónico de verificación"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:42
msgid "Almost done! Your account still needs to be activated."
@@ -453,7 +463,7 @@ msgid ""
" activated."
msgstr ""
"Alguien ya registró una cuenta con ese nombre de usuario, pero todavía no "
-"fué activada."
+"fue activada."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:68
#, python-format
@@ -471,7 +481,7 @@ msgstr "Perfil de %(username)s"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:85
msgid "Here's a spot to tell others about yourself."
-msgstr "Aquí hay un lugar para que le cuentes a los demás sobre tí"
+msgstr "Aquí hay un lugar para que le cuentes a los demás sobre tí."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:90
#: mediagoblin/templates/mediagoblin/user_pages/user.html:108
@@ -526,7 +536,15 @@ msgstr "Comentario"
msgid "I am sure I want to delete this"
msgstr "Estoy seguro de que quiero borrar esto"
-#: mediagoblin/user_pages/views.py:175
+#: mediagoblin/user_pages/views.py:142
+msgid "Empty comments are not allowed."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:148
+msgid "Comment posted!"
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:181
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 "
diff --git a/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.mo
index baab45ab..90e83303 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 032399d6..0a6a5a40 100644
--- a/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.po
@@ -3,6 +3,7 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
+# <chesuidayeur@yahoo.fr>, 2011.
# <joehillen@gmail.com>, 2011.
# <marktraceur@gmail.com>, 2011.
# <maxineb@members.fsf.org>, 2011.
@@ -12,9 +13,9 @@ msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n"
-"POT-Creation-Date: 2011-09-11 16:16-0500\n"
-"PO-Revision-Date: 2011-09-11 21:16+0000\n"
-"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
+"POT-Creation-Date: 2011-11-01 23:14-0500\n"
+"PO-Revision-Date: 2011-11-04 10:05+0000\n"
+"Last-Translator: chesuidayeur <chesuidayeur@yahoo.fr>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -42,26 +43,26 @@ msgstr "Confirmer le mot de passe"
#: mediagoblin/auth/forms.py:39
msgid "Type it again here to make sure there are no spelling mistakes."
msgstr ""
-"Tapez-le à nouveau ici pour vous assurer qu'il n'ya pas de fautes "
+"Tapez-le à nouveau ici pour vous assurer qu'il n'y a pas de fautes "
"d'orthographe."
#: mediagoblin/auth/forms.py:42
msgid "Email address"
msgstr "Adresse e-mail"
-#: mediagoblin/auth/views.py:42
+#: mediagoblin/auth/views.py:55
msgid "Sorry, registration is disabled on this instance."
msgstr "L'inscription n'est pas activée sur ce serveur, désolé."
-#: mediagoblin/auth/views.py:60
+#: mediagoblin/auth/views.py:73
msgid "Sorry, a user with that name already exists."
msgstr "Un utilisateur existe déjà avec ce nom, désolé."
-#: mediagoblin/auth/views.py:64
+#: mediagoblin/auth/views.py:77
msgid "Sorry, that email address has already been taken."
msgstr "Désolé, cette adresse courriel a déjà été prise."
-#: mediagoblin/auth/views.py:165
+#: mediagoblin/auth/views.py:179
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
@@ -69,60 +70,64 @@ msgstr ""
"Votre adresse e-mail a bien été vérifiée. Vous pouvez maintenant vous "
"identifier, modifier votre profil, et soumettre des images !"
-#: mediagoblin/auth/views.py:171
+#: mediagoblin/auth/views.py:185
msgid "The verification key or user id is incorrect"
msgstr "La clé de vérification ou le nom d'utilisateur est incorrect."
-#: mediagoblin/auth/views.py:192
+#: mediagoblin/auth/views.py:207
msgid "Resent your verification email."
msgstr "E-mail de vérification renvoyé."
-#: mediagoblin/auth/views.py:228
+#: mediagoblin/auth/views.py:248
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr ""
+"Impossible d'envoyer un email de récupération de mot de passe : votre compte"
+" est inactif ou bien l'email de votre compte n'a pas été vérifiée."
-#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+#: mediagoblin/edit/forms.py:24 mediagoblin/submit/forms.py:27
msgid "Title"
msgstr "Titre"
-#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:32
msgid "Tags"
msgstr "Tags"
-#: mediagoblin/edit/forms.py:33
+#: mediagoblin/edit/forms.py:31
msgid "Slug"
msgstr "Légende"
-#: mediagoblin/edit/forms.py:34
+#: mediagoblin/edit/forms.py:32
msgid "The slug can't be empty"
msgstr "La légende ne peut pas être laissée vide."
-#: mediagoblin/edit/forms.py:35
+#: mediagoblin/edit/forms.py:33
msgid ""
"The title part of this media's URL. You usually don't need to change this."
msgstr ""
+"Le nom de ce media dans l'URL. Vous n'avez normalement pas besoin de le "
+"changer"
-#: mediagoblin/edit/forms.py:42
+#: mediagoblin/edit/forms.py:40
msgid "Bio"
msgstr "Bio"
-#: mediagoblin/edit/forms.py:45
+#: mediagoblin/edit/forms.py:43
msgid "Website"
msgstr "Site web"
-#: mediagoblin/edit/views.py:63
+#: mediagoblin/edit/views.py:64
msgid "An entry with that slug already exists for this user."
msgstr "Une entrée existe déjà pour cet utilisateur avec la même légende."
-#: mediagoblin/edit/views.py:84
+#: mediagoblin/edit/views.py:85
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:154
+#: mediagoblin/edit/views.py:155
msgid "You are editing a user's profile. Proceed with caution."
msgstr ""
"Vous vous apprêtez à modifier le profil d'un utilisateur. Veuillez prendre "
@@ -130,7 +135,7 @@ msgstr ""
#: mediagoblin/process_media/errors.py:44
msgid "Invalid file given for media type."
-msgstr "Invalide fichier donné pour le type de média."
+msgstr "Le fichier envoyé ne correspond pas au type de média."
#: mediagoblin/submit/forms.py:25
msgid "File"
@@ -138,17 +143,17 @@ msgstr "Fichier"
#: mediagoblin/submit/forms.py:30
msgid "Description of this work"
-msgstr ""
+msgstr "Descriptif pour ce travail"
-#: mediagoblin/submit/views.py:47
+#: mediagoblin/submit/views.py:46
msgid "You must provide a file."
msgstr "Il vous faut fournir un fichier."
-#: mediagoblin/submit/views.py:50
+#: mediagoblin/submit/views.py:49
msgid "The file doesn't seem to be an image!"
msgstr "Ce fichier ne semble pas être une image !"
-#: mediagoblin/submit/views.py:122
+#: mediagoblin/submit/views.py:121
msgid "Woohoo! Submitted!"
msgstr "Youhou, c'est envoyé !"
@@ -158,7 +163,7 @@ msgstr "Zut!"
#: mediagoblin/templates/mediagoblin/404.html:24
msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr "Il ne semble pas être une page à cette adresse. Désolé!"
+msgstr "Il ne semble pas y avoir de page à cette adresse. Désolé !"
#: mediagoblin/templates/mediagoblin/404.html:26
msgid ""
@@ -166,11 +171,11 @@ msgid ""
" 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é ou supprimé."
+"recherchez a été déplacée ou supprimée."
#: mediagoblin/templates/mediagoblin/404.html:32
msgid "Image of 404 goblin stressing out"
-msgstr "Image de 404 gobelin stresser"
+msgstr "Image de 404 gobelin angoissé"
#: mediagoblin/templates/mediagoblin/base.html:22
msgid "GNU MediaGoblin"
@@ -189,8 +194,8 @@ msgid "verify your email!"
msgstr "vérifiez votre adresse e-mail !"
#: mediagoblin/templates/mediagoblin/base.html:73
-#: mediagoblin/templates/mediagoblin/auth/login.html:26
-#: mediagoblin/templates/mediagoblin/auth/login.html:34
+#: mediagoblin/templates/mediagoblin/auth/login.html:27
+#: mediagoblin/templates/mediagoblin/auth/login.html:35
msgid "Log in"
msgstr "S'identifier"
@@ -199,12 +204,12 @@ msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project"
msgstr ""
-"Propulsé par <a href=\"http://mediagoblin.org\">MediaGoblin</a> , un <a "
-"href=\"http://gnu.org/\">GNU</a> de projet"
+"Propulsé par <a href=\"http://mediagoblin.org\">MediaGoblin</a> , un projet "
+"<a href=\"http://gnu.org/\">GNU</a>"
#: mediagoblin/templates/mediagoblin/root.html:24
msgid "Explore"
-msgstr ""
+msgstr "Explorer"
#: mediagoblin/templates/mediagoblin/root.html:27
msgid "Hi there, media lover! MediaGoblin is..."
@@ -219,15 +224,15 @@ msgid ""
"A place for people to collaborate and show off original and derived "
"creations!"
msgstr ""
-"Un lieu pour les personnes de collaborer et de montrer des créations "
-"originales et dérivées!"
+"Un espace de création collaboratif : montrez vos œuvres, originales ou "
+"dérivées !"
#: mediagoblin/templates/mediagoblin/root.html:31
msgid ""
"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project, "
"after all.)"
msgstr ""
-"Logiciel libre. (Nous sommes une <a href=\"http://gnu.org\">GNU</a> projet, "
+"Logiciel libre. (Nous sommes un projet <a href=\"http://gnu.org\">GNU</a> "
"après tout.)"
#: mediagoblin/templates/mediagoblin/root.html:32
@@ -235,8 +240,8 @@ msgid ""
"Aiming to make the world a better place through decentralization and "
"(eventually, coming soon!) federation!"
msgstr ""
-"Visant à rendre le monde meilleur grâce à la décentralisation et "
-"(éventuellement, venir bientôt!) fédération!"
+"Une tentative de rendre le monde meilleur grâce à la décentralisation et (à "
+"terme, et pour bientôt !) la fédération !"
#: mediagoblin/templates/mediagoblin/root.html:33
msgid ""
@@ -258,43 +263,42 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:38
msgid "Excited to join us?"
-msgstr ""
+msgstr "Envi de vous joindre à nous ?"
#: mediagoblin/templates/mediagoblin/root.html:39
#, python-format
msgid ""
-"\n"
-" <a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
" or\n"
-" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>\n"
-" "
+" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
msgstr ""
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Créez gratuitement en compte</a>\n"
+" ou\n"
+" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Installez MediaGoblin sur votre propre serveur</a>"
#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Most recent media"
-msgstr ""
+msgstr "Tout derniers media"
-#: mediagoblin/templates/mediagoblin/auth/change_fp.html:27
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:29
msgid "Enter your new password"
-msgstr ""
+msgstr "Entrez un nouveau mot de passe"
-#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29
msgid "Enter your username or email"
-msgstr ""
+msgstr "Entrez votre nom d'utilisateur ou votre email"
#: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22
-msgid ""
-"\n"
-" Your password has been changed. Try to log in now.\n"
-" "
+msgid "Your password has been changed. Try to log in now."
msgstr ""
+"Votre mot de passe a été changé. Essayez maintenant de vous identifier."
#: mediagoblin/templates/mediagoblin/auth/fp_email_sent.html:22
msgid ""
-"\n"
-" Check your inbox. We sent an email with a URL for changing your password.\n"
-" "
+"Check your inbox. We sent an email with a URL for changing your password."
msgstr ""
+"Verifiez votre boîte de réception. Nous vous avons envoyé un email avec une "
+"URL vous permettant de changer votre mot de passe."
#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19
#, python-format
@@ -309,32 +313,41 @@ msgid ""
"If you think this is an error, just ignore this email and continue being\n"
"a happy goblin!"
msgstr ""
+"Bonjour %(username)s,\n"
+"\n"
+"Pour changer votre mot de passe GNU MediaGoblin, ouvrez l'URL suivante dans \n"
+"votre navigateur internet :\n"
+"\n"
+"%(verification_url)s\n"
+"\n"
+"Si vous pensez qu'il s'agit d'une erreur, ignorez simplement cet email et restez\n"
+"un goblin heureux !"
-#: mediagoblin/templates/mediagoblin/auth/login.html:29
+#: mediagoblin/templates/mediagoblin/auth/login.html:30
msgid "Logging in failed!"
-msgstr "Connexion a échoué!"
+msgstr "La connexion a échoué!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:42
+#: mediagoblin/templates/mediagoblin/auth/login.html:43
msgid "Don't have an account yet?"
msgstr "Pas encore de compte?"
-#: mediagoblin/templates/mediagoblin/auth/login.html:45
+#: mediagoblin/templates/mediagoblin/auth/login.html:46
msgid "Create one here!"
msgstr "Créez-en un ici!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:48
+#: mediagoblin/templates/mediagoblin/auth/login.html:49
msgid "Forgot your password?"
-msgstr ""
+msgstr "Vous avez oublié votre mot de passe ?"
-#: mediagoblin/templates/mediagoblin/auth/login.html:51
+#: mediagoblin/templates/mediagoblin/auth/login.html:52
msgid "Change it!"
-msgstr ""
+msgstr "Changez-le !"
#: mediagoblin/templates/mediagoblin/auth/register.html:27
msgid "Create an account!"
msgstr "Créer un compte!"
-#: mediagoblin/templates/mediagoblin/auth/register.html:30
+#: mediagoblin/templates/mediagoblin/auth/register.html:31
msgid "Create"
msgstr "Créer"
@@ -382,7 +395,7 @@ msgstr "Média comportant les tags suivants :"
msgid "Submit yer media"
msgstr "Soumettez ce média"
-#: mediagoblin/templates/mediagoblin/submit/start.html:29
+#: mediagoblin/templates/mediagoblin/submit/start.html:30
msgid "Submit"
msgstr "Soumettre"
@@ -403,7 +416,7 @@ msgstr "Voulez-vous vraiment supprimer %(title)s ?"
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
msgid "Delete Permanently"
-msgstr ""
+msgstr "Supprimer définitivement"
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:22
msgid "Media processing panel"
@@ -426,7 +439,7 @@ msgstr "Aucun média en transformation"
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:50
msgid "These uploads failed to process:"
-msgstr "Ces ajouts n'etaient pas processé:"
+msgstr "Le traitement de ces ajouts a échoué :"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:39
#: mediagoblin/templates/mediagoblin/user_pages/user.html:59
@@ -435,7 +448,7 @@ msgstr "Vérification d'email nécessaire"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:42
msgid "Almost done! Your account still needs to be activated."
-msgstr "Presque fini! Votre compte a encore besoin d'être activé."
+msgstr "Presque fini ! Votre compte a encore besoin d'être activé."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:47
msgid ""
@@ -486,7 +499,7 @@ msgstr "Modifier le profil"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:96
msgid "This user hasn't filled in their profile (yet)."
-msgstr "Cet utilisateur n'a pas rempli leur profil (encore)."
+msgstr "Cet utilisateur n'a pas (encore) rempli son profil."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:122
#, python-format
@@ -498,8 +511,8 @@ 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ît, mais vous ne semblez pas avoir quoi que ce "
-"soit encore ajouté."
+"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:141
msgid "Add media"
@@ -507,11 +520,11 @@ msgstr "Ajouter des médias"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:147
msgid "There doesn't seem to be any media here yet..."
-msgstr "Il ne semble pas être un média encore là ..."
+msgstr "Il ne semble pas y avoir de média là, pour l'instant ..."
#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
msgid "feed icon"
-msgstr "icon de flux"
+msgstr "icone de flux"
#: mediagoblin/templates/mediagoblin/utils/feed_link.html:23
msgid "Atom feed"
@@ -519,11 +532,11 @@ msgstr "flux Atom"
#: mediagoblin/templates/mediagoblin/utils/pagination.html:40
msgid "Newer"
-msgstr ""
+msgstr "Nouveaux"
#: mediagoblin/templates/mediagoblin/utils/pagination.html:46
msgid "Older"
-msgstr ""
+msgstr "Anciens"
#: mediagoblin/user_pages/forms.py:24
msgid "Comment"
@@ -531,9 +544,17 @@ msgstr "Commentaire"
#: mediagoblin/user_pages/forms.py:30
msgid "I am sure I want to delete this"
-msgstr ""
+msgstr "Je suis sûr de vouloir supprimer cela"
+
+#: mediagoblin/user_pages/views.py:142
+msgid "Empty comments are not allowed."
+msgstr "Les commentaires vides ne sont pas autorisés."
+
+#: mediagoblin/user_pages/views.py:148
+msgid "Comment posted!"
+msgstr "Votre commentaire a été posté !"
-#: mediagoblin/user_pages/views.py:175
+#: mediagoblin/user_pages/views.py:181
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. "
diff --git a/mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.mo
new file mode 100644
index 00000000..feb156ff
--- /dev/null
+++ 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
new file mode 100644
index 00000000..d9fdf8d6
--- /dev/null
+++ b/mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.po
@@ -0,0 +1,498 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+#
+# Translators:
+# Emilio Sepúlveda <djfunkinmixer@gmail.com>, 2011.
+msgid ""
+msgstr ""
+"Project-Id-Version: GNU MediaGoblin\n"
+"Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n"
+"POT-Creation-Date: 2011-11-01 23:14-0500\n"
+"PO-Revision-Date: 2011-11-02 04:13+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: ia\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+
+#: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:49
+msgid "Username"
+msgstr "Nomine de usator"
+
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:53
+msgid "Password"
+msgstr "Contrasigno"
+
+#: mediagoblin/auth/forms.py:35
+msgid "Passwords must match."
+msgstr ""
+
+#: mediagoblin/auth/forms.py:37
+msgid "Confirm password"
+msgstr ""
+
+#: mediagoblin/auth/forms.py:39
+msgid "Type it again here to make sure there are no spelling mistakes."
+msgstr ""
+
+#: mediagoblin/auth/forms.py:42
+msgid "Email address"
+msgstr "Adresse de e-posta"
+
+#: mediagoblin/auth/views.py:55
+msgid "Sorry, registration is disabled on this instance."
+msgstr ""
+
+#: mediagoblin/auth/views.py:73
+msgid "Sorry, a user with that name already exists."
+msgstr ""
+
+#: mediagoblin/auth/views.py:77
+msgid "Sorry, that email address has already been taken."
+msgstr ""
+
+#: mediagoblin/auth/views.py:179
+msgid ""
+"Your email address has been verified. You may now login, edit your profile, "
+"and submit images!"
+msgstr ""
+
+#: mediagoblin/auth/views.py:185
+msgid "The verification key or user id is incorrect"
+msgstr ""
+
+#: mediagoblin/auth/views.py:207
+msgid "Resent your verification email."
+msgstr ""
+
+#: mediagoblin/auth/views.py:248
+msgid ""
+"Could not send password recovery email as your username is inactive or your "
+"account's email address has not been verified."
+msgstr ""
+
+#: mediagoblin/edit/forms.py:24 mediagoblin/submit/forms.py:27
+msgid "Title"
+msgstr "Titulo"
+
+#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:32
+msgid "Tags"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:31
+msgid "Slug"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:32
+msgid "The slug can't be empty"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:33
+msgid ""
+"The title part of this media's URL. You usually don't need to change this."
+msgstr ""
+
+#: mediagoblin/edit/forms.py:40
+msgid "Bio"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:43
+msgid "Website"
+msgstr "Sito web"
+
+#: mediagoblin/edit/views.py:64
+msgid "An entry with that slug already exists for this user."
+msgstr ""
+
+#: mediagoblin/edit/views.py:85
+msgid "You are editing another user's media. Proceed with caution."
+msgstr ""
+
+#: mediagoblin/edit/views.py:155
+msgid "You are editing a user's profile. Proceed with caution."
+msgstr ""
+
+#: mediagoblin/process_media/errors.py:44
+msgid "Invalid file given for media type."
+msgstr ""
+
+#: mediagoblin/submit/forms.py:25
+msgid "File"
+msgstr ""
+
+#: mediagoblin/submit/forms.py:30
+msgid "Description of this work"
+msgstr ""
+
+#: mediagoblin/submit/views.py:46
+msgid "You must provide a file."
+msgstr ""
+
+#: mediagoblin/submit/views.py:49
+msgid "The file doesn't seem to be an image!"
+msgstr ""
+
+#: mediagoblin/submit/views.py:121
+msgid "Woohoo! Submitted!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/404.html:21
+msgid "Oops!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/404.html:24
+msgid "There doesn't seem to be a page at this address. Sorry!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/404.html:26
+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/404.html:32
+msgid "Image of 404 goblin stressing out"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/base.html:22
+msgid "GNU MediaGoblin"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/base.html:47
+msgid "MediaGoblin logo"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/base.html:52
+msgid "Submit media"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/base.html:63
+msgid "verify your email!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/base.html:73
+#: mediagoblin/templates/mediagoblin/auth/login.html:27
+#: mediagoblin/templates/mediagoblin/auth/login.html:35
+msgid "Log in"
+msgstr "Initiar session"
+
+#: mediagoblin/templates/mediagoblin/base.html:89
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
+"href=\"http://gnu.org/\">GNU</a> project"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:24
+msgid "Explore"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:27
+msgid "Hi there, media lover! MediaGoblin is..."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:29
+msgid "The perfect place for your media!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:30
+msgid ""
+"A place for people to collaborate and show off original and derived "
+"creations!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid ""
+"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project, "
+"after all.)"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:32
+msgid ""
+"Aiming to make the world a better place through decentralization and "
+"(eventually, coming soon!) federation!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:33
+msgid ""
+"Built for extensibility. (Multiple media types coming soon to the software,"
+" including video support!)"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid ""
+"Powered by people like you. (<a "
+"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve this"
+" software!</a>)"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+msgid "Excited to join us?"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:39
+#, python-format
+msgid ""
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
+" or\n"
+" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:53
+msgid "Most recent media"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:29
+msgid "Enter your new password"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29
+msgid "Enter your username or email"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22
+msgid "Your password has been changed. Try to log in now."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/fp_email_sent.html:22
+msgid ""
+"Check your inbox. We sent an email with a URL for changing your password."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19
+#, python-format
+msgid ""
+"Hi %(username)s,\n"
+"\n"
+"to change your GNU MediaGoblin password, open the following URL in \n"
+"your web browser:\n"
+"\n"
+"%(verification_url)s\n"
+"\n"
+"If you think this is an error, just ignore this email and continue being\n"
+"a happy goblin!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:30
+msgid "Logging in failed!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:43
+msgid "Don't have an account yet?"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:46
+msgid "Create one here!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:49
+msgid "Forgot your password?"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:52
+msgid "Change it!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:27
+msgid "Create an account!"
+msgstr "Crear un conto!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:31
+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 ""
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:29
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:36
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+msgid "Cancel"
+msgstr "Cancellar"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:37
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
+msgid "Save changes"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:29
+#, python-format
+msgid "Editing %(username)s's profile"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/listings/tag.html:31
+msgid "Media tagged with:"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:26
+msgid "Submit yer media"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:30
+msgid "Submit"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:32
+msgid "Sorry, no such user found."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
+#, python-format
+msgid "Really delete %(title)s?"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+msgid "Delete Permanently"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:22
+msgid "Media processing panel"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:25
+msgid ""
+"You can track the state of media being processed for your gallery here."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:28
+msgid "Media in-processing"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:46
+msgid "No media in-processing"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:50
+msgid "These uploads failed to process:"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:39
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:59
+msgid "Email verification needed"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:42
+msgid "Almost done! Your account still needs to be activated."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:47
+msgid ""
+"An email should arrive in a few moments with instructions on how to do so."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:51
+msgid "In case it doesn't:"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:54
+msgid "Resend verification email"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:62
+msgid ""
+"Someone has registered an account with this username, but it still has to be"
+" activated."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:68
+#, 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 ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:78
+#, python-format
+msgid "%(username)s's profile"
+msgstr "Profilo de %(username)s"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:85
+msgid "Here's a spot to tell others about yourself."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:90
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:108
+msgid "Edit profile"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:96
+msgid "This user hasn't filled in their profile (yet)."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:122
+#, python-format
+msgid "View all of %(username)s's media"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:135
+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:141
+msgid "Add media"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:147
+msgid "There doesn't seem to be any media here yet..."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
+msgid "feed icon"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/utils/feed_link.html:23
+msgid "Atom feed"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/utils/pagination.html:40
+msgid "Newer"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/utils/pagination.html:46
+msgid "Older"
+msgstr ""
+
+#: mediagoblin/user_pages/forms.py:24
+msgid "Comment"
+msgstr "Commento"
+
+#: mediagoblin/user_pages/forms.py:30
+msgid "I am sure I want to delete this"
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:142
+msgid "Empty comments are not allowed."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:148
+msgid "Comment posted!"
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:181
+msgid "You are about to delete another user's media. Proceed with caution."
+msgstr ""
+
+
diff --git a/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.mo
new file mode 100644
index 00000000..cc0ccbfa
--- /dev/null
+++ 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
new file mode 100644
index 00000000..183d09ed
--- /dev/null
+++ b/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.po
@@ -0,0 +1,528 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+#
+# Translators:
+# <robi@nunnisoft.ch>, 2011.
+msgid ""
+msgstr ""
+"Project-Id-Version: GNU MediaGoblin\n"
+"Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n"
+"POT-Creation-Date: 2011-11-01 23:14-0500\n"
+"PO-Revision-Date: 2011-11-02 04:13+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: it\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+
+#: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:49
+msgid "Username"
+msgstr "Nome utente"
+
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:53
+msgid "Password"
+msgstr "Password"
+
+#: mediagoblin/auth/forms.py:35
+msgid "Passwords must match."
+msgstr "Le password devono coincidere"
+
+#: mediagoblin/auth/forms.py:37
+msgid "Confirm password"
+msgstr "Conferma password"
+
+#: mediagoblin/auth/forms.py:39
+msgid "Type it again here to make sure there are no spelling mistakes."
+msgstr "Scrivilo ancora qui per assicurarti che non ci siano errori"
+
+#: mediagoblin/auth/forms.py:42
+msgid "Email address"
+msgstr "Indirizzo email"
+
+#: mediagoblin/auth/views.py:55
+msgid "Sorry, registration is disabled on this instance."
+msgstr "Spiacente, registrazione è disabilitata su questa istanza"
+
+#: mediagoblin/auth/views.py:73
+msgid "Sorry, a user with that name already exists."
+msgstr "Spiacente, esiste già un utente con quel nome"
+
+#: mediagoblin/auth/views.py:77
+msgid "Sorry, that email address has already been taken."
+msgstr "Spiacente, quell'indirizzo email è già stato preso."
+
+#: mediagoblin/auth/views.py:179
+msgid ""
+"Your email address has been verified. You may now login, edit your profile, "
+"and submit images!"
+msgstr ""
+"Il tuo indirizzo email è stato verificato. Puoi ora fare login, modificare "
+"il tuo profilo, e inserire immagini!"
+
+#: mediagoblin/auth/views.py:185
+msgid "The verification key or user id is incorrect"
+msgstr "La chiave di verifica o l'id utente è sbagliato"
+
+#: mediagoblin/auth/views.py:207
+msgid "Resent your verification email."
+msgstr "Rispedisci email di verifica"
+
+#: mediagoblin/auth/views.py:248
+msgid ""
+"Could not send password recovery email as your username is inactive or your "
+"account's email address has not been verified."
+msgstr ""
+
+#: mediagoblin/edit/forms.py:24 mediagoblin/submit/forms.py:27
+msgid "Title"
+msgstr "Titolo"
+
+#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:32
+msgid "Tags"
+msgstr "Tags"
+
+#: mediagoblin/edit/forms.py:31
+msgid "Slug"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:32
+msgid "The slug can't be empty"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:33
+msgid ""
+"The title part of this media's URL. You usually don't need to change this."
+msgstr ""
+
+#: mediagoblin/edit/forms.py:40
+msgid "Bio"
+msgstr "Bio"
+
+#: mediagoblin/edit/forms.py:43
+msgid "Website"
+msgstr "Sito web"
+
+#: mediagoblin/edit/views.py:64
+msgid "An entry with that slug already exists for this user."
+msgstr ""
+
+#: mediagoblin/edit/views.py:85
+msgid "You are editing another user's media. Proceed with caution."
+msgstr ""
+"Stai modificando documenti multimediale di un altro utente. Procedi con "
+"attenzione."
+
+#: mediagoblin/edit/views.py:155
+msgid "You are editing a user's profile. Proceed with caution."
+msgstr "Stai modificando il profilo di un utente. Procedi con attenzione."
+
+#: mediagoblin/process_media/errors.py:44
+msgid "Invalid file given for media type."
+msgstr "documento non valido come tipo multimediale."
+
+#: mediagoblin/submit/forms.py:25
+msgid "File"
+msgstr "Documento"
+
+#: mediagoblin/submit/forms.py:30
+msgid "Description of this work"
+msgstr "Descrizione di questo lavoro"
+
+#: mediagoblin/submit/views.py:46
+msgid "You must provide a file."
+msgstr "Devi specificare un documento."
+
+#: mediagoblin/submit/views.py:49
+msgid "The file doesn't seem to be an image!"
+msgstr "Il documento non sembra essere un'immagine!"
+
+#: mediagoblin/submit/views.py:121
+msgid "Woohoo! Submitted!"
+msgstr "Evviva! "
+
+#: mediagoblin/templates/mediagoblin/404.html:21
+msgid "Oops!"
+msgstr "Oops!"
+
+#: mediagoblin/templates/mediagoblin/404.html:24
+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:26
+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/404.html:32
+msgid "Image of 404 goblin stressing out"
+msgstr "Immagine di 404 folletti che stressano"
+
+#: mediagoblin/templates/mediagoblin/base.html:22
+msgid "GNU MediaGoblin"
+msgstr "GNU MediaGoblin"
+
+#: mediagoblin/templates/mediagoblin/base.html:47
+msgid "MediaGoblin logo"
+msgstr "MediaGoblin logo"
+
+#: mediagoblin/templates/mediagoblin/base.html:52
+msgid "Submit media"
+msgstr "Inoltra file multimediale"
+
+#: mediagoblin/templates/mediagoblin/base.html:63
+msgid "verify your email!"
+msgstr "verifica il tuo indirizzo email!"
+
+#: mediagoblin/templates/mediagoblin/base.html:73
+#: mediagoblin/templates/mediagoblin/auth/login.html:27
+#: mediagoblin/templates/mediagoblin/auth/login.html:35
+msgid "Log in"
+msgstr "Accedi"
+
+#: mediagoblin/templates/mediagoblin/base.html:89
+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>, un progetto "
+"<a href=\"http://gnu.org/\">GNU</a>"
+
+#: mediagoblin/templates/mediagoblin/root.html:24
+msgid "Explore"
+msgstr "Esplora"
+
+#: mediagoblin/templates/mediagoblin/root.html:27
+msgid "Hi there, media lover! MediaGoblin is..."
+msgstr "Ciao, amante del multimedia! MediaGoblin è..."
+
+#: mediagoblin/templates/mediagoblin/root.html:29
+msgid "The perfect place for your media!"
+msgstr "Il posto perfetto per i tuoi documenti multimediali!"
+
+#: mediagoblin/templates/mediagoblin/root.html:30
+msgid ""
+"A place for people to collaborate and show off original and derived "
+"creations!"
+msgstr ""
+"Un posto per collaborare con altri e mostrare le proprie creazioni originali"
+" e derivate!"
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid ""
+"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project, "
+"after all.)"
+msgstr ""
+"Libero, come in libertà. (Siamo un progetto <a "
+"href=\"http://gnu.org\">GNU</a>, dopotutto.)"
+
+#: mediagoblin/templates/mediagoblin/root.html:32
+msgid ""
+"Aiming to make the world a better place through decentralization and "
+"(eventually, coming soon!) federation!"
+msgstr ""
+"Con l'obbiettivo di rendere il mondo un posto migliore attraverso la "
+"decentrelizzazione e (finalmente, presto!) federazione!"
+
+#: mediagoblin/templates/mediagoblin/root.html:33
+msgid ""
+"Built for extensibility. (Multiple media types coming soon to the software,"
+" including video support!)"
+msgstr ""
+"Fatto per estensibilità. (Numerosi tipi multimediali saranno presto aggiunti"
+" al programma, incluso il supporto video!)"
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid ""
+"Powered by people like you. (<a "
+"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve this"
+" software!</a>)"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+msgid "Excited to join us?"
+msgstr "Eccitato di unirti a noi?"
+
+#: mediagoblin/templates/mediagoblin/root.html:39
+#, python-format
+msgid ""
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
+" or\n"
+" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:53
+msgid "Most recent media"
+msgstr "Documenti multimediali più recenti"
+
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:29
+msgid "Enter your new password"
+msgstr "Inserisci la tua nuova password"
+
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29
+msgid "Enter your username or email"
+msgstr "Inserisci il tuo nome utente o email"
+
+#: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22
+msgid "Your password has been changed. Try to log in now."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/fp_email_sent.html:22
+msgid ""
+"Check your inbox. We sent an email with a URL for changing your password."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19
+#, python-format
+msgid ""
+"Hi %(username)s,\n"
+"\n"
+"to change your GNU MediaGoblin password, open the following URL in \n"
+"your web browser:\n"
+"\n"
+"%(verification_url)s\n"
+"\n"
+"If you think this is an error, just ignore this email and continue being\n"
+"a happy goblin!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:30
+msgid "Logging in failed!"
+msgstr "Accesso fallito!"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:43
+msgid "Don't have an account yet?"
+msgstr "Non hai ancora un account?"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:46
+msgid "Create one here!"
+msgstr "Creane uno qui!"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:49
+msgid "Forgot your password?"
+msgstr "Hai dimenticato la password?"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:52
+msgid "Change it!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:27
+msgid "Create an account!"
+msgstr "Crea un account!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:31
+msgid "Create"
+msgstr "Crea"
+
+#: 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 ""
+"Ciao %(username)s,\n"
+"\n"
+"per attivare il tuo account GNU MediaGoblin, apri il seguente URL nel tuo navigatore web.\n"
+"\n"
+"%(verification_url)s"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:29
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "Stai modificando %(media_title)s"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:36
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+msgid "Cancel"
+msgstr "Annulla"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:37
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
+msgid "Save changes"
+msgstr "Salva i cambiamenti"
+
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:29
+#, python-format
+msgid "Editing %(username)s's profile"
+msgstr "Stai modificando il profilo di %(username)s"
+
+#: mediagoblin/templates/mediagoblin/listings/tag.html:31
+msgid "Media tagged with:"
+msgstr "Media taggata con:"
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:26
+msgid "Submit yer media"
+msgstr "Inoltra documento multimediale"
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:30
+msgid "Submit"
+msgstr "Conferma"
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media"
+msgstr "Documenti multimediali di <a href=\"%(user_url)s\">%(username)s</a>"
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:32
+msgid "Sorry, no such user found."
+msgstr "Mi dispiace, utente non trovato"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
+#, python-format
+msgid "Really delete %(title)s?"
+msgstr "Vuoi davvero cancellare %(title)s?"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+msgid "Delete Permanently"
+msgstr "Cancella permanentemente"
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:22
+msgid "Media processing panel"
+msgstr "Pannello di elaborazione media"
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:25
+msgid ""
+"You can track the state of media being processed for your gallery here."
+msgstr "Puoi seguire lo stato dell'elaborazione per la tua galleria qui."
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:28
+msgid "Media in-processing"
+msgstr "Media in elaborazione"
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:46
+msgid "No media in-processing"
+msgstr "Nessun documento multimediale in elaborazione"
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:50
+msgid "These uploads failed to process:"
+msgstr "L'elaborazione di questi upload è fallita:"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:39
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:59
+msgid "Email verification needed"
+msgstr "è necessario verificare email"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:42
+msgid "Almost done! Your account still needs to be activated."
+msgstr "Quasi finito! Il tuo account deve ancora essere attivato."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:47
+msgid ""
+"An email should arrive in a few moments with instructions on how to do so."
+msgstr ""
+"In breve dovresti ricevere un email contenente istruzioni su come fare."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:51
+msgid "In case it doesn't:"
+msgstr "Nel caso non fosse:"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:54
+msgid "Resend verification email"
+msgstr "Rispedisci email di verifica"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:62
+msgid ""
+"Someone has registered an account with this username, but it still has to be"
+" activated."
+msgstr ""
+"Qualcuno ha registrato un account con questo nome utente, ma deve ancora "
+"essere attivato."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:68
+#, 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 ""
+"Se sei quella persona ma hai perso l'email di verifica, puoi <a "
+"href=\"%(login_url)s\">accedere</a> e rispedirlo."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:78
+#, python-format
+msgid "%(username)s's profile"
+msgstr "profilo di %(username)s"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:85
+msgid "Here's a spot to tell others about yourself."
+msgstr "Ecco un posto dove raccontare agli altri di te."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:90
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:108
+msgid "Edit profile"
+msgstr "Modifica profilo"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:96
+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:122
+#, python-format
+msgid "View all of %(username)s's media"
+msgstr "Visualizza tutti i file multimediali di %(username)s"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:135
+msgid ""
+"This is where your media will appear, but you don't seem to have added "
+"anything yet."
+msgstr ""
+"Questo è dove i tuoi documenti multimediali appariranno, ma sembra che tu "
+"non abbia ancora aggiunto niente."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:141
+msgid "Add media"
+msgstr "Aggiungi documenti multimediali"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:147
+msgid "There doesn't seem to be any media here yet..."
+msgstr "Non sembra ci sia ancora nessun documento multimediali qui.."
+
+#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
+msgid "feed icon"
+msgstr "feed icon"
+
+#: mediagoblin/templates/mediagoblin/utils/feed_link.html:23
+msgid "Atom feed"
+msgstr "Atom feed"
+
+#: mediagoblin/templates/mediagoblin/utils/pagination.html:40
+msgid "Newer"
+msgstr "Più nuovo"
+
+#: mediagoblin/templates/mediagoblin/utils/pagination.html:46
+msgid "Older"
+msgstr "Più vecchio"
+
+#: mediagoblin/user_pages/forms.py:24
+msgid "Comment"
+msgstr "Commento"
+
+#: mediagoblin/user_pages/forms.py:30
+msgid "I am sure I want to delete this"
+msgstr "Sono sicuro di volerlo cancellare"
+
+#: mediagoblin/user_pages/views.py:142
+msgid "Empty comments are not allowed."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:148
+msgid "Comment posted!"
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:181
+msgid "You are about to delete another user's media. Proceed with caution."
+msgstr ""
+"Stai cancellando un documento multimediale di un altro utente. Procedi con "
+"attenzione."
+
+
diff --git a/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.mo
index efd3e3f4..5267eddc 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 79be3177..59262d82 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://bugs.foocorp.net/projects/mediagoblin/issues\n"
-"POT-Creation-Date: 2011-09-11 16:16-0500\n"
-"PO-Revision-Date: 2011-09-11 21:16+0000\n"
+"POT-Creation-Date: 2011-11-01 23:14-0500\n"
+"PO-Revision-Date: 2011-11-02 04:13+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
@@ -43,76 +43,76 @@ msgstr ""
msgid "Email address"
msgstr "メールアドレス"
-#: mediagoblin/auth/views.py:42
+#: mediagoblin/auth/views.py:55
msgid "Sorry, registration is disabled on this instance."
msgstr "申し訳ありませんが、このインスタンスで登録は無効になっています。"
-#: mediagoblin/auth/views.py:60
+#: mediagoblin/auth/views.py:73
msgid "Sorry, a user with that name already exists."
msgstr "申し訳ありませんが、その名前を持つユーザーがすでに存在しています。"
-#: mediagoblin/auth/views.py:64
+#: mediagoblin/auth/views.py:77
msgid "Sorry, that email address has already been taken."
msgstr ""
-#: mediagoblin/auth/views.py:165
+#: mediagoblin/auth/views.py:179
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr "メアドが確認されています。これで、ログインしてプロファイルを編集し、画像を提出することができます!"
-#: mediagoblin/auth/views.py:171
+#: mediagoblin/auth/views.py:185
msgid "The verification key or user id is incorrect"
msgstr "検証キーまたはユーザーIDが間違っています"
-#: mediagoblin/auth/views.py:192
+#: mediagoblin/auth/views.py:207
msgid "Resent your verification email."
msgstr "検証メールを再送しました。"
-#: mediagoblin/auth/views.py:228
+#: mediagoblin/auth/views.py:248
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr ""
-#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+#: mediagoblin/edit/forms.py:24 mediagoblin/submit/forms.py:27
msgid "Title"
msgstr "タイトル"
-#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:32
msgid "Tags"
msgstr "タグ"
-#: mediagoblin/edit/forms.py:33
+#: mediagoblin/edit/forms.py:31
msgid "Slug"
msgstr "スラグ"
-#: mediagoblin/edit/forms.py:34
+#: mediagoblin/edit/forms.py:32
msgid "The slug can't be empty"
msgstr "スラグは必要です。"
-#: mediagoblin/edit/forms.py:35
+#: mediagoblin/edit/forms.py:33
msgid ""
"The title part of this media's URL. You usually don't need to change this."
msgstr ""
-#: mediagoblin/edit/forms.py:42
+#: mediagoblin/edit/forms.py:40
msgid "Bio"
msgstr "自己紹介"
-#: mediagoblin/edit/forms.py:45
+#: mediagoblin/edit/forms.py:43
msgid "Website"
msgstr "URL"
-#: mediagoblin/edit/views.py:63
+#: mediagoblin/edit/views.py:64
msgid "An entry with that slug already exists for this user."
msgstr "そのスラグを持つエントリは、このユーザーは既に存在します。"
-#: mediagoblin/edit/views.py:84
+#: mediagoblin/edit/views.py:85
msgid "You are editing another user's media. Proceed with caution."
msgstr "あなたは、他のユーザーのメディアを編集しています。ご注意ください。"
-#: mediagoblin/edit/views.py:154
+#: mediagoblin/edit/views.py:155
msgid "You are editing a user's profile. Proceed with caution."
msgstr "あなたは、他のユーザーのプロファイルを編集しています。ご注意ください。"
@@ -128,15 +128,15 @@ msgstr "ファイル"
msgid "Description of this work"
msgstr ""
-#: mediagoblin/submit/views.py:47
+#: mediagoblin/submit/views.py:46
msgid "You must provide a file."
msgstr "ファイルを提供する必要があります。"
-#: mediagoblin/submit/views.py:50
+#: mediagoblin/submit/views.py:49
msgid "The file doesn't seem to be an image!"
msgstr "ファイルが画像ではないようです!"
-#: mediagoblin/submit/views.py:122
+#: mediagoblin/submit/views.py:121
msgid "Woohoo! Submitted!"
msgstr "投稿終了!"
@@ -175,8 +175,8 @@ msgid "verify your email!"
msgstr "メアドを確認してください!"
#: mediagoblin/templates/mediagoblin/base.html:73
-#: mediagoblin/templates/mediagoblin/auth/login.html:26
-#: mediagoblin/templates/mediagoblin/auth/login.html:34
+#: mediagoblin/templates/mediagoblin/auth/login.html:27
+#: mediagoblin/templates/mediagoblin/auth/login.html:35
msgid "Log in"
msgstr "ログイン"
@@ -236,37 +236,30 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:39
#, python-format
msgid ""
-"\n"
-" <a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
" or\n"
-" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>\n"
-" "
+" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Most recent media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/change_fp.html:27
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:29
msgid "Enter your new password"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29
msgid "Enter your username or email"
msgstr ""
#: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22
-msgid ""
-"\n"
-" Your password has been changed. Try to log in now.\n"
-" "
+msgid "Your password has been changed. Try to log in now."
msgstr ""
#: mediagoblin/templates/mediagoblin/auth/fp_email_sent.html:22
msgid ""
-"\n"
-" Check your inbox. We sent an email with a URL for changing your password.\n"
-" "
+"Check your inbox. We sent an email with a URL for changing your password."
msgstr ""
#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19
@@ -283,23 +276,23 @@ msgid ""
"a happy goblin!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/login.html:29
+#: mediagoblin/templates/mediagoblin/auth/login.html:30
msgid "Logging in failed!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/login.html:42
+#: mediagoblin/templates/mediagoblin/auth/login.html:43
msgid "Don't have an account yet?"
msgstr "まだアカウントを持っていませんか?"
-#: mediagoblin/templates/mediagoblin/auth/login.html:45
+#: mediagoblin/templates/mediagoblin/auth/login.html:46
msgid "Create one here!"
msgstr "ここで作成!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:48
+#: mediagoblin/templates/mediagoblin/auth/login.html:49
msgid "Forgot your password?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/login.html:51
+#: mediagoblin/templates/mediagoblin/auth/login.html:52
msgid "Change it!"
msgstr ""
@@ -307,7 +300,7 @@ msgstr ""
msgid "Create an account!"
msgstr "アカウントを作成!"
-#: mediagoblin/templates/mediagoblin/auth/register.html:30
+#: mediagoblin/templates/mediagoblin/auth/register.html:31
msgid "Create"
msgstr ""
@@ -355,7 +348,7 @@ msgstr "タグ付けされたコンテンツ:"
msgid "Submit yer media"
msgstr "コンテンツを投稿"
-#: mediagoblin/templates/mediagoblin/submit/start.html:29
+#: mediagoblin/templates/mediagoblin/submit/start.html:30
msgid "Submit"
msgstr "送信"
@@ -495,7 +488,15 @@ msgstr ""
msgid "I am sure I want to delete this"
msgstr ""
-#: mediagoblin/user_pages/views.py:175
+#: mediagoblin/user_pages/views.py:142
+msgid "Empty comments are not allowed."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:148
+msgid "Comment posted!"
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:181
msgid "You are about to delete another user's media. Proceed with caution."
msgstr ""
diff --git a/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.mo
index 261e5e95..e6d1976b 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 b9e0896d..618daf6f 100644
--- a/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.po
@@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n"
-"POT-Creation-Date: 2011-09-11 16:16-0500\n"
-"PO-Revision-Date: 2011-09-11 21:16+0000\n"
+"POT-Creation-Date: 2011-11-01 23:14-0500\n"
+"PO-Revision-Date: 2011-11-02 04:13+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
@@ -43,19 +43,19 @@ msgstr ""
msgid "Email address"
msgstr "E-mail adres"
-#: mediagoblin/auth/views.py:42
+#: mediagoblin/auth/views.py:55
msgid "Sorry, registration is disabled on this instance."
msgstr "Sorry, registratie is uitgeschakeld op deze instantie."
-#: mediagoblin/auth/views.py:60
+#: mediagoblin/auth/views.py:73
msgid "Sorry, a user with that name already exists."
msgstr "Sorry, er bestaat al een gebruiker met die naam."
-#: mediagoblin/auth/views.py:64
+#: mediagoblin/auth/views.py:77
msgid "Sorry, that email address has already been taken."
msgstr "Sorry, dat e-mailadres is al ingenomen."
-#: mediagoblin/auth/views.py:165
+#: mediagoblin/auth/views.py:179
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
@@ -63,60 +63,60 @@ msgstr ""
"Uw e-mailadres is geverifieerd. U kunt nu inloggen, uw profiel bewerken, en "
"afbeeldingen toevoegen!"
-#: mediagoblin/auth/views.py:171
+#: mediagoblin/auth/views.py:185
msgid "The verification key or user id is incorrect"
msgstr "De verificatie sleutel of gebruikers-ID is onjuist"
-#: mediagoblin/auth/views.py:192
+#: mediagoblin/auth/views.py:207
msgid "Resent your verification email."
msgstr "Verificatie e-mail opnieuw opgestuurd."
-#: mediagoblin/auth/views.py:228
+#: mediagoblin/auth/views.py:248
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr ""
-#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+#: mediagoblin/edit/forms.py:24 mediagoblin/submit/forms.py:27
msgid "Title"
msgstr "Titel"
-#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:32
msgid "Tags"
msgstr "Etiket"
-#: mediagoblin/edit/forms.py:33
+#: mediagoblin/edit/forms.py:31
msgid "Slug"
msgstr ""
-#: mediagoblin/edit/forms.py:34
+#: mediagoblin/edit/forms.py:32
msgid "The slug can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:35
+#: mediagoblin/edit/forms.py:33
msgid ""
"The title part of this media's URL. You usually don't need to change this."
msgstr ""
-#: mediagoblin/edit/forms.py:42
+#: mediagoblin/edit/forms.py:40
msgid "Bio"
msgstr "Bio"
-#: mediagoblin/edit/forms.py:45
+#: mediagoblin/edit/forms.py:43
msgid "Website"
msgstr "Website"
-#: mediagoblin/edit/views.py:63
+#: mediagoblin/edit/views.py:64
msgid "An entry with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:84
+#: mediagoblin/edit/views.py:85
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:154
+#: mediagoblin/edit/views.py:155
msgid "You are editing a user's profile. Proceed with caution."
msgstr ""
"U bent een gebruikersprofiel aan het aanpassen. Ga voorzichtig te werk."
@@ -133,15 +133,15 @@ msgstr "Bestand"
msgid "Description of this work"
msgstr ""
-#: mediagoblin/submit/views.py:47
+#: mediagoblin/submit/views.py:46
msgid "You must provide a file."
msgstr "U moet een bestand aangeven."
-#: mediagoblin/submit/views.py:50
+#: mediagoblin/submit/views.py:49
msgid "The file doesn't seem to be an image!"
msgstr "Het lijkt erop dat dit bestand geen afbeelding is!"
-#: mediagoblin/submit/views.py:122
+#: mediagoblin/submit/views.py:121
msgid "Woohoo! Submitted!"
msgstr "Mooizo! Toegevoegd!"
@@ -180,8 +180,8 @@ msgid "verify your email!"
msgstr "Controleer uw e-mail!"
#: mediagoblin/templates/mediagoblin/base.html:73
-#: mediagoblin/templates/mediagoblin/auth/login.html:26
-#: mediagoblin/templates/mediagoblin/auth/login.html:34
+#: mediagoblin/templates/mediagoblin/auth/login.html:27
+#: mediagoblin/templates/mediagoblin/auth/login.html:35
msgid "Log in"
msgstr "Inloggen"
@@ -241,37 +241,30 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:39
#, python-format
msgid ""
-"\n"
-" <a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
" or\n"
-" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>\n"
-" "
+" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Most recent media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/change_fp.html:27
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:29
msgid "Enter your new password"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29
msgid "Enter your username or email"
msgstr ""
#: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22
-msgid ""
-"\n"
-" Your password has been changed. Try to log in now.\n"
-" "
+msgid "Your password has been changed. Try to log in now."
msgstr ""
#: mediagoblin/templates/mediagoblin/auth/fp_email_sent.html:22
msgid ""
-"\n"
-" Check your inbox. We sent an email with a URL for changing your password.\n"
-" "
+"Check your inbox. We sent an email with a URL for changing your password."
msgstr ""
#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19
@@ -288,23 +281,23 @@ msgid ""
"a happy goblin!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/login.html:29
+#: mediagoblin/templates/mediagoblin/auth/login.html:30
msgid "Logging in failed!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/login.html:42
+#: mediagoblin/templates/mediagoblin/auth/login.html:43
msgid "Don't have an account yet?"
msgstr "Heeft u nog geen account?"
-#: mediagoblin/templates/mediagoblin/auth/login.html:45
+#: mediagoblin/templates/mediagoblin/auth/login.html:46
msgid "Create one here!"
msgstr "Maak er hier een!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:48
+#: mediagoblin/templates/mediagoblin/auth/login.html:49
msgid "Forgot your password?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/login.html:51
+#: mediagoblin/templates/mediagoblin/auth/login.html:52
msgid "Change it!"
msgstr ""
@@ -312,7 +305,7 @@ msgstr ""
msgid "Create an account!"
msgstr "Maak een account aan!"
-#: mediagoblin/templates/mediagoblin/auth/register.html:30
+#: mediagoblin/templates/mediagoblin/auth/register.html:31
msgid "Create"
msgstr ""
@@ -357,7 +350,7 @@ msgstr "Media met het etiket:"
msgid "Submit yer media"
msgstr "Voeg media toe"
-#: mediagoblin/templates/mediagoblin/submit/start.html:29
+#: mediagoblin/templates/mediagoblin/submit/start.html:30
msgid "Submit"
msgstr "Voeg toe"
@@ -501,7 +494,15 @@ msgstr "Commentaar"
msgid "I am sure I want to delete this"
msgstr ""
-#: mediagoblin/user_pages/views.py:175
+#: mediagoblin/user_pages/views.py:142
+msgid "Empty comments are not allowed."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:148
+msgid "Comment posted!"
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:181
msgid "You are about to delete another user's media. 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 9e4cf80f..ba427c29 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 cc0e495a..c74e1dd0 100644
--- a/mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.po
@@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n"
-"POT-Creation-Date: 2011-09-11 16:16-0500\n"
-"PO-Revision-Date: 2011-09-11 21:16+0000\n"
+"POT-Creation-Date: 2011-11-01 23:14-0500\n"
+"PO-Revision-Date: 2011-11-02 04:13+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
@@ -37,86 +37,87 @@ msgstr "Gjenta passord"
#: mediagoblin/auth/forms.py:39
msgid "Type it again here to make sure there are no spelling mistakes."
-msgstr ""
+msgstr "Skriv passordet omatt for å unngå stavefeil."
#: mediagoblin/auth/forms.py:42
msgid "Email address"
-msgstr "E-postadresse"
+msgstr "Epost"
-#: mediagoblin/auth/views.py:42
+#: mediagoblin/auth/views.py:55
msgid "Sorry, registration is disabled on this instance."
msgstr "Registrering er slege av. Orsak."
-#: mediagoblin/auth/views.py:60
+#: mediagoblin/auth/views.py:73
msgid "Sorry, a user with that name already exists."
msgstr "Ein konto med dette brukarnamnet finst allereide."
-#: mediagoblin/auth/views.py:64
+#: mediagoblin/auth/views.py:77
msgid "Sorry, that email address has already been taken."
msgstr "Den epostadressa er allereide teken."
-#: mediagoblin/auth/views.py:165
+#: mediagoblin/auth/views.py:179
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr ""
-"E-postadressa di, og dimed kontoen din er stadfesta. Du kan no logga inn, "
-"endra profilen din og lasta opp filer."
+"Kontoen din er stadfesta. Du kan no logga inn, endra profilen din og lasta "
+"opp filer."
-#: mediagoblin/auth/views.py:171
+#: mediagoblin/auth/views.py:185
msgid "The verification key or user id is incorrect"
msgstr "Stadfestingsnykelen eller brukar-ID-en din er feil."
-#: mediagoblin/auth/views.py:192
+#: mediagoblin/auth/views.py:207
msgid "Resent your verification email."
msgstr "Send ein ny stadfestingsepost."
-#: mediagoblin/auth/views.py:228
+#: mediagoblin/auth/views.py:248
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr ""
+"Kunne ikkje senda epost. Brukarnamnet ditt er inaktivt eller uverifisert."
-#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+#: mediagoblin/edit/forms.py:24 mediagoblin/submit/forms.py:27
msgid "Title"
msgstr "Tittel"
-#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:32
msgid "Tags"
msgstr "Merkelappar"
-#: mediagoblin/edit/forms.py:33
+#: mediagoblin/edit/forms.py:31
msgid "Slug"
-msgstr "Adressetittel"
+msgstr "Nettnamn"
-#: mediagoblin/edit/forms.py:34
+#: mediagoblin/edit/forms.py:32
msgid "The slug can't be empty"
-msgstr "Adressetittelen kan ikkje vera tom"
+msgstr "Nettnamnet kan ikkje vera tomt"
-#: mediagoblin/edit/forms.py:35
+#: mediagoblin/edit/forms.py:33
msgid ""
"The title part of this media's URL. You usually don't need to change this."
-msgstr ""
+msgstr "Nettnamnet (adressetittel) for mediefila di. Trengst ikkje endrast."
-#: mediagoblin/edit/forms.py:42
+#: mediagoblin/edit/forms.py:40
msgid "Bio"
msgstr "Presentasjon"
-#: mediagoblin/edit/forms.py:45
+#: mediagoblin/edit/forms.py:43
msgid "Website"
msgstr "Heimeside"
-#: mediagoblin/edit/views.py:63
+#: mediagoblin/edit/views.py:64
msgid "An entry with that slug already exists for this user."
msgstr "Eit innlegg med denne adressetittelen finst allereie."
-#: mediagoblin/edit/views.py:84
+#: mediagoblin/edit/views.py:85
msgid "You are editing another user's media. Proceed with caution."
-msgstr "Ver forsiktig, du redigerer ein annan konto sitt innlegg."
+msgstr "Trå varsamt, du endrar nokon andre sine mediefiler."
-#: mediagoblin/edit/views.py:154
+#: mediagoblin/edit/views.py:155
msgid "You are editing a user's profile. Proceed with caution."
-msgstr "Ver forsiktig, du redigerer ein annan konto sin profil."
+msgstr "Trå varsamt, du endrar nokon andre sin profil."
#: mediagoblin/process_media/errors.py:44
msgid "Invalid file given for media type."
@@ -128,17 +129,17 @@ msgstr "Fil"
#: mediagoblin/submit/forms.py:30
msgid "Description of this work"
-msgstr ""
+msgstr "Skildring av mediefila"
-#: mediagoblin/submit/views.py:47
+#: mediagoblin/submit/views.py:46
msgid "You must provide a file."
msgstr "Du må velja ei fil."
-#: mediagoblin/submit/views.py:50
+#: mediagoblin/submit/views.py:49
msgid "The file doesn't seem to be an image!"
msgstr "Fila verkar ikkje å vera ei gyldig biletefil."
-#: mediagoblin/submit/views.py:122
+#: mediagoblin/submit/views.py:121
msgid "Woohoo! Submitted!"
msgstr "Johoo! Opplasta!"
@@ -148,18 +149,19 @@ msgstr "Oops."
#: mediagoblin/templates/mediagoblin/404.html:24
msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr "Det ser ikkje ut til å vera noko her..."
+msgstr "Det ser ikkje ut til å vera noko her... Orsak."
#: mediagoblin/templates/mediagoblin/404.html:26
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, så er ho truleg flytta eller sletta."
+"Er du sikker på at adressa er korrekt, so er sida truleg flytta eller "
+"sletta."
#: mediagoblin/templates/mediagoblin/404.html:32
msgid "Image of 404 goblin stressing out"
-msgstr "Bilete av stressa 404-troll."
+msgstr "Bilete av stressa 404-tusse."
#: mediagoblin/templates/mediagoblin/base.html:22
msgid "GNU MediaGoblin"
@@ -178,8 +180,8 @@ msgid "verify your email!"
msgstr "Stadfest epostadressa di"
#: mediagoblin/templates/mediagoblin/base.html:73
-#: mediagoblin/templates/mediagoblin/auth/login.html:26
-#: mediagoblin/templates/mediagoblin/auth/login.html:34
+#: mediagoblin/templates/mediagoblin/auth/login.html:27
+#: mediagoblin/templates/mediagoblin/auth/login.html:35
msgid "Log in"
msgstr "Logg inn"
@@ -188,10 +190,12 @@ 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/root.html:24
msgid "Explore"
-msgstr ""
+msgstr "Utforsk"
#: mediagoblin/templates/mediagoblin/root.html:27
msgid "Hi there, media lover! MediaGoblin is..."
@@ -220,8 +224,9 @@ msgid ""
"Aiming to make the world a better place through decentralization and "
"(eventually, coming soon!) federation!"
msgstr ""
-"Arbeidar for å gjera verda ein betre stad gjennom desentralisering (til "
-"slutt, kjem snart!) federering."
+"Arbeidar for å gjera verda ein betre stad gjennom desentralisering og (til "
+"slutt, kjem snart!) federering, enkelt forklart deling og sending av "
+"mediefiler og kommentarar over fleire nettstader."
#: mediagoblin/templates/mediagoblin/root.html:33
msgid ""
@@ -241,43 +246,42 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:38
msgid "Excited to join us?"
-msgstr ""
+msgstr "Lyst til å bli med oss?"
#: mediagoblin/templates/mediagoblin/root.html:39
#, python-format
msgid ""
-"\n"
-" <a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
" or\n"
-" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>\n"
-" "
+" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
msgstr ""
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Opprett ein "
+"gratis konto</a> eller <a class=\"header_submit\" "
+"href=\"http://wiki.mediagoblin.org/HackingHowto\">installer MediaGoblin på "
+"eigen tenar</a>"
#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Most recent media"
-msgstr ""
+msgstr "Nyaste mediefiler"
-#: mediagoblin/templates/mediagoblin/auth/change_fp.html:27
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:29
msgid "Enter your new password"
-msgstr ""
+msgstr "Fyll inn passord"
-#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29
msgid "Enter your username or email"
-msgstr ""
+msgstr "Fyll inn brukarnamn eller epost"
#: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22
-msgid ""
-"\n"
-" Your password has been changed. Try to log in now.\n"
-" "
-msgstr ""
+msgid "Your password has been changed. Try to log in now."
+msgstr "Passordet endra. Prøv å logga inn no."
#: mediagoblin/templates/mediagoblin/auth/fp_email_sent.html:22
msgid ""
-"\n"
-" Check your inbox. We sent an email with a URL for changing your password.\n"
-" "
+"Check your inbox. We sent an email with a URL for changing your password."
msgstr ""
+"Sjekk innboksen din. Me har sendt deg ein epost med ei netadresse for "
+"passordendring."
#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19
#, python-format
@@ -292,32 +296,39 @@ msgid ""
"If you think this is an error, just ignore this email and continue being\n"
"a happy goblin!"
msgstr ""
+"Hei %(username)s,\n"
+"\n"
+"for å endra MediaGoblin-passordet ditt, opna fylgjande URL i ein netlesar:\n"
+"\n"
+" <%(verification_url)s>\n"
+"\n"
+"Dersom du mistenkjer dette er eit misstak, ignorer eposten og hald fram med å vera ein glad goblin!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:29
+#: mediagoblin/templates/mediagoblin/auth/login.html:30
msgid "Logging in failed!"
msgstr "Innlogging feila"
-#: mediagoblin/templates/mediagoblin/auth/login.html:42
+#: mediagoblin/templates/mediagoblin/auth/login.html:43
msgid "Don't have an account yet?"
msgstr "Har du ingen konto?"
-#: mediagoblin/templates/mediagoblin/auth/login.html:45
+#: mediagoblin/templates/mediagoblin/auth/login.html:46
msgid "Create one here!"
msgstr "Lag ein!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:48
+#: mediagoblin/templates/mediagoblin/auth/login.html:49
msgid "Forgot your password?"
-msgstr ""
+msgstr "Gløymd passordet?"
-#: mediagoblin/templates/mediagoblin/auth/login.html:51
+#: mediagoblin/templates/mediagoblin/auth/login.html:52
msgid "Change it!"
-msgstr ""
+msgstr "Endra"
#: mediagoblin/templates/mediagoblin/auth/register.html:27
msgid "Create an account!"
msgstr "Lag ein konto."
-#: mediagoblin/templates/mediagoblin/auth/register.html:30
+#: mediagoblin/templates/mediagoblin/auth/register.html:31
msgid "Create"
msgstr "Opprett"
@@ -333,19 +344,19 @@ msgid ""
msgstr ""
"Hei %(username)s,\n"
"\n"
-"opna den følgjande adressa i netlesaren din for å aktivera kontoen din:\n"
+"opna fylgjande netadresse i netlesaren din for å aktivera kontoen din:\n"
"\n"
"%(verification_url)s"
#: mediagoblin/templates/mediagoblin/edit/edit.html:29
#, python-format
msgid "Editing %(media_title)s"
-msgstr "Redigerer %(media_title)s"
+msgstr "Endrar %(media_title)s"
#: mediagoblin/templates/mediagoblin/edit/edit.html:36
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
msgid "Cancel"
-msgstr "Avbryt"
+msgstr "Bryt av"
#: mediagoblin/templates/mediagoblin/edit/edit.html:37
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
@@ -355,7 +366,7 @@ msgstr "Lagra"
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:29
#, python-format
msgid "Editing %(username)s's profile"
-msgstr "Redigerar profilen til %(username)s"
+msgstr "Endrar profilen til %(username)s"
#: mediagoblin/templates/mediagoblin/listings/tag.html:31
msgid "Media tagged with:"
@@ -365,14 +376,14 @@ msgstr "Merkelappar:"
msgid "Submit yer media"
msgstr "Last opp"
-#: mediagoblin/templates/mediagoblin/submit/start.html:29
+#: mediagoblin/templates/mediagoblin/submit/start.html:30
msgid "Submit"
msgstr "Send"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32
#, python-format
msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media"
-msgstr "<a href=\"%(user_url)s\">%(username)s</a> sin mediafiler"
+msgstr "<a href=\"%(user_url)s\">%(username)s</a> sine mediefiler"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52
#: mediagoblin/templates/mediagoblin/user_pages/user.html:32
@@ -382,11 +393,11 @@ msgstr "Fann ingen slik brukar"
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
msgid "Really delete %(title)s?"
-msgstr ""
+msgstr "Vil du verkeleg sletta %(title)s?"
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
msgid "Delete Permanently"
-msgstr ""
+msgstr "Slett permament"
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:22
msgid "Media processing panel"
@@ -407,7 +418,7 @@ msgstr "Ingen media under handsaming"
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:50
msgid "These uploads failed to process:"
-msgstr "Klarte ikkje handsame desse opplasta filene:"
+msgstr "Klarte ikkje handsama desse opplasta filene:"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:39
#: mediagoblin/templates/mediagoblin/user_pages/user.html:59
@@ -467,21 +478,21 @@ msgstr "Brukaren har ikkje fylt ut profilen sin (enno)."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:122
#, python-format
msgid "View all of %(username)s's media"
-msgstr "Sjå all media frå %(username)s"
+msgstr "Sjå alle %(username)s sine mediefiler"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:135
msgid ""
"This is where your media will appear, but you don't seem to have added "
"anything yet."
-msgstr "Her kjem mediet ditt. Ser ikkje ut til at du har lagt til noko."
+msgstr "Her kjem mediefilene dine. Ser ikkje ut til at du har lagt til noko."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:141
msgid "Add media"
-msgstr "Legg til media"
+msgstr "Legg til mediefiler"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:147
msgid "There doesn't seem to be any media here yet..."
-msgstr "Ser ikkje ut til at det finst noko media her nett no."
+msgstr "Ser ikkje ut til at det finst nokon mediefiler her nett no."
#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
msgid "feed icon"
@@ -493,11 +504,11 @@ msgstr "Atom-kjelde"
#: mediagoblin/templates/mediagoblin/utils/pagination.html:40
msgid "Newer"
-msgstr ""
+msgstr "Nyare"
#: mediagoblin/templates/mediagoblin/utils/pagination.html:46
msgid "Older"
-msgstr ""
+msgstr "Eldre"
#: mediagoblin/user_pages/forms.py:24
msgid "Comment"
@@ -505,10 +516,19 @@ msgstr "Innspel"
#: mediagoblin/user_pages/forms.py:30
msgid "I am sure I want to delete this"
+msgstr "Eg er sikker eg vil sletta dette"
+
+#: mediagoblin/user_pages/views.py:142
+msgid "Empty comments are not allowed."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:148
+msgid "Comment posted!"
msgstr ""
-#: mediagoblin/user_pages/views.py:175
+#: mediagoblin/user_pages/views.py:181
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."
diff --git a/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.mo
index 686989fc..31cb860c 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 02054003..047e598b 100644
--- a/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.po
@@ -4,12 +4,13 @@
#
# Translators:
# <snd.noise@gmail.com>, 2011.
+# ufa <ufa@technotroll.org>, 2011.
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n"
-"POT-Creation-Date: 2011-09-11 16:16-0500\n"
-"PO-Revision-Date: 2011-09-11 21:16+0000\n"
+"POT-Creation-Date: 2011-11-01 23:14-0500\n"
+"PO-Revision-Date: 2011-11-02 04:13+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: Portuguese (Brazilian) (http://www.transifex.net/projects/p/mediagoblin/team/pt_BR/)\n"
"MIME-Version: 1.0\n"
@@ -38,24 +39,25 @@ msgstr "Confirmar senha"
#: mediagoblin/auth/forms.py:39
msgid "Type it again here to make sure there are no spelling mistakes."
msgstr ""
+"Digite novamente aqui para ter certeza que não houve erros de digitação"
#: mediagoblin/auth/forms.py:42
msgid "Email address"
msgstr "Endereço de email"
-#: mediagoblin/auth/views.py:42
+#: mediagoblin/auth/views.py:55
msgid "Sorry, registration is disabled on this instance."
msgstr "Desculpa, o registro está desativado neste momento."
-#: mediagoblin/auth/views.py:60
+#: mediagoblin/auth/views.py:73
msgid "Sorry, a user with that name already exists."
msgstr "Desculpe, um usuário com este nome já existe."
-#: mediagoblin/auth/views.py:64
+#: mediagoblin/auth/views.py:77
msgid "Sorry, that email address has already been taken."
-msgstr ""
+msgstr "Desculpe, esse endereço de email já está em uso."
-#: mediagoblin/auth/views.py:165
+#: mediagoblin/auth/views.py:179
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
@@ -63,64 +65,67 @@ msgstr ""
"O seu endereço de e-mail foi verificado. Você pode agora fazer login, editar"
" seu perfil, e enviar imagens!"
-#: mediagoblin/auth/views.py:171
+#: mediagoblin/auth/views.py:185
msgid "The verification key or user id is incorrect"
msgstr "A chave de verificação ou nome usuário estão incorretos."
-#: mediagoblin/auth/views.py:192
+#: mediagoblin/auth/views.py:207
msgid "Resent your verification email."
msgstr "O email de verificação foi reenviado."
-#: mediagoblin/auth/views.py:228
+#: mediagoblin/auth/views.py:248
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr ""
+"Não foi possível enviar o email de recuperação de senha, pois seu nome de "
+"usuário está inativo ou o email da sua conta não foi confirmado."
-#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+#: mediagoblin/edit/forms.py:24 mediagoblin/submit/forms.py:27
msgid "Title"
msgstr "Título"
-#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:32
msgid "Tags"
-msgstr "Tags"
+msgstr "Etiquetas"
-#: mediagoblin/edit/forms.py:33
+#: mediagoblin/edit/forms.py:31
msgid "Slug"
-msgstr ""
+msgstr "Arquivo"
-#: mediagoblin/edit/forms.py:34
+#: mediagoblin/edit/forms.py:32
msgid "The slug can't be empty"
-msgstr ""
+msgstr "O arquivo não pode estar vazio"
-#: mediagoblin/edit/forms.py:35
+#: mediagoblin/edit/forms.py:33
msgid ""
"The title part of this media's URL. You usually don't need to change this."
msgstr ""
+"A parte título da URL dessa mídia. Geralmente não é necessário alterar isso."
-#: mediagoblin/edit/forms.py:42
+#: mediagoblin/edit/forms.py:40
msgid "Bio"
-msgstr "Biográfia"
+msgstr "Biografia"
-#: mediagoblin/edit/forms.py:45
+#: mediagoblin/edit/forms.py:43
msgid "Website"
msgstr "Website"
-#: mediagoblin/edit/views.py:63
+#: mediagoblin/edit/views.py:64
msgid "An entry with that slug already exists for this user."
-msgstr ""
+msgstr "Uma entrada com esse arquivo já existe para esse usuário"
-#: mediagoblin/edit/views.py:84
+#: mediagoblin/edit/views.py:85
msgid "You are editing another user's media. Proceed with caution."
-msgstr ""
+msgstr "Você está editando a mídia de outro usuário. Tenha cuidado."
-#: mediagoblin/edit/views.py:154
+#: mediagoblin/edit/views.py:155
msgid "You are editing a user's profile. Proceed with caution."
-msgstr ""
+msgstr "Você está editando um perfil de usuário. Tenha cuidado."
#: mediagoblin/process_media/errors.py:44
msgid "Invalid file given for media type."
-msgstr ""
+msgstr "Arquivo inválido para esse tipo de mídia"
#: mediagoblin/submit/forms.py:25
msgid "File"
@@ -128,37 +133,39 @@ msgstr "Arquivo"
#: mediagoblin/submit/forms.py:30
msgid "Description of this work"
-msgstr ""
+msgstr "Descrição desse trabalho"
-#: mediagoblin/submit/views.py:47
+#: mediagoblin/submit/views.py:46
msgid "You must provide a file."
msgstr "Você deve fornecer um arquivo."
-#: mediagoblin/submit/views.py:50
+#: mediagoblin/submit/views.py:49
msgid "The file doesn't seem to be an image!"
msgstr "O arquivo não parece ser uma imagem!"
-#: mediagoblin/submit/views.py:122
+#: mediagoblin/submit/views.py:121
msgid "Woohoo! Submitted!"
msgstr "Eba! Enviado!"
#: mediagoblin/templates/mediagoblin/404.html:21
msgid "Oops!"
-msgstr ""
+msgstr "Oops"
#: mediagoblin/templates/mediagoblin/404.html:24
msgid "There doesn't seem to be a page at this address. Sorry!"
-msgstr ""
+msgstr "Aparentemente não existe uma página com esse endereço. Desculpe!"
#: mediagoblin/templates/mediagoblin/404.html:26
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/404.html:32
msgid "Image of 404 goblin stressing out"
-msgstr ""
+msgstr "Imagem do goblin 404 aparecendo"
#: mediagoblin/templates/mediagoblin/base.html:22
msgid "GNU MediaGoblin"
@@ -166,7 +173,7 @@ msgstr "GNU MediaGoblin"
#: mediagoblin/templates/mediagoblin/base.html:47
msgid "MediaGoblin logo"
-msgstr ""
+msgstr "Logo MediaGoblin"
#: mediagoblin/templates/mediagoblin/base.html:52
msgid "Submit media"
@@ -177,8 +184,8 @@ msgid "verify your email!"
msgstr "Verifique seu email!"
#: mediagoblin/templates/mediagoblin/base.html:73
-#: mediagoblin/templates/mediagoblin/auth/login.html:26
-#: mediagoblin/templates/mediagoblin/auth/login.html:34
+#: mediagoblin/templates/mediagoblin/auth/login.html:27
+#: mediagoblin/templates/mediagoblin/auth/login.html:35
msgid "Log in"
msgstr "Entrar"
@@ -187,42 +194,52 @@ msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU</a> project"
msgstr ""
+"Desenvolvido por <a href=\"http://mediagoblin.org\">MediaGoblin</a>, um "
+"projeto <a href=\"http://gnu.org/\">GNU</a>"
#: mediagoblin/templates/mediagoblin/root.html:24
msgid "Explore"
-msgstr ""
+msgstr "Explorar"
#: mediagoblin/templates/mediagoblin/root.html:27
msgid "Hi there, media lover! MediaGoblin is..."
-msgstr ""
+msgstr "Olá amante de mídias. MediaGoblin é..."
#: mediagoblin/templates/mediagoblin/root.html:29
msgid "The perfect place for your media!"
-msgstr ""
+msgstr "O lugar perfeito para sua mídia!"
#: mediagoblin/templates/mediagoblin/root.html:30
msgid ""
"A place for people to collaborate and show off original and derived "
"creations!"
msgstr ""
+"Um lugar para as pessoas colaborarem e mostrarem suas criações originais e "
+"derivadas!"
#: mediagoblin/templates/mediagoblin/root.html:31
msgid ""
"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project, "
"after all.)"
msgstr ""
+"Livre como a liberdade. (Afinal, somos um projeto <a "
+"href=\"http://gnu.org\">GNU</a>)"
#: mediagoblin/templates/mediagoblin/root.html:32
msgid ""
"Aiming to make the world a better place through decentralization and "
"(eventually, coming soon!) federation!"
msgstr ""
+"Com o objetivo de fazer um mundo melhor através da descentralização e "
+"(eventualmente, em breve) federação!"
#: mediagoblin/templates/mediagoblin/root.html:33
msgid ""
"Built for extensibility. (Multiple media types coming soon to the software,"
" including video support!)"
msgstr ""
+"Construído para extensibilidade. (Múltiplos tipos de mídia em breve, "
+"incluindo suporte a vídeo) "
#: mediagoblin/templates/mediagoblin/root.html:34
msgid ""
@@ -230,46 +247,47 @@ msgid ""
"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve this"
" software!</a>)"
msgstr ""
+"Desenvolvido por pessoas como você. (<a "
+"href=\"http://mediagoblin.org/pages/join.html\">Você pode ajudar a melhorar "
+"esse software</a>)"
#: mediagoblin/templates/mediagoblin/root.html:38
msgid "Excited to join us?"
-msgstr ""
+msgstr "Animado para juntar-se a nós?"
#: mediagoblin/templates/mediagoblin/root.html:39
#, python-format
msgid ""
-"\n"
-" <a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
" or\n"
-" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>\n"
-" "
+" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
msgstr ""
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\"> Crie uma conta grátis </a>\n"
+" ou <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Configure seu próprio servidor MediaGoblin</a>\n"
+" "
#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Most recent media"
-msgstr ""
+msgstr "Mídia mais recente"
-#: mediagoblin/templates/mediagoblin/auth/change_fp.html:27
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:29
msgid "Enter your new password"
-msgstr ""
+msgstr "Digite sua nova senha"
-#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29
msgid "Enter your username or email"
-msgstr ""
+msgstr "Digite seu nome de usuário ou email"
#: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22
-msgid ""
-"\n"
-" Your password has been changed. Try to log in now.\n"
-" "
-msgstr ""
+msgid "Your password has been changed. Try to log in now."
+msgstr "Sua senha foi alterada. Tente entrar agora."
#: mediagoblin/templates/mediagoblin/auth/fp_email_sent.html:22
msgid ""
-"\n"
-" Check your inbox. We sent an email with a URL for changing your password.\n"
-" "
+"Check your inbox. We sent an email with a URL for changing your password."
msgstr ""
+"Verifique sua caixa de entrada. Mandamos um email com a URL para troca da "
+"senha"
#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19
#, python-format
@@ -284,34 +302,42 @@ msgid ""
"If you think this is an error, just ignore this email and continue being\n"
"a happy goblin!"
msgstr ""
+"Olá %(username)s,\n"
+"\n"
+"para alterar sua senha do GNU MediaGoblin, abra a seguinte URL\n"
+"no seu navegador web:\n"
+"\n"
+"%(verification_url)s\n"
+"\n"
+"Se você acha que isso é um erro, desconsidere esse email e continue sendo um goblin feliz"
-#: mediagoblin/templates/mediagoblin/auth/login.html:29
+#: mediagoblin/templates/mediagoblin/auth/login.html:30
msgid "Logging in failed!"
-msgstr ""
+msgstr "Autenticação falhou"
-#: mediagoblin/templates/mediagoblin/auth/login.html:42
+#: mediagoblin/templates/mediagoblin/auth/login.html:43
msgid "Don't have an account yet?"
msgstr "Ainda não tem conta?"
-#: mediagoblin/templates/mediagoblin/auth/login.html:45
+#: mediagoblin/templates/mediagoblin/auth/login.html:46
msgid "Create one here!"
msgstr "Crie uma aqui!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:48
+#: mediagoblin/templates/mediagoblin/auth/login.html:49
msgid "Forgot your password?"
-msgstr ""
+msgstr "Esqueceu sua senha?"
-#: mediagoblin/templates/mediagoblin/auth/login.html:51
+#: mediagoblin/templates/mediagoblin/auth/login.html:52
msgid "Change it!"
-msgstr ""
+msgstr "Altere-a"
#: mediagoblin/templates/mediagoblin/auth/register.html:27
msgid "Create an account!"
msgstr "Criar uma conta!"
-#: mediagoblin/templates/mediagoblin/auth/register.html:30
+#: mediagoblin/templates/mediagoblin/auth/register.html:31
msgid "Create"
-msgstr ""
+msgstr "Criar"
#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19
#, python-format
@@ -351,69 +377,70 @@ msgstr "Editando perfil de %(username)s"
#: mediagoblin/templates/mediagoblin/listings/tag.html:31
msgid "Media tagged with:"
-msgstr ""
+msgstr "Mídia marcada como:"
#: mediagoblin/templates/mediagoblin/submit/start.html:26
msgid "Submit yer media"
msgstr "Envie sua mídia"
-#: mediagoblin/templates/mediagoblin/submit/start.html:29
+#: mediagoblin/templates/mediagoblin/submit/start.html:30
msgid "Submit"
msgstr "Enviar"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32
#, python-format
msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media"
-msgstr ""
+msgstr "Mídia de <a href=\"%(user_url)s\"> %(username)s </a> "
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52
#: mediagoblin/templates/mediagoblin/user_pages/user.html:32
msgid "Sorry, no such user found."
-msgstr "Desculpe, tal usuário não encontrado."
+msgstr "Desculpe, esse usuário não foi encontrado."
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
msgid "Really delete %(title)s?"
-msgstr ""
+msgstr "Realmente apagar %(title)s ?"
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
msgid "Delete Permanently"
-msgstr ""
+msgstr "Apagar permanentemente"
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:22
msgid "Media processing panel"
-msgstr ""
+msgstr "Painel de processamento de mídia"
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:25
msgid ""
"You can track the state of media being processed for your gallery here."
msgstr ""
+"Você pode verificar como a mídia esta sendo processada para sua galeria aqui"
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:28
msgid "Media in-processing"
-msgstr ""
+msgstr "Mídia em processo"
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:46
msgid "No media in-processing"
-msgstr ""
+msgstr "Nenhuma mídia em processo"
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:50
msgid "These uploads failed to process:"
-msgstr ""
+msgstr "Esses envios não foram processados:"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:39
#: mediagoblin/templates/mediagoblin/user_pages/user.html:59
msgid "Email verification needed"
-msgstr ""
+msgstr "Verificação de email necessária"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:42
msgid "Almost done! Your account still needs to be activated."
-msgstr ""
+msgstr "Quase pronto! Sua conta ainda precisa ser ativada"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:47
msgid ""
"An email should arrive in a few moments with instructions on how to do so."
-msgstr "Receberá um email com instruções de como fazer."
+msgstr "Um email deve chegar em instantes com instruções de como fazê-lo."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:51
msgid "In case it doesn't:"
@@ -428,6 +455,8 @@ msgid ""
"Someone has registered an account with this username, but it still has to be"
" activated."
msgstr ""
+"Alguém registrou uma conta com esse nome de usuário, mas ainda precisa ser "
+"ativada."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:68
#, python-format
@@ -445,7 +474,7 @@ msgstr "Perfil de %(username)s"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:85
msgid "Here's a spot to tell others about yourself."
-msgstr ""
+msgstr "Aqui é o lugar onde você fala de si para os outros."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:90
#: mediagoblin/templates/mediagoblin/user_pages/user.html:108
@@ -454,53 +483,63 @@ msgstr "Editar perfil"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:96
msgid "This user hasn't filled in their profile (yet)."
-msgstr ""
+msgstr "Esse usuário não preencheu seu perfil (ainda)."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:122
#, python-format
msgid "View all of %(username)s's media"
-msgstr ""
+msgstr "Ver todas as mídias de %(username)s"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:135
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:141
msgid "Add media"
-msgstr ""
+msgstr "Adicionar mídia"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:147
msgid "There doesn't seem to be any media here yet..."
-msgstr ""
+msgstr "Aparentemente não há nenhuma mídia aqui ainda..."
#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
msgid "feed icon"
-msgstr ""
+msgstr "ícone feed"
#: mediagoblin/templates/mediagoblin/utils/feed_link.html:23
msgid "Atom feed"
-msgstr ""
+msgstr "Atom feed"
#: mediagoblin/templates/mediagoblin/utils/pagination.html:40
msgid "Newer"
-msgstr ""
+msgstr "Mais novo"
#: mediagoblin/templates/mediagoblin/utils/pagination.html:46
msgid "Older"
-msgstr ""
+msgstr "Mais velho"
#: mediagoblin/user_pages/forms.py:24
msgid "Comment"
-msgstr ""
+msgstr "Comentário"
#: mediagoblin/user_pages/forms.py:30
msgid "I am sure I want to delete this"
+msgstr "Eu tenho certeza de que quero pagar isso"
+
+#: mediagoblin/user_pages/views.py:142
+msgid "Empty comments are not allowed."
msgstr ""
-#: mediagoblin/user_pages/views.py:175
-msgid "You are about to delete another user's media. Proceed with caution."
+#: mediagoblin/user_pages/views.py:148
+msgid "Comment posted!"
msgstr ""
+#: mediagoblin/user_pages/views.py:181
+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."
+
diff --git a/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.mo
index 994d6f30..2ab9cf8b 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 967f7dbb..01fe5c48 100644
--- a/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.po
@@ -8,9 +8,9 @@ msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n"
-"POT-Creation-Date: 2011-09-11 16:16-0500\n"
-"PO-Revision-Date: 2011-09-11 21:16+0000\n"
-"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
+"POT-Creation-Date: 2011-11-01 23:14-0500\n"
+"PO-Revision-Date: 2011-11-02 20:49+0000\n"
+"Last-Translator: gap <gapop@hotmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -43,19 +43,19 @@ msgstr "Introdu parola din nou pentru verificare."
msgid "Email address"
msgstr "Adresa de e-mail"
-#: mediagoblin/auth/views.py:42
+#: mediagoblin/auth/views.py:55
msgid "Sorry, registration is disabled on this instance."
-msgstr "Ne pare rău, dar înscrierile sunt dezactivate pe această instanță."
+msgstr "Ne pare rău, dar înscrierile sunt dezactivate pe acest server."
-#: mediagoblin/auth/views.py:60
+#: mediagoblin/auth/views.py:73
msgid "Sorry, a user with that name already exists."
msgstr "Ne pare rău, există deja un utilizator cu același nume."
-#: mediagoblin/auth/views.py:64
+#: mediagoblin/auth/views.py:77
msgid "Sorry, that email address has already been taken."
msgstr "Ne pare rău, această adresă de e-mail este deja rezervată."
-#: mediagoblin/auth/views.py:165
+#: mediagoblin/auth/views.py:179
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
@@ -63,61 +63,63 @@ msgstr ""
"Adresa ta de e-mail a fost confirmată. Poți să te autentifici, să îți "
"completezi profilul și să trimiți imagini!"
-#: mediagoblin/auth/views.py:171
+#: mediagoblin/auth/views.py:185
msgid "The verification key or user id is incorrect"
msgstr "Cheie de verificare sau user ID incorect."
-#: mediagoblin/auth/views.py:192
+#: mediagoblin/auth/views.py:207
msgid "Resent your verification email."
msgstr "E-mail-ul de verificare a fost retrimis."
-#: mediagoblin/auth/views.py:228
+#: mediagoblin/auth/views.py:248
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr ""
+"E-mailul pentru recuperarea parolei nu a putut fi trimis deoarece contul tău"
+" e inactiv sau adresa ta de e-mail nu a fost confirmată."
-#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+#: mediagoblin/edit/forms.py:24 mediagoblin/submit/forms.py:27
msgid "Title"
msgstr "Titlu"
-#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:32
msgid "Tags"
msgstr "Etichete"
-#: mediagoblin/edit/forms.py:33
+#: mediagoblin/edit/forms.py:31
msgid "Slug"
msgstr "Identificator"
-#: mediagoblin/edit/forms.py:34
+#: mediagoblin/edit/forms.py:32
msgid "The slug can't be empty"
msgstr "Identificatorul nu poate să lipsească"
-#: mediagoblin/edit/forms.py:35
+#: mediagoblin/edit/forms.py:33
msgid ""
"The title part of this media's URL. You usually don't need to change this."
msgstr ""
"Partea din adresa acestui fișier corespunzătoare titlului. De regulă nu "
"trebuie modificată."
-#: mediagoblin/edit/forms.py:42
+#: mediagoblin/edit/forms.py:40
msgid "Bio"
msgstr "Biografie"
-#: mediagoblin/edit/forms.py:45
+#: mediagoblin/edit/forms.py:43
msgid "Website"
msgstr "Sit Web"
-#: mediagoblin/edit/views.py:63
+#: mediagoblin/edit/views.py:64
msgid "An entry with that slug already exists for this user."
msgstr ""
"Există deja un entry cu același identificator pentru acest utilizator."
-#: mediagoblin/edit/views.py:84
+#: mediagoblin/edit/views.py:85
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:154
+#: mediagoblin/edit/views.py:155
msgid "You are editing a user's profile. Proceed with caution."
msgstr "Editezi profilul unui utilizator. Se recomandă prudență."
@@ -133,15 +135,15 @@ msgstr "Fișier"
msgid "Description of this work"
msgstr "Descrierea acestui fișier"
-#: mediagoblin/submit/views.py:47
+#: mediagoblin/submit/views.py:46
msgid "You must provide a file."
msgstr "Trebuie să selectezi un fișier."
-#: mediagoblin/submit/views.py:50
+#: mediagoblin/submit/views.py:49
msgid "The file doesn't seem to be an image!"
msgstr "Fișierul nu pare a fi o imagine!"
-#: mediagoblin/submit/views.py:122
+#: mediagoblin/submit/views.py:121
msgid "Woohoo! Submitted!"
msgstr "Gata, trimis!"
@@ -158,8 +160,8 @@ 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 este corectă, poate că pagina pe care o cauți a "
-"fost mutată sau ștearsă."
+"Dacă ești sigur că adresa e corectă, poate că pagina pe care o cauți a fost "
+"mutată sau ștearsă."
#: mediagoblin/templates/mediagoblin/404.html:32
msgid "Image of 404 goblin stressing out"
@@ -182,8 +184,8 @@ msgid "verify your email!"
msgstr "verifică e-mail-ul!"
#: mediagoblin/templates/mediagoblin/base.html:73
-#: mediagoblin/templates/mediagoblin/auth/login.html:26
-#: mediagoblin/templates/mediagoblin/auth/login.html:34
+#: mediagoblin/templates/mediagoblin/auth/login.html:27
+#: mediagoblin/templates/mediagoblin/auth/login.html:35
msgid "Log in"
msgstr "Autentificare"
@@ -197,7 +199,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:24
msgid "Explore"
-msgstr ""
+msgstr "Explorează"
#: mediagoblin/templates/mediagoblin/root.html:27
msgid "Hi there, media lover! MediaGoblin is..."
@@ -250,43 +252,41 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:38
msgid "Excited to join us?"
-msgstr ""
+msgstr "Vrei să ni te alături?"
#: mediagoblin/templates/mediagoblin/root.html:39
#, python-format
msgid ""
-"\n"
-" <a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
" or\n"
-" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>\n"
-" "
+" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
msgstr ""
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Creează gratuit un cont</a>\n"
+" sau\n"
+" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">instalează MediaGoblin pe serverul tău</a>"
#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Most recent media"
-msgstr ""
+msgstr "Cele mai recente fișiere"
-#: mediagoblin/templates/mediagoblin/auth/change_fp.html:27
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:29
msgid "Enter your new password"
-msgstr ""
+msgstr "Introdu noua parolă"
-#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29
msgid "Enter your username or email"
-msgstr ""
+msgstr "Introdu numele de utilizator sau adresa de e-mail"
#: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22
-msgid ""
-"\n"
-" Your password has been changed. Try to log in now.\n"
-" "
-msgstr ""
+msgid "Your password has been changed. Try to log in now."
+msgstr "Parola a fost schimbată. Încearcă să te autentifici acum."
#: mediagoblin/templates/mediagoblin/auth/fp_email_sent.html:22
msgid ""
-"\n"
-" Check your inbox. We sent an email with a URL for changing your password.\n"
-" "
+"Check your inbox. We sent an email with a URL for changing your password."
msgstr ""
+"Verifică-ți căsuța de e-mail. Ți-am trimis un mesaj cu link-ul pentru "
+"schimbarea parolei."
#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19
#, python-format
@@ -301,32 +301,39 @@ msgid ""
"If you think this is an error, just ignore this email and continue being\n"
"a happy goblin!"
msgstr ""
+"Bună, %(username)s\n"
+"\n"
+"Pentru a schimba parola ta la GNU MediaGoblin, accesează adresa următoare:\n"
+"\n"
+"%(verification_url)s\n"
+"\n"
+"Dacă ai primit acest mesaj din greșeală, ignoră-l și fii mai departe un elf fericit!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:29
+#: mediagoblin/templates/mediagoblin/auth/login.html:30
msgid "Logging in failed!"
msgstr "Autentificare eșuată!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:42
+#: mediagoblin/templates/mediagoblin/auth/login.html:43
msgid "Don't have an account yet?"
msgstr "Nu ai un cont?"
-#: mediagoblin/templates/mediagoblin/auth/login.html:45
+#: mediagoblin/templates/mediagoblin/auth/login.html:46
msgid "Create one here!"
msgstr "Creează-l aici!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:48
+#: mediagoblin/templates/mediagoblin/auth/login.html:49
msgid "Forgot your password?"
-msgstr ""
+msgstr "Ai uitat parola?"
-#: mediagoblin/templates/mediagoblin/auth/login.html:51
+#: mediagoblin/templates/mediagoblin/auth/login.html:52
msgid "Change it!"
-msgstr ""
+msgstr "Schimb-o!"
#: mediagoblin/templates/mediagoblin/auth/register.html:27
msgid "Create an account!"
msgstr "Creează un cont!"
-#: mediagoblin/templates/mediagoblin/auth/register.html:30
+#: mediagoblin/templates/mediagoblin/auth/register.html:31
msgid "Create"
msgstr "Creează"
@@ -342,7 +349,7 @@ msgid ""
msgstr ""
"Bună, %(username)s,\n"
"\n"
-"pentru activarea contului tău GNU MediaGoblin, accesează adresa următoare:\n"
+"pentru activarea contului tău la GNU MediaGoblin, accesează adresa următoare:\n"
"\n"
"%(verification_url)s"
@@ -374,7 +381,7 @@ msgstr "Etichete:"
msgid "Submit yer media"
msgstr "Trimite fișierele tale media"
-#: mediagoblin/templates/mediagoblin/submit/start.html:29
+#: mediagoblin/templates/mediagoblin/submit/start.html:30
msgid "Submit"
msgstr "Trimite"
@@ -421,7 +428,7 @@ msgstr "Aceste fișiere nu au putut fi procesate:"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:39
#: mediagoblin/templates/mediagoblin/user_pages/user.html:59
msgid "Email verification needed"
-msgstr "Este necesară verificarea adresei de e-mail"
+msgstr "Este necesară confirmarea adresei de e-mail"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:42
msgid "Almost done! Your account still needs to be activated."
@@ -430,11 +437,11 @@ msgstr "Aproape gata! Mai trebuie doar să activezi contul."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:47
msgid ""
"An email should arrive in a few moments with instructions on how to do so."
-msgstr "Vei primi în scurt timp un mesaj prin e-mail cu instrucțiuni."
+msgstr "Vei primi în scurt timp un e-mail cu instrucțiuni."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:51
msgid "In case it doesn't:"
-msgstr "Dacă nu primești mesajul:"
+msgstr "Dacă nu-l primești:"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:54
msgid "Resend verification email"
@@ -478,7 +485,7 @@ msgstr "Acest utilizator nu și-a completat (încă) profilul."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:122
#, python-format
msgid "View all of %(username)s's media"
-msgstr "Toate fișierele media ale lui %(username)s"
+msgstr "Vezi toate fișierele media ale lui %(username)s"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:135
msgid ""
@@ -520,7 +527,15 @@ msgstr "Scrie un comentariu"
msgid "I am sure I want to delete this"
msgstr "Sunt sigur că doresc să șterg"
-#: mediagoblin/user_pages/views.py:175
+#: mediagoblin/user_pages/views.py:142
+msgid "Empty comments are not allowed."
+msgstr "Comentariul trebuie să aibă un conținut."
+
+#: mediagoblin/user_pages/views.py:148
+msgid "Comment posted!"
+msgstr "Comentariul a fost transmis."
+
+#: mediagoblin/user_pages/views.py:181
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ă "
diff --git a/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.mo
index 2b698e4d..4b5481e0 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 865f5424..f4bfbd67 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://bugs.foocorp.net/projects/mediagoblin/issues\n"
-"POT-Creation-Date: 2011-09-11 16:16-0500\n"
-"PO-Revision-Date: 2011-09-11 21:16+0000\n"
-"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
+"POT-Creation-Date: 2011-11-01 23:14-0500\n"
+"PO-Revision-Date: 2011-11-04 11:13+0000\n"
+"Last-Translator: aleksejrs <deletesoftware@yandex.ru>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -37,25 +37,25 @@ msgstr "Подтвердите пароль"
#: mediagoblin/auth/forms.py:39
msgid "Type it again here to make sure there are no spelling mistakes."
-msgstr "Type it again here to make sure there are no spelling mistakes."
+msgstr "Наберите его ещё раз здесь, чтобы избежать опечаток."
#: mediagoblin/auth/forms.py:42
msgid "Email address"
msgstr "Адрес электронной почты"
-#: mediagoblin/auth/views.py:42
+#: mediagoblin/auth/views.py:55
msgid "Sorry, registration is disabled on this instance."
msgstr "Извините, на этом разделе регистрация запрещена."
-#: mediagoblin/auth/views.py:60
+#: mediagoblin/auth/views.py:73
msgid "Sorry, a user with that name already exists."
msgstr "Извините, пользователь с этим именем уже зарегистрирован."
-#: mediagoblin/auth/views.py:64
+#: mediagoblin/auth/views.py:77
msgid "Sorry, that email address has already been taken."
-msgstr "Извините, этот адрес электнонной почты уже занят."
+msgstr "Извините, этот адрес электронной почты уже занят."
-#: mediagoblin/auth/views.py:165
+#: mediagoblin/auth/views.py:179
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
@@ -63,61 +63,64 @@ msgstr ""
"Адрес вашей электронной потвержден. Вы теперь можете войти и начать "
"редактировать свой профиль и загружать новые изображения!"
-#: mediagoblin/auth/views.py:171
+#: mediagoblin/auth/views.py:185
msgid "The verification key or user id is incorrect"
msgstr "Неверный ключ проверки или идентификатор пользователя"
-#: mediagoblin/auth/views.py:192
+#: mediagoblin/auth/views.py:207
msgid "Resent your verification email."
msgstr "Переслать сообщение с подтверждением аккаунта."
-#: mediagoblin/auth/views.py:228
+#: mediagoblin/auth/views.py:248
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr ""
+"Мы не можем отправить сообщение для восстановления пароля, потому что ваша "
+"учётная запись неактивна, либо указанный в ней адрес электронной почты не "
+"был подтверждён."
-#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+#: mediagoblin/edit/forms.py:24 mediagoblin/submit/forms.py:27
msgid "Title"
msgstr "Название"
-#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:32
msgid "Tags"
msgstr "Метки"
-#: mediagoblin/edit/forms.py:33
+#: mediagoblin/edit/forms.py:31
msgid "Slug"
msgstr "Отличительная часть адреса"
-#: mediagoblin/edit/forms.py:34
+#: mediagoblin/edit/forms.py:32
msgid "The slug can't be empty"
msgstr "Отличительная часть адреса необходима"
-#: mediagoblin/edit/forms.py:35
+#: mediagoblin/edit/forms.py:33
msgid ""
"The title part of this media's URL. You usually don't need to change this."
msgstr ""
"Часть адреса этого файла, производная от его названия. Её обычно не нужно "
"изменять."
-#: mediagoblin/edit/forms.py:42
+#: mediagoblin/edit/forms.py:40
msgid "Bio"
msgstr "Биография"
-#: mediagoblin/edit/forms.py:45
+#: mediagoblin/edit/forms.py:43
msgid "Website"
msgstr "Сайт"
-#: mediagoblin/edit/views.py:63
+#: mediagoblin/edit/views.py:64
msgid "An entry with that slug already exists for this user."
msgstr ""
"У этого пользователя уже есть файл с такой отличительной частью адреса."
-#: mediagoblin/edit/views.py:84
+#: mediagoblin/edit/views.py:85
msgid "You are editing another user's media. Proceed with caution."
msgstr "Вы редактируете файлы другого пользователя. Будьте осторожны."
-#: mediagoblin/edit/views.py:154
+#: mediagoblin/edit/views.py:155
msgid "You are editing a user's profile. Proceed with caution."
msgstr "Вы редактируете профиль пользователя. Будьте осторожны."
@@ -133,15 +136,15 @@ msgstr "Файл"
msgid "Description of this work"
msgstr "Описание этого произведения"
-#: mediagoblin/submit/views.py:47
+#: mediagoblin/submit/views.py:46
msgid "You must provide a file."
msgstr "Вы должны загрузить файл."
-#: mediagoblin/submit/views.py:50
+#: mediagoblin/submit/views.py:49
msgid "The file doesn't seem to be an image!"
msgstr "Файл, похоже, не является картинкой!"
-#: mediagoblin/submit/views.py:122
+#: mediagoblin/submit/views.py:121
msgid "Woohoo! Submitted!"
msgstr "Ура! Файл загружен!"
@@ -180,8 +183,8 @@ msgid "verify your email!"
msgstr "подтвердите ваш адрес электронной почты!"
#: mediagoblin/templates/mediagoblin/base.html:73
-#: mediagoblin/templates/mediagoblin/auth/login.html:26
-#: mediagoblin/templates/mediagoblin/auth/login.html:34
+#: mediagoblin/templates/mediagoblin/auth/login.html:27
+#: mediagoblin/templates/mediagoblin/auth/login.html:35
msgid "Log in"
msgstr "Войти"
@@ -190,6 +193,8 @@ 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/root.html:24
msgid "Explore"
@@ -197,7 +202,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:27
msgid "Hi there, media lover! MediaGoblin is..."
-msgstr "Привет, любитель мультимедиа! MediaGoblin это…"
+msgstr "Привет, любитель мультимедиа! MediaGoblin…"
#: mediagoblin/templates/mediagoblin/root.html:29
msgid "The perfect place for your media!"
@@ -230,8 +235,8 @@ msgid ""
"Built for extensibility. (Multiple media types coming soon to the software,"
" including video support!)"
msgstr ""
-"Built for extensibility. (Multiple media types coming soon to the software,"
-" including video support!)"
+"Рассчитан на расширяемость. (В программе скоро должна появиться поддержка "
+"других видов мультимедиа, таких как видео!)"
#: mediagoblin/templates/mediagoblin/root.html:34
msgid ""
@@ -250,37 +255,30 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:39
#, python-format
msgid ""
-"\n"
-" <a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
" or\n"
-" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>\n"
-" "
+" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Most recent media"
-msgstr ""
+msgstr "Самые новые файлы"
-#: mediagoblin/templates/mediagoblin/auth/change_fp.html:27
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:29
msgid "Enter your new password"
-msgstr ""
+msgstr "Введите свой новый пароль"
-#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29
msgid "Enter your username or email"
-msgstr ""
+msgstr "Введите Ваше имя пользователя или адрес электронной почты"
#: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22
-msgid ""
-"\n"
-" Your password has been changed. Try to log in now.\n"
-" "
+msgid "Your password has been changed. Try to log in now."
msgstr ""
#: mediagoblin/templates/mediagoblin/auth/fp_email_sent.html:22
msgid ""
-"\n"
-" Check your inbox. We sent an email with a URL for changing your password.\n"
-" "
+"Check your inbox. We sent an email with a URL for changing your password."
msgstr ""
#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19
@@ -297,31 +295,31 @@ msgid ""
"a happy goblin!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/login.html:29
+#: mediagoblin/templates/mediagoblin/auth/login.html:30
msgid "Logging in failed!"
msgstr "Авторизация неуспешна!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:42
+#: mediagoblin/templates/mediagoblin/auth/login.html:43
msgid "Don't have an account yet?"
msgstr "Ещё нету аккаунта?"
-#: mediagoblin/templates/mediagoblin/auth/login.html:45
+#: mediagoblin/templates/mediagoblin/auth/login.html:46
msgid "Create one here!"
msgstr "Создайте здесь!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:48
+#: mediagoblin/templates/mediagoblin/auth/login.html:49
msgid "Forgot your password?"
-msgstr ""
+msgstr "Забыли свой пароль?"
-#: mediagoblin/templates/mediagoblin/auth/login.html:51
+#: mediagoblin/templates/mediagoblin/auth/login.html:52
msgid "Change it!"
-msgstr ""
+msgstr "Смените его!"
#: mediagoblin/templates/mediagoblin/auth/register.html:27
msgid "Create an account!"
msgstr "Создать аккаунт!"
-#: mediagoblin/templates/mediagoblin/auth/register.html:30
+#: mediagoblin/templates/mediagoblin/auth/register.html:31
msgid "Create"
msgstr "Создать"
@@ -369,14 +367,14 @@ msgstr "Файлы с меткой:"
msgid "Submit yer media"
msgstr "Загрузить файл(ы)"
-#: mediagoblin/templates/mediagoblin/submit/start.html:29
+#: mediagoblin/templates/mediagoblin/submit/start.html:30
msgid "Submit"
msgstr "Подтвердить"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32
#, python-format
msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media"
-msgstr "Файлы пользователя &lt;a href=\"%(user_url)s\"&gt;%(username)s&lt;/a&gt;"
+msgstr "Файлы пользователя <a href=\"%(user_url)s\">%(username)s</a>"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52
#: mediagoblin/templates/mediagoblin/user_pages/user.html:32
@@ -436,7 +434,8 @@ msgstr "А если нет, то:"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:54
msgid "Resend verification email"
-msgstr "Повторно отправить подверждение на адрес электнонной почты"
+msgstr ""
+"Повторно отправить сообщение для подверждения адреса электронной почты"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:62
msgid ""
@@ -514,8 +513,16 @@ msgstr "Комментарий"
msgid "I am sure I want to delete this"
msgstr "Я уверен, что хочу удалить это"
-#: mediagoblin/user_pages/views.py:175
-msgid "You are about to delete another user's media. Proceed with caution."
+#: mediagoblin/user_pages/views.py:142
+msgid "Empty comments are not allowed."
+msgstr "Empty comments are not allowed."
+
+#: mediagoblin/user_pages/views.py:148
+msgid "Comment posted!"
msgstr ""
+#: mediagoblin/user_pages/views.py:181
+msgid "You are about to delete another user's media. Proceed with caution."
+msgstr "Вы на пороге удаления файла другого пользователя. Будьте осторожны."
+
diff --git a/mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.mo
new file mode 100644
index 00000000..684c850a
--- /dev/null
+++ 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
new file mode 100644
index 00000000..d3196b9c
--- /dev/null
+++ b/mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.po
@@ -0,0 +1,541 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+#
+# Translators:
+# <zatroch.martin@gmail.com>, 2011.
+msgid ""
+msgstr ""
+"Project-Id-Version: GNU MediaGoblin\n"
+"Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n"
+"POT-Creation-Date: 2011-11-01 23:14-0500\n"
+"PO-Revision-Date: 2011-11-02 04:13+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: sk\n"
+"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2\n"
+
+#: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:49
+msgid "Username"
+msgstr "Prihlasovacie meno"
+
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:53
+msgid "Password"
+msgstr "Heslo"
+
+#: mediagoblin/auth/forms.py:35
+msgid "Passwords must match."
+msgstr "Heslá sa musia zhodovať."
+
+#: mediagoblin/auth/forms.py:37
+msgid "Confirm password"
+msgstr "Potvrdiť heslo"
+
+#: mediagoblin/auth/forms.py:39
+msgid "Type it again here to make sure there are no spelling mistakes."
+msgstr "Prepíš ho sem opätovne kvôli uisteniu, že nedošlo k preklepu."
+
+#: mediagoblin/auth/forms.py:42
+msgid "Email address"
+msgstr "E-mailová adresa"
+
+#: mediagoblin/auth/views.py:55
+msgid "Sorry, registration is disabled on this instance."
+msgstr "Prepáč, registrácia na tejto inštancii nie je povolená."
+
+#: mediagoblin/auth/views.py:73
+msgid "Sorry, a user with that name already exists."
+msgstr "Prepáč, rovnaké prihlasovacie meno už niekto používa."
+
+#: mediagoblin/auth/views.py:77
+msgid "Sorry, that email address has already been taken."
+msgstr "Prepáč, daná e-mailová adresa už bola pri registrácii využitá."
+
+#: mediagoblin/auth/views.py:179
+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! "
+
+#: mediagoblin/auth/views.py:185
+msgid "The verification key or user id is incorrect"
+msgstr "Nesprávny overovací kľúč alebo používateľské ID"
+
+#: mediagoblin/auth/views.py:207
+msgid "Resent your verification email."
+msgstr "Opätovne zaslať overovaciu správu."
+
+#: mediagoblin/auth/views.py:248
+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ť správu ohľadom obnovy hesla, nakoľko je tvoje "
+"používateľské meno buď neaktívne alebo e-mailová adresa účtu neoverená."
+
+#: mediagoblin/edit/forms.py:24 mediagoblin/submit/forms.py:27
+msgid "Title"
+msgstr "Nadpis"
+
+#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:32
+msgid "Tags"
+msgstr "Štítky"
+
+#: mediagoblin/edit/forms.py:31
+msgid "Slug"
+msgstr "Unikátna časť adresy"
+
+#: mediagoblin/edit/forms.py:32
+msgid "The slug can't be empty"
+msgstr "Unikátna časť adresy musí byť vyplnená"
+
+#: mediagoblin/edit/forms.py:33
+msgid ""
+"The title part of this media's URL. You usually don't need to change this."
+msgstr "Titulná časť URL odkazu média. Zvyčajne to meniť nemusíš."
+
+#: mediagoblin/edit/forms.py:40
+msgid "Bio"
+msgstr "Bio"
+
+#: mediagoblin/edit/forms.py:43
+msgid "Website"
+msgstr "Webstránka"
+
+#: mediagoblin/edit/views.py:64
+msgid "An entry with that slug already exists for this user."
+msgstr "Položku s rovnakou unikátnou časťou adresy už niekde máš."
+
+#: mediagoblin/edit/views.py:85
+msgid "You are editing another user's media. Proceed with caution."
+msgstr "Upravuješ médiá niekoho iného. Pristupuj opatrne."
+
+#: mediagoblin/edit/views.py:155
+msgid "You are editing a user's profile. Proceed with caution."
+msgstr "Upravuješ používateľský profil. Pristupuj opatrne."
+
+#: mediagoblin/process_media/errors.py:44
+msgid "Invalid file given for media type."
+msgstr "Odovzdaný nesprávny súbor pre daný typ média."
+
+#: mediagoblin/submit/forms.py:25
+msgid "File"
+msgstr "Súbor"
+
+#: mediagoblin/submit/forms.py:30
+msgid "Description of this work"
+msgstr "Charakteristika diela"
+
+#: mediagoblin/submit/views.py:46
+msgid "You must provide a file."
+msgstr "Poskytni súbor."
+
+#: mediagoblin/submit/views.py:49
+msgid "The file doesn't seem to be an image!"
+msgstr "Súbor najskôr nie je obrázkom!"
+
+#: mediagoblin/submit/views.py:121
+msgid "Woohoo! Submitted!"
+msgstr "Juchú! Úspešne vložené!"
+
+#: mediagoblin/templates/mediagoblin/404.html:21
+msgid "Oops!"
+msgstr "Ajaj!"
+
+#: mediagoblin/templates/mediagoblin/404.html:24
+msgid "There doesn't seem to be a page at this address. Sorry!"
+msgstr "Na danej adrese sa stránka zrejme nenachádza. Prepáč!"
+
+#: mediagoblin/templates/mediagoblin/404.html:26
+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/404.html:32
+msgid "Image of 404 goblin stressing out"
+msgstr "Obrázok stresujúceho goblina pri chybovom kóde č. 404"
+
+#: mediagoblin/templates/mediagoblin/base.html:22
+msgid "GNU MediaGoblin"
+msgstr "GNU MediaGoblin"
+
+#: mediagoblin/templates/mediagoblin/base.html:47
+msgid "MediaGoblin logo"
+msgstr "MediaGoblin logo"
+
+#: mediagoblin/templates/mediagoblin/base.html:52
+msgid "Submit media"
+msgstr "Vložiť výtvor"
+
+#: mediagoblin/templates/mediagoblin/base.html:63
+msgid "verify your email!"
+msgstr "over si svoj e-mail!"
+
+#: mediagoblin/templates/mediagoblin/base.html:73
+#: mediagoblin/templates/mediagoblin/auth/login.html:27
+#: mediagoblin/templates/mediagoblin/auth/login.html:35
+msgid "Log in"
+msgstr "Prihlásenie"
+
+#: mediagoblin/templates/mediagoblin/base.html:89
+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/root.html:24
+msgid "Explore"
+msgstr "Preskúmať"
+
+#: mediagoblin/templates/mediagoblin/root.html:27
+msgid "Hi there, media lover! MediaGoblin is..."
+msgstr "Vitaj medzi nami, kreatívne stvorenie! MediaGoblin je..."
+
+#: mediagoblin/templates/mediagoblin/root.html:29
+msgid "The perfect place for your media!"
+msgstr "Parádne miesto pre tvoje výtvory!"
+
+#: mediagoblin/templates/mediagoblin/root.html:30
+msgid ""
+"A place for people to collaborate and show off original and derived "
+"creations!"
+msgstr ""
+"Miesto pre ľudí, vhodné na spoluprácu a vystavovanie tak originálnych, ako "
+"aj odvodených kreácií!"
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid ""
+"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project, "
+"after all.)"
+msgstr ""
+"Voľné, vo význame slobody. (Koniec-koncov, sme predsa <a "
+"href=\"http://gnu.org\">GNU</a> projekt.)"
+
+#: mediagoblin/templates/mediagoblin/root.html:32
+msgid ""
+"Aiming to make the world a better place through decentralization and "
+"(eventually, coming soon!) federation!"
+msgstr ""
+"Zo snahou spraviť svet lepším miestom vďaka decentralizácii a (eventuálne, "
+"už čoskoro!) federácii!"
+
+#: mediagoblin/templates/mediagoblin/root.html:33
+msgid ""
+"Built for extensibility. (Multiple media types coming soon to the software,"
+" including video support!)"
+msgstr ""
+"S dôrazom na rozšíriteľnosť. (Podpora pre rozličné typy médií v tomto "
+"softvéri už čoskoro, nevynímajúc videá!)"
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid ""
+"Powered by people like you. (<a "
+"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve this"
+" software!</a>)"
+msgstr ""
+"Existujeme aj vďaka ľudom ako si ty. (<a "
+"href=\"http://mediagoblin.org/pages/join.html\">Môžeš nám pomôcť softvér "
+"vylepšiť!</a>)"
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+msgid "Excited to join us?"
+msgstr "Tak čo, chceš sa pridať?"
+
+#: mediagoblin/templates/mediagoblin/root.html:39
+#, python-format
+msgid ""
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
+" or\n"
+" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr ""
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Vytvoriť bezplatný účet</a>\n"
+" alebo\n"
+" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Sprevádzkovať MediaGoblin na vlastnom serveri</a>"
+
+#: mediagoblin/templates/mediagoblin/root.html:53
+msgid "Most recent media"
+msgstr "Najčerstvejšie výtvory"
+
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:29
+msgid "Enter your new password"
+msgstr "Vlož svoje nové heslo"
+
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29
+msgid "Enter your username or email"
+msgstr "Vlož svoje používateľské meno alebo e-mailovú adresu"
+
+#: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22
+msgid "Your password has been changed. Try to log in now."
+msgstr "Heslo ti bolo zmenené. Skús sa prihlásiť teraz."
+
+#: mediagoblin/templates/mediagoblin/auth/fp_email_sent.html:22
+msgid ""
+"Check your inbox. We sent an email with a URL for changing your password."
+msgstr ""
+"Skontroluj si e-mailovú schránku. Bol ti zaslaná správa s URL odkazom pre "
+"zmenu tvojho hesla."
+
+#: 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 ""
+"Ahoj %(username)s,\n"
+"\n"
+"pre zmenu svojho hesla k GNU MediaGoblin účtu, otvor nasledujúci URL odkaz vo \n"
+"svojom prehliadači:\n"
+"\n"
+"%(verification_url)s\n"
+"\n"
+"Pokiaľ si myslíš, že došlo k omylu, tak jednoducho ignoruj túto správu a neprestávaj byť šťastným goblinom!"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:30
+msgid "Logging in failed!"
+msgstr "Prihlásenie zlyhalo!"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:43
+msgid "Don't have an account yet?"
+msgstr "Ešte nemáš účet?"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:46
+msgid "Create one here!"
+msgstr "Vytvoriť jeden tu!"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:49
+msgid "Forgot your password?"
+msgstr "Zabudnuté heslo?"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:52
+msgid "Change it!"
+msgstr "Zmeniť ho!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:27
+msgid "Create an account!"
+msgstr "Vytvoriť účet!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:31
+msgid "Create"
+msgstr "Vytvoriť"
+
+#: 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 ""
+"Ahoj %(username)s,\n"
+"\n"
+"pre aktiváciu tvojho GNU MediaGoblin účtu, otvor nasledujúci URL odkaz vo\n"
+"svojom prehliadači:\n"
+"\n"
+"%(verification_url)s"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:29
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "Úprava %(media_title)s"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:36
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+msgid "Cancel"
+msgstr "Zrušiť"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:37
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
+msgid "Save changes"
+msgstr "Uložiť zmeny"
+
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:29
+#, python-format
+msgid "Editing %(username)s's profile"
+msgstr "Úprava profilu, ktorý vlastní %(username)s"
+
+#: mediagoblin/templates/mediagoblin/listings/tag.html:31
+msgid "Media tagged with:"
+msgstr "Výtvor značený štítkami:"
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:26
+msgid "Submit yer media"
+msgstr "Vlož svoj výtvor"
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:30
+msgid "Submit"
+msgstr "Vložiť"
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media"
+msgstr "<a href=\"%(user_url)s\">Výtvory, ktoré vlastní %(username)s</a>"
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:32
+msgid "Sorry, no such user found."
+msgstr "Prepáč, používateľské meno nenájdené."
+
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
+#, python-format
+msgid "Really delete %(title)s?"
+msgstr "Skutočne odstrániť %(title)s?"
+
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+msgid "Delete Permanently"
+msgstr "Odstrániť navždy"
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:22
+msgid "Media processing panel"
+msgstr "Sekcia spracovania médií"
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:25
+msgid ""
+"You can track the state of media being processed for your gallery here."
+msgstr "Tu môžeš sledovať priebeh spracovania médií pre svoju galériu."
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:28
+msgid "Media in-processing"
+msgstr "Médiá v procese spracovania"
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:46
+msgid "No media in-processing"
+msgstr "Žiadne médiá v procese spracovania"
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:50
+msgid "These uploads failed to process:"
+msgstr "Nasledovné vloženia neprešli spracovaním:"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:39
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:59
+msgid "Email verification needed"
+msgstr "Potrebné overenie e-mailovej adresy"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:42
+msgid "Almost done! Your account still needs to be activated."
+msgstr "Takmer hotovo! Ešte ti musí byť aktivovaný účet."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:47
+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 mala onedlho doraziť."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:51
+msgid "In case it doesn't:"
+msgstr "V prípade, že sa tak nestalo:"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:54
+msgid "Resend verification email"
+msgstr "Opätovne zaslať overovaciu správu"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:62
+msgid ""
+"Someone has registered an account with this username, but it still has to be"
+" activated."
+msgstr ""
+"Účet s týmto prihlasovacím menom je už registrovaný, avšak ešte stále "
+"neaktívny."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:68
+#, 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 ""
+"Pokiaľ si to ty, ale už nemáš overovaciu správu, tak sa môžeš <a "
+"href=\"%(login_url)s\">prihlásiť</a> a preposlať si ju."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:78
+#, python-format
+msgid "%(username)s's profile"
+msgstr "Profil, ktorý vlastní %(username)s"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:85
+msgid "Here's a spot to tell others about yourself."
+msgstr "Povedz tu o sebe ostatným."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:90
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:108
+msgid "Edit profile"
+msgstr "Upraviť profil"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:96
+msgid "This user hasn't filled in their profile (yet)."
+msgstr "Dotyčná osoba ešte nevyplnila svoj profil (zatiaľ)."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:122
+#, 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:135
+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:141
+msgid "Add media"
+msgstr "Pridať výtvor"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:147
+msgid "There doesn't seem to be any media here yet..."
+msgstr "Najskôr tu ešte nebudú žiadne výtvory..."
+
+#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
+msgid "feed icon"
+msgstr "ikona čítačky"
+
+#: mediagoblin/templates/mediagoblin/utils/feed_link.html:23
+msgid "Atom feed"
+msgstr "Čítačka Atom"
+
+#: mediagoblin/templates/mediagoblin/utils/pagination.html:40
+msgid "Newer"
+msgstr "Novšie"
+
+#: mediagoblin/templates/mediagoblin/utils/pagination.html:46
+msgid "Older"
+msgstr "Staršie"
+
+#: mediagoblin/user_pages/forms.py:24
+msgid "Comment"
+msgstr "Komentár"
+
+#: mediagoblin/user_pages/forms.py:30
+msgid "I am sure I want to delete this"
+msgstr "Jednoznačne to chcem odstrániť"
+
+#: mediagoblin/user_pages/views.py:142
+msgid "Empty comments are not allowed."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:148
+msgid "Comment posted!"
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:181
+msgid "You are about to delete another user's media. Proceed with caution."
+msgstr "Chystáš sa odstrániť výtvory niekoho iného. Pristupuj opatrne."
+
+
diff --git a/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.mo
index d1ce44b2..52e3d632 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 17ffeec0..cba4fdd0 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://bugs.foocorp.net/projects/mediagoblin/issues\n"
-"POT-Creation-Date: 2011-09-11 16:16-0500\n"
-"PO-Revision-Date: 2011-09-11 21:16+0000\n"
+"POT-Creation-Date: 2011-11-01 23:14-0500\n"
+"PO-Revision-Date: 2011-11-02 04:13+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
@@ -43,19 +43,19 @@ msgstr ""
msgid "Email address"
msgstr "E-poštni naslov"
-#: mediagoblin/auth/views.py:42
+#: mediagoblin/auth/views.py:55
msgid "Sorry, registration is disabled on this instance."
msgstr "Oprostite, prijava za ta izvod ni omogočena."
-#: mediagoblin/auth/views.py:60
+#: mediagoblin/auth/views.py:73
msgid "Sorry, a user with that name already exists."
msgstr "Oprostite, uporabnik s tem imenom že obstaja."
-#: mediagoblin/auth/views.py:64
+#: mediagoblin/auth/views.py:77
msgid "Sorry, that email address has already been taken."
msgstr "Oprostite, ta e-poštni naslov je že v uporabi."
-#: mediagoblin/auth/views.py:165
+#: mediagoblin/auth/views.py:179
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
@@ -63,58 +63,58 @@ msgstr ""
"Vaš e-poštni naslov je bil potrjen. Sedaj se lahko prijavite, uredite svoj "
"profil in pošljete slike."
-#: mediagoblin/auth/views.py:171
+#: mediagoblin/auth/views.py:185
msgid "The verification key or user id is incorrect"
msgstr "Potrditveni ključ ali uporabniška identifikacija je napačna"
-#: mediagoblin/auth/views.py:192
+#: mediagoblin/auth/views.py:207
msgid "Resent your verification email."
msgstr "Ponovno pošiljanje potrditvene e-pošte."
-#: mediagoblin/auth/views.py:228
+#: mediagoblin/auth/views.py:248
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr ""
-#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+#: mediagoblin/edit/forms.py:24 mediagoblin/submit/forms.py:27
msgid "Title"
msgstr "Naslov"
-#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:32
msgid "Tags"
msgstr "Oznake"
-#: mediagoblin/edit/forms.py:33
+#: mediagoblin/edit/forms.py:31
msgid "Slug"
msgstr "Oznaka"
-#: mediagoblin/edit/forms.py:34
+#: mediagoblin/edit/forms.py:32
msgid "The slug can't be empty"
msgstr "Oznaka ne sme biti prazna"
-#: mediagoblin/edit/forms.py:35
+#: mediagoblin/edit/forms.py:33
msgid ""
"The title part of this media's URL. You usually don't need to change this."
msgstr ""
-#: mediagoblin/edit/forms.py:42
+#: mediagoblin/edit/forms.py:40
msgid "Bio"
msgstr "Biografija"
-#: mediagoblin/edit/forms.py:45
+#: mediagoblin/edit/forms.py:43
msgid "Website"
msgstr "Spletna stran"
-#: mediagoblin/edit/views.py:63
+#: mediagoblin/edit/views.py:64
msgid "An entry with that slug already exists for this user."
msgstr "Vnos s to oznako za tega uporabnika že obstaja."
-#: mediagoblin/edit/views.py:84
+#: mediagoblin/edit/views.py:85
msgid "You are editing another user's media. Proceed with caution."
msgstr "Urejate vsebino drugega uporabnika. Nadaljujte pazljivo."
-#: mediagoblin/edit/views.py:154
+#: mediagoblin/edit/views.py:155
msgid "You are editing a user's profile. Proceed with caution."
msgstr "Urejate uporabniški profil. Nadaljujte pazljivo."
@@ -130,15 +130,15 @@ msgstr "Datoteka"
msgid "Description of this work"
msgstr ""
-#: mediagoblin/submit/views.py:47
+#: mediagoblin/submit/views.py:46
msgid "You must provide a file."
msgstr "Podati morate datoteko."
-#: mediagoblin/submit/views.py:50
+#: mediagoblin/submit/views.py:49
msgid "The file doesn't seem to be an image!"
msgstr "Kot kaže datoteka ni slika."
-#: mediagoblin/submit/views.py:122
+#: mediagoblin/submit/views.py:121
msgid "Woohoo! Submitted!"
msgstr "Juhej! Poslano."
@@ -179,8 +179,8 @@ msgid "verify your email!"
msgstr "Preverite svojo e-pošto."
#: mediagoblin/templates/mediagoblin/base.html:73
-#: mediagoblin/templates/mediagoblin/auth/login.html:26
-#: mediagoblin/templates/mediagoblin/auth/login.html:34
+#: mediagoblin/templates/mediagoblin/auth/login.html:27
+#: mediagoblin/templates/mediagoblin/auth/login.html:35
msgid "Log in"
msgstr "Prijava"
@@ -249,37 +249,30 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:39
#, python-format
msgid ""
-"\n"
-" <a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
" or\n"
-" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>\n"
-" "
+" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Most recent media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/change_fp.html:27
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:29
msgid "Enter your new password"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29
msgid "Enter your username or email"
msgstr ""
#: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22
-msgid ""
-"\n"
-" Your password has been changed. Try to log in now.\n"
-" "
+msgid "Your password has been changed. Try to log in now."
msgstr ""
#: mediagoblin/templates/mediagoblin/auth/fp_email_sent.html:22
msgid ""
-"\n"
-" Check your inbox. We sent an email with a URL for changing your password.\n"
-" "
+"Check your inbox. We sent an email with a URL for changing your password."
msgstr ""
#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19
@@ -296,23 +289,23 @@ msgid ""
"a happy goblin!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/login.html:29
+#: mediagoblin/templates/mediagoblin/auth/login.html:30
msgid "Logging in failed!"
msgstr "Prijava ni uspela."
-#: mediagoblin/templates/mediagoblin/auth/login.html:42
+#: mediagoblin/templates/mediagoblin/auth/login.html:43
msgid "Don't have an account yet?"
msgstr "Še nimate računa?"
-#: mediagoblin/templates/mediagoblin/auth/login.html:45
+#: mediagoblin/templates/mediagoblin/auth/login.html:46
msgid "Create one here!"
msgstr "Ustvarite si ga."
-#: mediagoblin/templates/mediagoblin/auth/login.html:48
+#: mediagoblin/templates/mediagoblin/auth/login.html:49
msgid "Forgot your password?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/login.html:51
+#: mediagoblin/templates/mediagoblin/auth/login.html:52
msgid "Change it!"
msgstr ""
@@ -320,7 +313,7 @@ msgstr ""
msgid "Create an account!"
msgstr "Ustvarite račun."
-#: mediagoblin/templates/mediagoblin/auth/register.html:30
+#: mediagoblin/templates/mediagoblin/auth/register.html:31
msgid "Create"
msgstr "Ustvari"
@@ -369,7 +362,7 @@ msgstr "Vsebina označena z:"
msgid "Submit yer media"
msgstr "Pošljite svojo vsebino"
-#: mediagoblin/templates/mediagoblin/submit/start.html:29
+#: mediagoblin/templates/mediagoblin/submit/start.html:30
msgid "Submit"
msgstr "Pošlji"
@@ -513,7 +506,15 @@ msgstr "Komentar"
msgid "I am sure I want to delete this"
msgstr ""
-#: mediagoblin/user_pages/views.py:175
+#: mediagoblin/user_pages/views.py:142
+msgid "Empty comments are not allowed."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:148
+msgid "Comment posted!"
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:181
msgid "You are about to delete another user's media. Proceed with caution."
msgstr ""
diff --git a/mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.mo
index d09aea44..d2649938 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 da928da6..b4b2fb7b 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://bugs.foocorp.net/projects/mediagoblin/issues\n"
-"POT-Creation-Date: 2011-09-11 16:16-0500\n"
-"PO-Revision-Date: 2011-09-11 21:16+0000\n"
+"POT-Creation-Date: 2011-11-01 23:14-0500\n"
+"PO-Revision-Date: 2011-11-02 04:13+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: Serbian (http://www.transifex.net/projects/p/mediagoblin/team/sr/)\n"
"MIME-Version: 1.0\n"
@@ -42,76 +42,76 @@ msgstr ""
msgid "Email address"
msgstr ""
-#: mediagoblin/auth/views.py:42
+#: mediagoblin/auth/views.py:55
msgid "Sorry, registration is disabled on this instance."
msgstr ""
-#: mediagoblin/auth/views.py:60
+#: mediagoblin/auth/views.py:73
msgid "Sorry, a user with that name already exists."
msgstr ""
-#: mediagoblin/auth/views.py:64
+#: mediagoblin/auth/views.py:77
msgid "Sorry, that email address has already been taken."
msgstr ""
-#: mediagoblin/auth/views.py:165
+#: mediagoblin/auth/views.py:179
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr ""
-#: mediagoblin/auth/views.py:171
+#: mediagoblin/auth/views.py:185
msgid "The verification key or user id is incorrect"
msgstr ""
-#: mediagoblin/auth/views.py:192
+#: mediagoblin/auth/views.py:207
msgid "Resent your verification email."
msgstr ""
-#: mediagoblin/auth/views.py:228
+#: mediagoblin/auth/views.py:248
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr ""
-#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+#: mediagoblin/edit/forms.py:24 mediagoblin/submit/forms.py:27
msgid "Title"
msgstr ""
-#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:32
msgid "Tags"
msgstr ""
-#: mediagoblin/edit/forms.py:33
+#: mediagoblin/edit/forms.py:31
msgid "Slug"
msgstr ""
-#: mediagoblin/edit/forms.py:34
+#: mediagoblin/edit/forms.py:32
msgid "The slug can't be empty"
msgstr ""
-#: mediagoblin/edit/forms.py:35
+#: mediagoblin/edit/forms.py:33
msgid ""
"The title part of this media's URL. You usually don't need to change this."
msgstr ""
-#: mediagoblin/edit/forms.py:42
+#: mediagoblin/edit/forms.py:40
msgid "Bio"
msgstr ""
-#: mediagoblin/edit/forms.py:45
+#: mediagoblin/edit/forms.py:43
msgid "Website"
msgstr ""
-#: mediagoblin/edit/views.py:63
+#: mediagoblin/edit/views.py:64
msgid "An entry with that slug already exists for this user."
msgstr ""
-#: mediagoblin/edit/views.py:84
+#: mediagoblin/edit/views.py:85
msgid "You are editing another user's media. Proceed with caution."
msgstr ""
-#: mediagoblin/edit/views.py:154
+#: mediagoblin/edit/views.py:155
msgid "You are editing a user's profile. Proceed with caution."
msgstr ""
@@ -127,15 +127,15 @@ msgstr ""
msgid "Description of this work"
msgstr ""
-#: mediagoblin/submit/views.py:47
+#: mediagoblin/submit/views.py:46
msgid "You must provide a file."
msgstr ""
-#: mediagoblin/submit/views.py:50
+#: mediagoblin/submit/views.py:49
msgid "The file doesn't seem to be an image!"
msgstr ""
-#: mediagoblin/submit/views.py:122
+#: mediagoblin/submit/views.py:121
msgid "Woohoo! Submitted!"
msgstr ""
@@ -174,8 +174,8 @@ msgid "verify your email!"
msgstr ""
#: mediagoblin/templates/mediagoblin/base.html:73
-#: mediagoblin/templates/mediagoblin/auth/login.html:26
-#: mediagoblin/templates/mediagoblin/auth/login.html:34
+#: mediagoblin/templates/mediagoblin/auth/login.html:27
+#: mediagoblin/templates/mediagoblin/auth/login.html:35
msgid "Log in"
msgstr ""
@@ -235,37 +235,30 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:39
#, python-format
msgid ""
-"\n"
-" <a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
" or\n"
-" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>\n"
-" "
+" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Most recent media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/change_fp.html:27
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:29
msgid "Enter your new password"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29
msgid "Enter your username or email"
msgstr ""
#: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22
-msgid ""
-"\n"
-" Your password has been changed. Try to log in now.\n"
-" "
+msgid "Your password has been changed. Try to log in now."
msgstr ""
#: mediagoblin/templates/mediagoblin/auth/fp_email_sent.html:22
msgid ""
-"\n"
-" Check your inbox. We sent an email with a URL for changing your password.\n"
-" "
+"Check your inbox. We sent an email with a URL for changing your password."
msgstr ""
#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19
@@ -282,23 +275,23 @@ msgid ""
"a happy goblin!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/login.html:29
+#: mediagoblin/templates/mediagoblin/auth/login.html:30
msgid "Logging in failed!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/login.html:42
+#: mediagoblin/templates/mediagoblin/auth/login.html:43
msgid "Don't have an account yet?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/login.html:45
+#: mediagoblin/templates/mediagoblin/auth/login.html:46
msgid "Create one here!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/login.html:48
+#: mediagoblin/templates/mediagoblin/auth/login.html:49
msgid "Forgot your password?"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/login.html:51
+#: mediagoblin/templates/mediagoblin/auth/login.html:52
msgid "Change it!"
msgstr ""
@@ -306,7 +299,7 @@ msgstr ""
msgid "Create an account!"
msgstr ""
-#: mediagoblin/templates/mediagoblin/auth/register.html:30
+#: mediagoblin/templates/mediagoblin/auth/register.html:31
msgid "Create"
msgstr ""
@@ -349,7 +342,7 @@ msgstr ""
msgid "Submit yer media"
msgstr ""
-#: mediagoblin/templates/mediagoblin/submit/start.html:29
+#: mediagoblin/templates/mediagoblin/submit/start.html:30
msgid "Submit"
msgstr ""
@@ -489,7 +482,15 @@ msgstr ""
msgid "I am sure I want to delete this"
msgstr ""
-#: mediagoblin/user_pages/views.py:175
+#: mediagoblin/user_pages/views.py:142
+msgid "Empty comments are not allowed."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:148
+msgid "Comment posted!"
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:181
msgid "You are about to delete another user's media. Proceed with caution."
msgstr ""
diff --git a/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.mo
index 5f8ac655..2ae7c510 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 f38166a5..3ee44b18 100644
--- a/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.po
@@ -3,13 +3,14 @@
# This file is distributed under the same license as the PROJECT project.
#
# Translators:
+# <simon@ingenmansland.se>, 2011.
# <transifex@wandborg.se>, 2011.
msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n"
-"POT-Creation-Date: 2011-09-11 16:16-0500\n"
-"PO-Revision-Date: 2011-09-11 21:16+0000\n"
+"POT-Creation-Date: 2011-11-01 23:14-0500\n"
+"PO-Revision-Date: 2011-11-02 04:13+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: Swedish (http://www.transifex.net/projects/p/mediagoblin/team/sv/)\n"
"MIME-Version: 1.0\n"
@@ -43,19 +44,19 @@ msgstr "Skriv in det igen för att undvika stavfel."
msgid "Email address"
msgstr "E-postadress"
-#: mediagoblin/auth/views.py:42
+#: mediagoblin/auth/views.py:55
msgid "Sorry, registration is disabled on this instance."
msgstr "Vi beklagar, registreringen är avtängd på den här instansen."
-#: mediagoblin/auth/views.py:60
+#: mediagoblin/auth/views.py:73
msgid "Sorry, a user with that name already exists."
msgstr "En användare med det användarnamnet finns redan."
-#: mediagoblin/auth/views.py:64
+#: mediagoblin/auth/views.py:77
msgid "Sorry, that email address has already been taken."
msgstr "Den e-postadressen är redan tagen."
-#: mediagoblin/auth/views.py:165
+#: mediagoblin/auth/views.py:179
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
@@ -63,58 +64,60 @@ msgstr ""
"Din e-postadress är verifierad. Du kan nu logga in, redigera din profil och "
"ladda upp filer!"
-#: mediagoblin/auth/views.py:171
+#: mediagoblin/auth/views.py:185
msgid "The verification key or user id is incorrect"
msgstr "Verifieringsnyckeln eller användar-IDt är fel."
-#: mediagoblin/auth/views.py:192
+#: mediagoblin/auth/views.py:207
msgid "Resent your verification email."
msgstr "Skickade ett nytt verifierings-email."
-#: mediagoblin/auth/views.py:228
+#: mediagoblin/auth/views.py:248
msgid ""
"Could not send password recovery email as your username is inactive or your "
"account's email address has not been verified."
msgstr ""
+"Kunde inte skicka e-poståterställning av lösenord eftersom ditt användarnamn"
+" är inaktivt eller kontots e-postadress har inte verifierats."
-#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+#: mediagoblin/edit/forms.py:24 mediagoblin/submit/forms.py:27
msgid "Title"
msgstr "Titel"
-#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:32
msgid "Tags"
msgstr "Taggar"
-#: mediagoblin/edit/forms.py:33
+#: mediagoblin/edit/forms.py:31
msgid "Slug"
msgstr "Sökvägsnamn"
-#: mediagoblin/edit/forms.py:34
+#: mediagoblin/edit/forms.py:32
msgid "The slug can't be empty"
msgstr "Sökvägsnamnet kan inte vara tomt"
-#: mediagoblin/edit/forms.py:35
+#: mediagoblin/edit/forms.py:33
msgid ""
"The title part of this media's URL. You usually don't need to change this."
msgstr "Sökvägstitlen för din media. Du brukar inte behöva ändra denna."
-#: mediagoblin/edit/forms.py:42
+#: mediagoblin/edit/forms.py:40
msgid "Bio"
msgstr "Presentation"
-#: mediagoblin/edit/forms.py:45
+#: mediagoblin/edit/forms.py:43
msgid "Website"
msgstr "Hemsida"
-#: mediagoblin/edit/views.py:63
+#: mediagoblin/edit/views.py:64
msgid "An entry with that slug already exists for this user."
msgstr "Ett inlägg med det sökvägsnamnet existerar redan."
-#: mediagoblin/edit/views.py:84
+#: mediagoblin/edit/views.py:85
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:154
+#: mediagoblin/edit/views.py:155
msgid "You are editing a user's profile. Proceed with caution."
msgstr "Var försiktig, du redigerar en annan användares profil."
@@ -130,15 +133,15 @@ msgstr "Fil"
msgid "Description of this work"
msgstr "Beskrivning av verket"
-#: mediagoblin/submit/views.py:47
+#: mediagoblin/submit/views.py:46
msgid "You must provide a file."
msgstr "Du måste ange en fil"
-#: mediagoblin/submit/views.py:50
+#: mediagoblin/submit/views.py:49
msgid "The file doesn't seem to be an image!"
msgstr "Filen verkar inte vara en giltig bildfil!"
-#: mediagoblin/submit/views.py:122
+#: mediagoblin/submit/views.py:121
msgid "Woohoo! Submitted!"
msgstr "Tjohoo! Upladdat!"
@@ -179,8 +182,8 @@ msgid "verify your email!"
msgstr "Verifiera din e-postadress!"
#: mediagoblin/templates/mediagoblin/base.html:73
-#: mediagoblin/templates/mediagoblin/auth/login.html:26
-#: mediagoblin/templates/mediagoblin/auth/login.html:34
+#: mediagoblin/templates/mediagoblin/auth/login.html:27
+#: mediagoblin/templates/mediagoblin/auth/login.html:35
msgid "Log in"
msgstr "Logga in"
@@ -194,7 +197,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:24
msgid "Explore"
-msgstr ""
+msgstr "Utforska"
#: mediagoblin/templates/mediagoblin/root.html:27
msgid "Hi there, media lover! MediaGoblin is..."
@@ -251,43 +254,42 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:38
msgid "Excited to join us?"
-msgstr ""
+msgstr "Nyfiken att gå med oss?"
#: mediagoblin/templates/mediagoblin/root.html:39
#, python-format
msgid ""
-"\n"
-" <a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
" or\n"
-" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>\n"
-" "
+" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
msgstr ""
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Skapa ett konto gratis</a>\n"
+"\n"
+" or\n"
+" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Installera MediaGoblin på din egen server</a>"
#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Most recent media"
-msgstr ""
+msgstr "Senast medier"
-#: mediagoblin/templates/mediagoblin/auth/change_fp.html:27
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:29
msgid "Enter your new password"
-msgstr ""
+msgstr "Fyll i ditt lösenord"
-#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29
msgid "Enter your username or email"
-msgstr ""
+msgstr "Fyll i ditt användarnamn eller lösenord"
#: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22
-msgid ""
-"\n"
-" Your password has been changed. Try to log in now.\n"
-" "
-msgstr ""
+msgid "Your password has been changed. Try to log in now."
+msgstr "Ditt lösenord är nu ändrat. Testa att logga in nu."
#: mediagoblin/templates/mediagoblin/auth/fp_email_sent.html:22
msgid ""
-"\n"
-" Check your inbox. We sent an email with a URL for changing your password.\n"
-" "
+"Check your inbox. We sent an email with a URL for changing your password."
msgstr ""
+"Kolla din inkorg. Vi har skickat ett e-postmeddelande med en webbadress för "
+"att ändra ditt lösenord."
#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19
#, python-format
@@ -302,32 +304,40 @@ msgid ""
"If you think this is an error, just ignore this email and continue being\n"
"a happy goblin!"
msgstr ""
+"Hej %(username)s,\n"
+"\n"
+"för att ändra ditt GNU MediaGoblin-lösenord, öppna följande länk i\n"
+"din webbläsare:\n"
+"\n"
+"%(verification_url)s\n"
+"\n"
+"Om du misstänker att du fått detta epostmeddelanade av misstag, ignorera det och fortsätt vara ett glatt troll!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:29
+#: mediagoblin/templates/mediagoblin/auth/login.html:30
msgid "Logging in failed!"
msgstr "Inloggning misslyckades!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:42
+#: mediagoblin/templates/mediagoblin/auth/login.html:43
msgid "Don't have an account yet?"
-msgstr "Har du inget konto?"
+msgstr "Har du inget konto än?"
-#: mediagoblin/templates/mediagoblin/auth/login.html:45
+#: mediagoblin/templates/mediagoblin/auth/login.html:46
msgid "Create one here!"
-msgstr "Skapa ett!"
+msgstr "Skapa ett här!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:48
+#: mediagoblin/templates/mediagoblin/auth/login.html:49
msgid "Forgot your password?"
-msgstr ""
+msgstr "Glömt ditt lösenord?"
-#: mediagoblin/templates/mediagoblin/auth/login.html:51
+#: mediagoblin/templates/mediagoblin/auth/login.html:52
msgid "Change it!"
-msgstr ""
+msgstr "Ändra!"
#: mediagoblin/templates/mediagoblin/auth/register.html:27
msgid "Create an account!"
msgstr "Skapa ett konto!"
-#: mediagoblin/templates/mediagoblin/auth/register.html:30
+#: mediagoblin/templates/mediagoblin/auth/register.html:31
msgid "Create"
msgstr "Skapa"
@@ -343,7 +353,7 @@ msgid ""
msgstr ""
"Hej %(username)s,\n"
"\n"
-"oppna den följande URLen i din webbläsare för att aktivera ditt konto på GNU MediaGoblin:\n"
+"öppna den följande webbadressen i din webbläsare för att aktivera ditt konto på GNU MediaGoblin:\n"
"\n"
"%(verification_url)s"
@@ -360,7 +370,7 @@ msgstr "Avbryt"
#: mediagoblin/templates/mediagoblin/edit/edit.html:37
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
msgid "Save changes"
-msgstr "Spara"
+msgstr "Spara ändringar"
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:29
#, python-format
@@ -369,13 +379,13 @@ msgstr "Redigerar %(username)ss profil"
#: mediagoblin/templates/mediagoblin/listings/tag.html:31
msgid "Media tagged with:"
-msgstr "Taggat med:"
+msgstr "Media taggat med:"
#: mediagoblin/templates/mediagoblin/submit/start.html:26
msgid "Submit yer media"
msgstr "Ladda upp"
-#: mediagoblin/templates/mediagoblin/submit/start.html:29
+#: mediagoblin/templates/mediagoblin/submit/start.html:30
msgid "Submit"
msgstr "Skicka"
@@ -387,7 +397,7 @@ msgstr "<a href=\"%(user_url)s\">%(username)s</a>s media"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52
#: mediagoblin/templates/mediagoblin/user_pages/user.html:32
msgid "Sorry, no such user found."
-msgstr "Finns ingen sådan användare ännu."
+msgstr "Ledsen, hittar ingen sådan användare."
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
#, python-format
@@ -523,7 +533,15 @@ msgstr "Kommentar"
msgid "I am sure I want to delete this"
msgstr "Jag är säker på att jag vill radera detta"
-#: mediagoblin/user_pages/views.py:175
+#: mediagoblin/user_pages/views.py:142
+msgid "Empty comments are not allowed."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:148
+msgid "Comment posted!"
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:181
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."
diff --git a/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.mo
new file mode 100644
index 00000000..b0d8d3fc
--- /dev/null
+++ 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
new file mode 100644
index 00000000..289bddb5
--- /dev/null
+++ b/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.po
@@ -0,0 +1,498 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+#
+# Translators:
+# వీవెన్ <veeven@gmail.com>, 2011.
+msgid ""
+msgstr ""
+"Project-Id-Version: GNU MediaGoblin\n"
+"Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n"
+"POT-Creation-Date: 2011-11-01 23:14-0500\n"
+"PO-Revision-Date: 2011-11-03 14:08+0000\n"
+"Last-Translator: veeven <veeven@gmail.com>\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: te\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+
+#: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:49
+msgid "Username"
+msgstr "వాడుకరి పేరు"
+
+#: mediagoblin/auth/forms.py:30 mediagoblin/auth/forms.py:53
+msgid "Password"
+msgstr "సంకేతపదం"
+
+#: mediagoblin/auth/forms.py:35
+msgid "Passwords must match."
+msgstr ""
+
+#: mediagoblin/auth/forms.py:37
+msgid "Confirm password"
+msgstr ""
+
+#: mediagoblin/auth/forms.py:39
+msgid "Type it again here to make sure there are no spelling mistakes."
+msgstr ""
+
+#: mediagoblin/auth/forms.py:42
+msgid "Email address"
+msgstr "ఈమెయిలు చిరునామా"
+
+#: mediagoblin/auth/views.py:55
+msgid "Sorry, registration is disabled on this instance."
+msgstr ""
+
+#: mediagoblin/auth/views.py:73
+msgid "Sorry, a user with that name already exists."
+msgstr ""
+
+#: mediagoblin/auth/views.py:77
+msgid "Sorry, that email address has already been taken."
+msgstr ""
+
+#: mediagoblin/auth/views.py:179
+msgid ""
+"Your email address has been verified. You may now login, edit your profile, "
+"and submit images!"
+msgstr ""
+
+#: mediagoblin/auth/views.py:185
+msgid "The verification key or user id is incorrect"
+msgstr ""
+
+#: mediagoblin/auth/views.py:207
+msgid "Resent your verification email."
+msgstr ""
+
+#: mediagoblin/auth/views.py:248
+msgid ""
+"Could not send password recovery email as your username is inactive or your "
+"account's email address has not been verified."
+msgstr ""
+
+#: mediagoblin/edit/forms.py:24 mediagoblin/submit/forms.py:27
+msgid "Title"
+msgstr "శీర్షిక"
+
+#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:32
+msgid "Tags"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:31
+msgid "Slug"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:32
+msgid "The slug can't be empty"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:33
+msgid ""
+"The title part of this media's URL. You usually don't need to change this."
+msgstr ""
+
+#: mediagoblin/edit/forms.py:40
+msgid "Bio"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:43
+msgid "Website"
+msgstr ""
+
+#: mediagoblin/edit/views.py:64
+msgid "An entry with that slug already exists for this user."
+msgstr ""
+
+#: mediagoblin/edit/views.py:85
+msgid "You are editing another user's media. Proceed with caution."
+msgstr ""
+
+#: mediagoblin/edit/views.py:155
+msgid "You are editing a user's profile. Proceed with caution."
+msgstr ""
+
+#: mediagoblin/process_media/errors.py:44
+msgid "Invalid file given for media type."
+msgstr ""
+
+#: mediagoblin/submit/forms.py:25
+msgid "File"
+msgstr ""
+
+#: mediagoblin/submit/forms.py:30
+msgid "Description of this work"
+msgstr ""
+
+#: mediagoblin/submit/views.py:46
+msgid "You must provide a file."
+msgstr ""
+
+#: mediagoblin/submit/views.py:49
+msgid "The file doesn't seem to be an image!"
+msgstr ""
+
+#: mediagoblin/submit/views.py:121
+msgid "Woohoo! Submitted!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/404.html:21
+msgid "Oops!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/404.html:24
+msgid "There doesn't seem to be a page at this address. Sorry!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/404.html:26
+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/404.html:32
+msgid "Image of 404 goblin stressing out"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/base.html:22
+msgid "GNU MediaGoblin"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/base.html:47
+msgid "MediaGoblin logo"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/base.html:52
+msgid "Submit media"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/base.html:63
+msgid "verify your email!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/base.html:73
+#: mediagoblin/templates/mediagoblin/auth/login.html:27
+#: mediagoblin/templates/mediagoblin/auth/login.html:35
+msgid "Log in"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/base.html:89
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
+"href=\"http://gnu.org/\">GNU</a> project"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:24
+msgid "Explore"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:27
+msgid "Hi there, media lover! MediaGoblin is..."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:29
+msgid "The perfect place for your media!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:30
+msgid ""
+"A place for people to collaborate and show off original and derived "
+"creations!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:31
+msgid ""
+"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project, "
+"after all.)"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:32
+msgid ""
+"Aiming to make the world a better place through decentralization and "
+"(eventually, coming soon!) federation!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:33
+msgid ""
+"Built for extensibility. (Multiple media types coming soon to the software,"
+" including video support!)"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:34
+msgid ""
+"Powered by people like you. (<a "
+"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve this"
+" software!</a>)"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:38
+msgid "Excited to join us?"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:39
+#, python-format
+msgid ""
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
+" or\n"
+" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/root.html:53
+msgid "Most recent media"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:29
+msgid "Enter your new password"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29
+msgid "Enter your username or email"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22
+msgid "Your password has been changed. Try to log in now."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/fp_email_sent.html:22
+msgid ""
+"Check your inbox. We sent an email with a URL for changing your password."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19
+#, python-format
+msgid ""
+"Hi %(username)s,\n"
+"\n"
+"to change your GNU MediaGoblin password, open the following URL in \n"
+"your web browser:\n"
+"\n"
+"%(verification_url)s\n"
+"\n"
+"If you think this is an error, just ignore this email and continue being\n"
+"a happy goblin!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:30
+msgid "Logging in failed!"
+msgstr "ప్రవేశం విఫలమయ్యింది!"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:43
+msgid "Don't have an account yet?"
+msgstr "మీకు ఇంకా ఖాతా లేదా?"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:46
+msgid "Create one here!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:49
+msgid "Forgot your password?"
+msgstr "మీ సంకేతపదాన్ని మర్చిపోయారా?"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:52
+msgid "Change it!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:27
+msgid "Create an account!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:31
+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 ""
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:29
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:36
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49
+msgid "Cancel"
+msgstr "రద్దుచేయి"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:37
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
+msgid "Save changes"
+msgstr "మార్పులను భద్రపరచు"
+
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:29
+#, python-format
+msgid "Editing %(username)s's profile"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/listings/tag.html:31
+msgid "Media tagged with:"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:26
+msgid "Submit yer media"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:30
+msgid "Submit"
+msgstr "దాఖలు చెయ్యి"
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:32
+msgid "Sorry, no such user found."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30
+#, python-format
+msgid "Really delete %(title)s?"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
+msgid "Delete Permanently"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:22
+msgid "Media processing panel"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:25
+msgid ""
+"You can track the state of media being processed for your gallery here."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:28
+msgid "Media in-processing"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:46
+msgid "No media in-processing"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:50
+msgid "These uploads failed to process:"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:39
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:59
+msgid "Email verification needed"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:42
+msgid "Almost done! Your account still needs to be activated."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:47
+msgid ""
+"An email should arrive in a few moments with instructions on how to do so."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:51
+msgid "In case it doesn't:"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:54
+msgid "Resend verification email"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:62
+msgid ""
+"Someone has registered an account with this username, but it still has to be"
+" activated."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:68
+#, 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 ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:78
+#, python-format
+msgid "%(username)s's profile"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:85
+msgid "Here's a spot to tell others about yourself."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:90
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:108
+msgid "Edit profile"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:96
+msgid "This user hasn't filled in their profile (yet)."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:122
+#, python-format
+msgid "View all of %(username)s's media"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:135
+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:141
+msgid "Add media"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:147
+msgid "There doesn't seem to be any media here yet..."
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
+msgid "feed icon"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/utils/feed_link.html:23
+msgid "Atom feed"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/utils/pagination.html:40
+msgid "Newer"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/utils/pagination.html:46
+msgid "Older"
+msgstr ""
+
+#: mediagoblin/user_pages/forms.py:24
+msgid "Comment"
+msgstr "వ్యాఖ్య"
+
+#: mediagoblin/user_pages/forms.py:30
+msgid "I am sure I want to delete this"
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:142
+msgid "Empty comments are not allowed."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:148
+msgid "Comment posted!"
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:181
+msgid "You are about to delete another user's media. 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 e0117391..e3751aeb 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 9e4380c2..c664adbe 100644
--- a/mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.po
@@ -9,8 +9,8 @@ msgid ""
msgstr ""
"Project-Id-Version: GNU MediaGoblin\n"
"Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n"
-"POT-Creation-Date: 2011-09-11 16:16-0500\n"
-"PO-Revision-Date: 2011-09-11 21:16+0000\n"
+"POT-Creation-Date: 2011-11-01 23:14-0500\n"
+"PO-Revision-Date: 2011-11-02 04:13+0000\n"
"Last-Translator: cwebber <cwebber@dustycloud.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
@@ -44,76 +44,76 @@ msgstr "再輸入一次,確定你沒有打錯字。"
msgid "Email address"
msgstr "電子郵件位置"
-#: mediagoblin/auth/views.py:42
+#: mediagoblin/auth/views.py:55
msgid "Sorry, registration is disabled on this instance."
msgstr "抱歉, 這個項目已經被暫停註冊."
-#: mediagoblin/auth/views.py:60
+#: mediagoblin/auth/views.py:73
msgid "Sorry, a user with that name already exists."
msgstr "抱歉, 這個使用者名稱已經存在."
-#: mediagoblin/auth/views.py:64
+#: mediagoblin/auth/views.py:77
msgid "Sorry, that email address has already been taken."
msgstr "抱歉,這個電子郵件已經被其他人使用了。"
-#: mediagoblin/auth/views.py:165
+#: mediagoblin/auth/views.py:179
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr "你的電子郵件位址已被認證. 你現在就可以登入, 編輯你的個人檔案而且遞交照片!"
-#: mediagoblin/auth/views.py:171
+#: mediagoblin/auth/views.py:185
msgid "The verification key or user id is incorrect"
msgstr "認證碼或是使用者帳號錯誤"
-#: mediagoblin/auth/views.py:192
+#: mediagoblin/auth/views.py:207
msgid "Resent your verification email."
msgstr "重送認證信."
-#: mediagoblin/auth/views.py:228
+#: mediagoblin/auth/views.py:248
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/edit/forms.py:26 mediagoblin/submit/forms.py:27
+#: mediagoblin/edit/forms.py:24 mediagoblin/submit/forms.py:27
msgid "Title"
msgstr "標題"
-#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:32
+#: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:32
msgid "Tags"
msgstr "標籤"
-#: mediagoblin/edit/forms.py:33
+#: mediagoblin/edit/forms.py:31
msgid "Slug"
msgstr "自訂字串"
-#: mediagoblin/edit/forms.py:34
+#: mediagoblin/edit/forms.py:32
msgid "The slug can't be empty"
msgstr "自訂字串不能空白"
-#: mediagoblin/edit/forms.py:35
+#: mediagoblin/edit/forms.py:33
msgid ""
"The title part of this media's URL. You usually don't need to change this."
-msgstr ""
+msgstr "此媒體網址的名稱。你通常不需要變動這個的。"
-#: mediagoblin/edit/forms.py:42
+#: mediagoblin/edit/forms.py:40
msgid "Bio"
msgstr "自我介紹"
-#: mediagoblin/edit/forms.py:45
+#: mediagoblin/edit/forms.py:43
msgid "Website"
msgstr "網站"
-#: mediagoblin/edit/views.py:63
+#: mediagoblin/edit/views.py:64
msgid "An entry with that slug already exists for this user."
msgstr "這個自訂字串已經被其他人用了"
-#: mediagoblin/edit/views.py:84
+#: mediagoblin/edit/views.py:85
msgid "You are editing another user's media. Proceed with caution."
msgstr "你正在編輯他人的媒體檔案. 請謹慎處理."
-#: mediagoblin/edit/views.py:154
+#: mediagoblin/edit/views.py:155
msgid "You are editing a user's profile. Proceed with caution."
msgstr "你正在編輯一位用戶的檔案. 請謹慎處理."
@@ -127,17 +127,17 @@ msgstr "檔案"
#: mediagoblin/submit/forms.py:30
msgid "Description of this work"
-msgstr ""
+msgstr "這個作品的描述"
-#: mediagoblin/submit/views.py:47
+#: mediagoblin/submit/views.py:46
msgid "You must provide a file."
msgstr "你必須提供一個檔案"
-#: mediagoblin/submit/views.py:50
+#: mediagoblin/submit/views.py:49
msgid "The file doesn't seem to be an image!"
msgstr "檔案似乎不是一個圖片喔!"
-#: mediagoblin/submit/views.py:122
+#: mediagoblin/submit/views.py:121
msgid "Woohoo! Submitted!"
msgstr "呼呼! 送出去嚕!"
@@ -176,8 +176,8 @@ msgid "verify your email!"
msgstr "確認您的電子郵件!"
#: mediagoblin/templates/mediagoblin/base.html:73
-#: mediagoblin/templates/mediagoblin/auth/login.html:26
-#: mediagoblin/templates/mediagoblin/auth/login.html:34
+#: mediagoblin/templates/mediagoblin/auth/login.html:27
+#: mediagoblin/templates/mediagoblin/auth/login.html:35
msgid "Log in"
msgstr "登入"
@@ -191,7 +191,7 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:24
msgid "Explore"
-msgstr ""
+msgstr "探索"
#: mediagoblin/templates/mediagoblin/root.html:27
msgid "Hi there, media lover! MediaGoblin is..."
@@ -236,43 +236,39 @@ msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:38
msgid "Excited to join us?"
-msgstr ""
+msgstr "迫不亟待想要加入我們?"
#: mediagoblin/templates/mediagoblin/root.html:39
#, python-format
msgid ""
-"\n"
-" <a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n"
" or\n"
-" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>\n"
-" "
+" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>"
msgstr ""
+"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">建立一個免費帳號</a>\n"
+" 或是\n"
+" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">在你的伺服器上設立 MediaGoblin</a>"
#: mediagoblin/templates/mediagoblin/root.html:53
msgid "Most recent media"
-msgstr ""
+msgstr "最新的媒體"
-#: mediagoblin/templates/mediagoblin/auth/change_fp.html:27
+#: mediagoblin/templates/mediagoblin/auth/change_fp.html:29
msgid "Enter your new password"
-msgstr ""
+msgstr "輸入你的新密碼"
-#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27
+#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29
msgid "Enter your username or email"
-msgstr ""
+msgstr "輸入你的帳號或是電子郵件"
#: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22
-msgid ""
-"\n"
-" Your password has been changed. Try to log in now.\n"
-" "
-msgstr ""
+msgid "Your password has been changed. Try to log in now."
+msgstr "你的密碼已經改變了。現在就登入試試看。"
#: mediagoblin/templates/mediagoblin/auth/fp_email_sent.html:22
msgid ""
-"\n"
-" Check your inbox. We sent an email with a URL for changing your password.\n"
-" "
-msgstr ""
+"Check your inbox. We sent an email with a URL for changing your password."
+msgstr "檢查你的收件匣。我們已經傳送了電子郵件,你可利用郵件中的網址變更密碼。"
#: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19
#, python-format
@@ -287,32 +283,39 @@ msgid ""
"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!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:29
+#: mediagoblin/templates/mediagoblin/auth/login.html:30
msgid "Logging in failed!"
msgstr "登入失敗!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:42
+#: mediagoblin/templates/mediagoblin/auth/login.html:43
msgid "Don't have an account yet?"
msgstr "還沒有帳號嗎?"
-#: mediagoblin/templates/mediagoblin/auth/login.html:45
+#: mediagoblin/templates/mediagoblin/auth/login.html:46
msgid "Create one here!"
msgstr "在這裡建立一個吧!"
-#: mediagoblin/templates/mediagoblin/auth/login.html:48
+#: mediagoblin/templates/mediagoblin/auth/login.html:49
msgid "Forgot your password?"
-msgstr ""
+msgstr "忘了密碼嗎?"
-#: mediagoblin/templates/mediagoblin/auth/login.html:51
+#: mediagoblin/templates/mediagoblin/auth/login.html:52
msgid "Change it!"
-msgstr ""
+msgstr "變更!"
#: mediagoblin/templates/mediagoblin/auth/register.html:27
msgid "Create an account!"
msgstr "建立一個帳號!"
-#: mediagoblin/templates/mediagoblin/auth/register.html:30
+#: mediagoblin/templates/mediagoblin/auth/register.html:31
msgid "Create"
msgstr "建立"
@@ -360,7 +363,7 @@ msgstr "媒體檔案被標籤為:"
msgid "Submit yer media"
msgstr "遞交你的媒體檔案"
-#: mediagoblin/templates/mediagoblin/submit/start.html:29
+#: mediagoblin/templates/mediagoblin/submit/start.html:30
msgid "Submit"
msgstr "送出"
@@ -381,7 +384,7 @@ msgstr "真的要刪除 %(title)s?"
#: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50
msgid "Delete Permanently"
-msgstr ""
+msgstr "永遠刪除"
#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:22
msgid "Media processing panel"
@@ -486,11 +489,11 @@ msgstr "Atom feed"
#: mediagoblin/templates/mediagoblin/utils/pagination.html:40
msgid "Newer"
-msgstr ""
+msgstr "新一點"
#: mediagoblin/templates/mediagoblin/utils/pagination.html:46
msgid "Older"
-msgstr ""
+msgstr "舊一點"
#: mediagoblin/user_pages/forms.py:24
msgid "Comment"
@@ -498,9 +501,17 @@ msgstr "評論"
#: mediagoblin/user_pages/forms.py:30
msgid "I am sure I want to delete this"
+msgstr "我確定我想要刪除"
+
+#: mediagoblin/user_pages/views.py:142
+msgid "Empty comments are not allowed."
+msgstr ""
+
+#: mediagoblin/user_pages/views.py:148
+msgid "Comment posted!"
msgstr ""
-#: mediagoblin/user_pages/views.py:175
+#: mediagoblin/user_pages/views.py:181
msgid "You are about to delete another user's media. Proceed with caution."
msgstr "你在刪除其他人的媒體檔案。請小心處理喔。"
diff --git a/mediagoblin/init/__init__.py b/mediagoblin/init/__init__.py
index b7f52595..08a0618d 100644
--- a/mediagoblin/init/__init__.py
+++ b/mediagoblin/init/__init__.py
@@ -29,8 +29,12 @@ from mediagoblin.workbench import WorkbenchManager
from mediagoblin.storage import storage_system_from_config
-class Error(Exception): pass
-class ImproperlyConfigured(Error): pass
+class Error(Exception):
+ pass
+
+
+class ImproperlyConfigured(Error):
+ pass
def setup_global_and_app_config(config_path):
@@ -76,8 +80,8 @@ def setup_database():
"in fact they appear to be from the future?!")
setup_globals(
- db_connection = connection,
- database = db)
+ db_connection=connection,
+ database=db)
return connection, db
@@ -99,10 +103,10 @@ def get_jinja_loader(user_template_path=None):
def get_staticdirector(app_config):
- if app_config.has_key('direct_remote_path'):
+ if 'direct_remote_path' in app_config:
return staticdirect.RemoteStaticDirect(
app_config['direct_remote_path'].strip())
- elif app_config.has_key('direct_remote_paths'):
+ elif 'direct_remote_paths' in app_config:
direct_remote_path_lines = app_config[
'direct_remote_paths'].strip().splitlines()
return staticdirect.MultiRemoteStaticDirect(
@@ -126,8 +130,8 @@ def setup_storage():
queue_store = storage_system_from_config(global_config[key_long])
setup_globals(
- public_store = public_store,
- queue_store = queue_store)
+ public_store=public_store,
+ queue_store=queue_store)
return public_store, queue_store
@@ -137,7 +141,7 @@ def setup_workbench():
workbench_manager = WorkbenchManager(app_config['workbench_path'])
- setup_globals(workbench_manager = workbench_manager)
+ setup_globals(workbench_manager=workbench_manager)
def setup_beaker_cache():
diff --git a/mediagoblin/init/celery/__init__.py b/mediagoblin/init/celery/__init__.py
index c5d37420..a62d40e3 100644
--- a/mediagoblin/init/celery/__init__.py
+++ b/mediagoblin/init/celery/__init__.py
@@ -42,25 +42,25 @@ def setup_celery_from_config(app_config, global_config,
- set_environ: if set, this will CELERY_CONFIG_MODULE to the
settings_module
"""
- if global_config.has_key('celery'):
+ if 'celery' in global_config:
celery_conf = global_config['celery']
else:
celery_conf = {}
-
+
celery_settings = {}
# set up mongodb stuff
celery_settings['CELERY_RESULT_BACKEND'] = 'mongodb'
- if not celery_settings.has_key('BROKER_BACKEND'):
+ if 'BROKER_BACKEND' not in celery_settings:
celery_settings['BROKER_BACKEND'] = 'mongodb'
celery_mongo_settings = {}
- if app_config.has_key('db_host'):
+ if 'db_host' in app_config:
celery_mongo_settings['host'] = app_config['db_host']
if celery_settings['BROKER_BACKEND'] == 'mongodb':
celery_settings['BROKER_HOST'] = app_config['db_host']
- if app_config.has_key('db_port'):
+ if 'db_port' in app_config:
celery_mongo_settings['port'] = app_config['db_port']
if celery_settings['BROKER_BACKEND'] == 'mongodb':
celery_settings['BROKER_PORT'] = app_config['db_port']
@@ -86,6 +86,6 @@ def setup_celery_from_config(app_config, global_config,
for key, value in celery_settings.iteritems():
setattr(this_module, key, value)
-
+
if set_environ:
os.environ['CELERY_CONFIG_MODULE'] = settings_module
diff --git a/mediagoblin/init/celery/from_celery.py b/mediagoblin/init/celery/from_celery.py
index 3e5adb98..05669b67 100644
--- a/mediagoblin/init/celery/from_celery.py
+++ b/mediagoblin/init/celery/from_celery.py
@@ -44,7 +44,7 @@ def setup_self(check_environ_for_conf=True, module_name=OUR_MODULENAME,
if not os.path.exists(mgoblin_conf_file):
raise IOError(
"MEDIAGOBLIN_CONFIG not set or file does not exist")
-
+
# By setting the environment variable here we should ensure that
# this is the module that gets set up.
os.environ['CELERY_CONFIG_MODULE'] = module_name
diff --git a/mediagoblin/init/config.py b/mediagoblin/init/config.py
index 029a0956..ae232e91 100644
--- a/mediagoblin/init/config.py
+++ b/mediagoblin/init/config.py
@@ -73,7 +73,7 @@ def read_mediagoblin_config(config_path, config_spec=CONFIG_SPEC_PATH):
# For now the validator just works with the default functions,
# but in the future if we want to add additional validation/configuration
# functions we'd add them to validator.functions here.
- #
+ #
# See also:
# http://www.voidspace.org.uk/python/validate.html#adding-functions
validator = Validator()
diff --git a/mediagoblin/listings/routing.py b/mediagoblin/listings/routing.py
index b72bd015..234f2595 100644
--- a/mediagoblin/listings/routing.py
+++ b/mediagoblin/listings/routing.py
@@ -25,4 +25,3 @@ tag_routes = [
Route('mediagoblin.listings.tag_atom_feed', "/{tag}/atom/",
controller="mediagoblin.listings.views:tag_atom_feed"),
]
-
diff --git a/mediagoblin/listings/views.py b/mediagoblin/listings/views.py
index b3384eb4..12e539e7 100644
--- a/mediagoblin/listings/views.py
+++ b/mediagoblin/listings/views.py
@@ -16,7 +16,8 @@
from mediagoblin.db.util import DESCENDING
-from mediagoblin.util import Pagination, render_to_response
+from mediagoblin.tools.pagination import Pagination
+from mediagoblin.tools.response import render_to_response
from mediagoblin.decorators import uses_pagination
from werkzeug.contrib.atom import AtomFeed
@@ -46,7 +47,7 @@ def tag_listing(request, page):
{u'state': u'processed',
u'tags.slug': tag_slug})
cursor = cursor.sort('created', DESCENDING)
-
+
pagination = Pagination(page, cursor)
media_entries = pagination()
@@ -63,6 +64,7 @@ def tag_listing(request, page):
ATOM_DEFAULT_NR_OF_UPDATED_ITEMS = 15
+
def tag_atom_feed(request):
"""
generates the atom feed with the tag images
diff --git a/mediagoblin/messages.py b/mediagoblin/messages.py
index dc82fbf6..054d46c0 100644
--- a/mediagoblin/messages.py
+++ b/mediagoblin/messages.py
@@ -20,11 +20,13 @@ SUCCESS = 'success'
WARNING = 'warning'
ERROR = 'error'
+
def add_message(request, level, text):
messages = request.session.setdefault('messages', [])
messages.append({'level': level, 'text': text})
request.session.save()
+
def fetch_messages(request, clear_from_session=True):
messages = request.session.get('messages')
if messages and clear_from_session:
diff --git a/mediagoblin/middleware/__init__.py b/mediagoblin/middleware/__init__.py
index 586debbf..05325ee5 100644
--- a/mediagoblin/middleware/__init__.py
+++ b/mediagoblin/middleware/__init__.py
@@ -16,4 +16,5 @@
ENABLED_MIDDLEWARE = (
'mediagoblin.middleware.noop:NoOpMiddleware',
+ 'mediagoblin.middleware.csrf:CsrfMiddleware',
)
diff --git a/mediagoblin/middleware/csrf.py b/mediagoblin/middleware/csrf.py
new file mode 100644
index 00000000..8275c18e
--- /dev/null
+++ b/mediagoblin/middleware/csrf.py
@@ -0,0 +1,132 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 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 hashlib
+import random
+
+from webob.exc import HTTPForbidden
+from wtforms import Form, HiddenField, validators
+
+from mediagoblin import mg_globals
+
+# Use the system (hardware-based) random number generator if it exists.
+# -- this optimization is lifted from Django
+if hasattr(random, 'SystemRandom'):
+ getrandbits = random.SystemRandom().getrandbits
+else:
+ getrandbits = random.getrandbits
+
+
+class CsrfForm(Form):
+ """Simple form to handle rendering a CSRF token and confirming it
+ is included in the POST."""
+
+ csrf_token = HiddenField("",
+ [validators.Required()])
+
+
+def render_csrf_form_token(request):
+ """Render the CSRF token in a format suitable for inclusion in a
+ form."""
+
+ form = CsrfForm(csrf_token=request.environ['CSRF_TOKEN'])
+
+ return form.csrf_token
+
+
+class CsrfMiddleware(object):
+ """CSRF Protection Middleware
+
+ Adds a CSRF Cookie to responses and verifies that it is present
+ and matches the form token for non-safe requests.
+ """
+
+ CSRF_KEYLEN = 64
+ SAFE_HTTP_METHODS = ("GET", "HEAD", "OPTIONS", "TRACE")
+
+ def __init__(self, mg_app):
+ self.app = mg_app
+
+ def process_request(self, request):
+ """For non-safe requests, confirm that the tokens are present
+ and match.
+ """
+
+ # get the token from the cookie
+ try:
+ request.environ['CSRF_TOKEN'] = \
+ request.cookies[mg_globals.app_config['csrf_cookie_name']]
+
+ except KeyError, e:
+ # if it doesn't exist, make a new one
+ request.environ['CSRF_TOKEN'] = self._make_token(request)
+
+ # if this is a non-"safe" request (ie, one that could have
+ # side effects), confirm that the CSRF tokens are present and
+ # valid
+ if request.method not in self.SAFE_HTTP_METHODS \
+ and ('gmg.verify_csrf' in request.environ or
+ 'paste.testing' not in request.environ):
+
+ return self.verify_tokens(request)
+
+ def process_response(self, request, response):
+ """Add the CSRF cookie to the response if needed and set Vary
+ headers.
+ """
+
+ # set the CSRF cookie
+ response.set_cookie(
+ mg_globals.app_config['csrf_cookie_name'],
+ request.environ['CSRF_TOKEN'],
+ path=request.environ['SCRIPT_NAME'],
+ domain=mg_globals.app_config.get('csrf_cookie_domain'),
+ secure=(request.scheme.lower() == 'https'),
+ httponly=True)
+
+ # update the Vary header
+ response.vary = (getattr(response, 'vary', None) or []) + ['Cookie']
+
+ def _make_token(self, request):
+ """Generate a new token to use for CSRF protection."""
+
+ return "%s" % (getrandbits(self.CSRF_KEYLEN),)
+
+ def verify_tokens(self, request):
+ """Verify that the CSRF Cookie exists and that it matches the
+ form value."""
+
+ # confirm the cookie token was presented
+ cookie_token = request.cookies.get(
+ mg_globals.app_config['csrf_cookie_name'],
+ None)
+
+ if cookie_token is None:
+ # the CSRF cookie must be present in the request
+ return HTTPForbidden()
+
+ # get the form token and confirm it matches
+ form = CsrfForm(request.POST)
+ if form.validate():
+ form_token = form.csrf_token.data
+
+ if form_token == cookie_token:
+ # all's well that ends well
+ return
+
+ # either the tokens didn't match or the form token wasn't
+ # present; either way, the request is denied
+ return HTTPForbidden()
diff --git a/mediagoblin/middleware/noop.py b/mediagoblin/middleware/noop.py
index 28380232..820b5d9e 100644
--- a/mediagoblin/middleware/noop.py
+++ b/mediagoblin/middleware/noop.py
@@ -14,6 +14,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
class NoOpMiddleware(object):
def __init__(self, mg_app):
diff --git a/mediagoblin/process_media/__init__.py b/mediagoblin/process_media/__init__.py
index 96fe49fe..346bb479 100644
--- a/mediagoblin/process_media/__init__.py
+++ b/mediagoblin/process_media/__init__.py
@@ -14,8 +14,9 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import Image
+import os
+import Image
from celery.task import Task
from celery import registry
@@ -31,7 +32,7 @@ MEDIUM_SIZE = 640, 640
def create_pub_filepath(entry, filename):
return mgg.public_store.get_unique_filepath(
['media_entries',
- unicode(entry['_id']),
+ unicode(entry._id),
filename])
@@ -56,7 +57,7 @@ class ProcessMedia(Task):
__import__(entry['media_type'])
process_image(entry)
except BaseProcessingFail, exc:
- mark_entry_failed(entry[u'_id'], exc)
+ mark_entry_failed(entry._id, exc)
return
except ImportError, exc:
mark_entry_failed(entry[u'_id'], exc)
@@ -68,9 +69,10 @@ class ProcessMedia(Task):
"""
If the processing failed we should mark that in the database.
- Assuming that the exception raised is a subclass of BaseProcessingFail,
- we can use that to get more information about the failure and store that
- for conveying information to users about the failure, etc.
+ Assuming that the exception raised is a subclass of
+ BaseProcessingFail, we can use that to get more information
+ about the failure and store that for conveying information to
+ users about the failure, etc.
"""
entry_id = args[0]
mark_entry_failed(entry_id, exc)
@@ -83,10 +85,10 @@ def mark_entry_failed(entry_id, exc):
"""
Mark a media entry as having failed in its conversion.
- Uses the exception that was raised to mark more information. If the
- exception is a derivative of BaseProcessingFail then we can store extra
- information that can be useful for users telling them why their media failed
- to process.
+ Uses the exception that was raised to mark more information. If
+ the exception is a derivative of BaseProcessingFail then we can
+ store extra information that can be useful for users telling them
+ why their media failed to process.
Args:
- entry_id: The id of the media entry
@@ -119,27 +121,34 @@ def process_image(entry):
Code to process an image
"""
workbench = mgg.workbench_manager.create_workbench()
+ # Conversions subdirectory to avoid collisions
+ conversions_subdir = os.path.join(
+ workbench.dir, 'conversions')
+ os.mkdir(conversions_subdir)
queued_filepath = entry['queued_media_file']
queued_filename = workbench.localized_file(
mgg.queue_store, queued_filepath,
'source')
+ extension = os.path.splitext(queued_filename)[1]
+
try:
thumb = Image.open(queued_filename)
except IOError:
raise BadMediaFail()
thumb.thumbnail(THUMB_SIZE, Image.ANTIALIAS)
- # ensure color mode is compatible with jpg
- if thumb.mode != "RGB":
- thumb = thumb.convert("RGB")
-
- thumb_filepath = create_pub_filepath(entry, 'thumbnail.jpg')
- thumb_file = mgg.public_store.get_file(thumb_filepath, 'w')
- with thumb_file:
- thumb.save(thumb_file, "JPEG", quality=90)
+ # Copy the thumb to the conversion subdir, then remotely.
+ thumb_filename = 'thumbnail' + extension
+ thumb_filepath = create_pub_filepath(entry, thumb_filename)
+ tmp_thumb_filename = os.path.join(
+ conversions_subdir, thumb_filename)
+ with file(tmp_thumb_filename, 'w') as thumb_file:
+ thumb.save(thumb_file)
+ mgg.public_store.copy_local_to_storage(
+ tmp_thumb_filename, thumb_filepath)
# If the size of the original file exceeds the specified size of a `medium`
# file, a `medium.jpg` files is created and later associated with the media
@@ -150,15 +159,18 @@ def process_image(entry):
if medium.size[0] > MEDIUM_SIZE[0] or medium.size[1] > MEDIUM_SIZE[1]:
medium.thumbnail(MEDIUM_SIZE, Image.ANTIALIAS)
- if medium.mode != "RGB":
- medium = medium.convert("RGB")
+ medium_filename = 'medium' + extension
+ medium_filepath = create_pub_filepath(entry, medium_filename)
+ tmp_medium_filename = os.path.join(
+ conversions_subdir, medium_filename)
+
+ with file(tmp_medium_filename, 'w') as medium_file:
+ medium.save(medium_file)
- medium_filepath = create_pub_filepath(entry, 'medium.jpg')
- medium_file = mgg.public_store.get_file(medium_filepath, 'w')
+ mgg.public_store.copy_local_to_storage(
+ tmp_medium_filename, medium_filepath)
- with medium_file:
- medium.save(medium_file, "JPEG", quality=90)
- medium_processed = True
+ medium_processed = True
# we have to re-read because unlike PIL, not everything reads
# things in string representation :)
@@ -167,7 +179,8 @@ def process_image(entry):
with queued_file:
original_filepath = create_pub_filepath(entry, queued_filepath[-1])
- with mgg.public_store.get_file(original_filepath, 'wb') as original_file:
+ with mgg.public_store.get_file(original_filepath, 'wb') \
+ as original_file:
original_file.write(queued_file.read())
mgg.queue_store.delete_file(queued_filepath)
diff --git a/mediagoblin/process_media/errors.py b/mediagoblin/process_media/errors.py
index 156f0a01..4224a3e1 100644
--- a/mediagoblin/process_media/errors.py
+++ b/mediagoblin/process_media/errors.py
@@ -14,19 +14,20 @@
# 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.util import lazy_pass_to_ugettext as _
+from mediagoblin.tools.translate import lazy_pass_to_ugettext as _
+
class BaseProcessingFail(Exception):
"""
Base exception that all other processing failure messages should
subclass from.
-
+
You shouldn't call this itself; instead you should subclass it
and provid the exception_path and general_message applicable to
this error.
"""
general_message = u''
-
+
@property
def exception_path(self):
return u"%s:%s" % (
@@ -34,8 +35,8 @@ class BaseProcessingFail(Exception):
def __init__(self, **metadata):
self.metadata = metadata or {}
-
-
+
+
class BadMediaFail(BaseProcessingFail):
"""
Error that should be raised when an inappropriate file was given
diff --git a/mediagoblin/static/css/base.css b/mediagoblin/static/css/base.css
index b108cc9e..12d88ffa 100644
--- a/mediagoblin/static/css/base.css
+++ b/mediagoblin/static/css/base.css
@@ -22,7 +22,7 @@
font-family: 'Lato';
font-style: normal;
font-weight: 400;
- src: local('Lato Regular'), local('Lato-Regular'), url('../fonts/Lato-Regular.woff') format('truetype');
+ src: local('Lato Regular'), local('Lato-Regular'), url('../fonts/Lato-Regular.ttf') format('truetype');
}
body {
@@ -98,30 +98,6 @@ a.mediagoblin_logo{
font-weight: bold;
}
-.header_submit, .header_submit_highlight{
- color: #272727;
- background-color: #aaa;
- background-image: -webkit-gradient(linear, left top, left bottom, from(##D2D2D2), to(#aaa));
- background-image: -webkit-linear-gradient(top, #D2D2D2, #aaa);
- background-image: -moz-linear-gradient(top, #D2D2D2, #aaa);
- background-image: -ms-linear-gradient(top, #D2D2D2, #aaa);
- background-image: -o-linear-gradient(top, #D2D2D2, #aaa);
- background-image: linear-gradient(top, #D2D2D2, #aaa);
- box-shadow: 0px 0px 4px #000;
- border-radius: 3px;
- margin: 8px;
- padding: 3px 8px;
- text-decoration: none;
- border: medium none;
- font-style: normal;
- font-weight: bold;
- font-size: 1em;
-}
-
-.header_submit_highlight{
-background-image: -moz-linear-gradient(center top , rgb(134, 212, 177), rgb(109, 173, 144));
-}
-
.mediagoblin_footer {
height: 30px;
border-top: 1px solid #333;
@@ -141,7 +117,28 @@ background-image: -moz-linear-gradient(center top , rgb(134, 212, 177), rgb(109,
/* common website elements */
-.button, .cancel_link {
+.button_action, .button_action_highlight{
+ color: #c3c3c3;
+ background-color: #363636;
+ border: 1px solid;
+ border-color: #464646 #2B2B2B #252525;
+ border-radius: 4px;
+ margin: 8px;
+ padding: 3px 8px;
+ text-decoration: none;
+ font-style: normal;
+ font-weight: bold;
+ font-size: 1em;
+}
+
+.button_action_highlight{
+ background-color: #86D4B1;
+ border-color: #A2DEC3 #6CAA8E #5C9179;
+ color: #283F35;
+}
+
+
+.button_form, .cancel_link {
height: 32px;
min-width: 99px;
background-color: #86d4b1;
@@ -161,7 +158,6 @@ background-image: -moz-linear-gradient(center top , rgb(134, 212, 177), rgb(109,
padding-right: 11px;
text-decoration: none;
font-family: 'Lato', sans-serif;
- font-size: 1.2em;
font-weight: bold;
}
@@ -184,7 +180,7 @@ text-align: center;
}
.empty_space{
- background-color: #222;
+ background-image: url("../images/empty_back.png");
font-style: italic;
text-align: center;
height: 160px;
@@ -213,11 +209,11 @@ text-align: center;
width: 100%;
}
-.form_field_box {
- margin-bottom: 24px;
+.form_field_input {
+ margin-bottom: 10px;
}
-.form_field_label,.form_field_input {
+.form_field_label {
margin-bottom: 4px;
}
@@ -250,8 +246,12 @@ text-align: center;
font-size: 0.9em;
}
+.comment_content {
+ margin-bottom: 30px;
+}
+
.comment_content p {
- margin-bottom: 4px;
+ margin-bottom: 0px;
}
/* media galleries */
@@ -291,23 +291,22 @@ img.media_icon{
/* navigation */
.navigation_button{
- width: 139px;
+ width: 135px;
display: block;
float: left;
text-align: center;
- background-color: #333;
+ background-color: #1d1d1d;
+ border: 1px solid;
+ border-color: #2c2c2c #232323 #1a1a1a;
+ border-radius: 4px;
text-decoration: none;
- padding: 12px 0pt;
- font-size: 2em;
+ padding: 12px 0 16px;
+ font-size: 1.4em;
margin: 0 0 20px
}
-p.navigation_button{
- color: #272727;
-}
-
.navigation_left{
- margin-right: 2px;
+ margin-right: 6px;
}
/* messages */
diff --git a/mediagoblin/static/images/empty_back.png b/mediagoblin/static/images/empty_back.png
new file mode 100644
index 00000000..3522ddd3
--- /dev/null
+++ b/mediagoblin/static/images/empty_back.png
Binary files differ
diff --git a/mediagoblin/static/images/icon_comment.png b/mediagoblin/static/images/icon_comment.png
new file mode 100644
index 00000000..76860a92
--- /dev/null
+++ b/mediagoblin/static/images/icon_comment.png
Binary files differ
diff --git a/mediagoblin/static/images/icon_delete.png b/mediagoblin/static/images/icon_delete.png
deleted file mode 100644
index 9d76a5db..00000000
--- a/mediagoblin/static/images/icon_delete.png
+++ /dev/null
Binary files differ
diff --git a/mediagoblin/static/images/icon_edit.png b/mediagoblin/static/images/icon_edit.png
deleted file mode 100644
index 480c73ad..00000000
--- a/mediagoblin/static/images/icon_edit.png
+++ /dev/null
Binary files differ
diff --git a/mediagoblin/static/images/logo.png b/mediagoblin/static/images/logo.png
index 1c08a2fb..b40e58fb 100644
--- a/mediagoblin/static/images/logo.png
+++ b/mediagoblin/static/images/logo.png
Binary files differ
diff --git a/mediagoblin/static/images/logo.svg b/mediagoblin/static/images/logo.svg
new file mode 100644
index 00000000..f236a597
--- /dev/null
+++ b/mediagoblin/static/images/logo.svg
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="554"
+ height="101.99998"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.48.2 r9819"
+ sodipodi:docname="mediagoblin.svg"
+ inkscape:export-filename="mediagoblin.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs4" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1"
+ inkscape:cx="279.13053"
+ inkscape:cy="65.605728"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ borderlayer="true"
+ inkscape:showpageshadow="false"
+ inkscape:window-width="1280"
+ inkscape:window-height="1000"
+ inkscape:window-x="0"
+ inkscape:window-y="24"
+ inkscape:window-maximized="1"
+ inkscape:snap-bbox="true"
+ inkscape:bbox-paths="true"
+ inkscape:bbox-nodes="true"
+ inkscape:snap-bbox-midpoints="true"
+ inkscape:snap-bbox-edge-midpoints="true"
+ inkscape:object-paths="true"
+ inkscape:object-nodes="true"
+ inkscape:snap-midpoints="true"
+ inkscape:snap-smooth-nodes="true"
+ inkscape:snap-intersection-paths="true"
+ inkscape:snap-object-midpoints="true"
+ inkscape:snap-center="true"
+ inkscape:snap-page="true"
+ showguides="false"
+ inkscape:guide-bbox="true"
+ inkscape:snap-global="true"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ showborder="false">
+ <sodipodi:guide
+ orientation="1,0"
+ position="1062.0155,252.54874"
+ id="guide3002" />
+ <inkscape:grid
+ type="xygrid"
+ id="grid4021"
+ empspacing="5"
+ visible="true"
+ enabled="true"
+ snapvisiblegridlinesonly="true" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="62.322892,118.88571"
+ id="guide3814" />
+ <sodipodi:guide
+ orientation="0,1"
+ position="154.25003,65.249969"
+ id="guide3816" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="main"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(865.93433,-886.66071)">
+ <g
+ id="g3010"
+ transform="matrix(0.68692139,0,0,0.52224846,-26.609327,197.42947)" />
+ <g
+ id="g3951"
+ transform="matrix(0.75599155,0,0,0.75599155,-269.59547,339.3242)" />
+ <g
+ transform="matrix(0.75599155,0,0,0.75599155,5.8142558,339.3242)"
+ id="g3969" />
+ <path
+ id="path3051"
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:11;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
+ d="m -498.47812,909.8741 c -14.29997,-0.25966 -24.30551,9.34241 -26.50888,22.91161 -2.4313,14.97291 6.8419,28.27685 20.6875,30.5 13.84559,2.22316 27.00531,-7.50109 29.46875,-22.46875 2.41774,-14.68996 -7.14681,-30.64325 -23.64737,-30.94286 z m -1.10263,8.03661 c 11.82552,0.0748 16.8356,12.60864 15.5625,21.78125 -1.4685,10.58046 -9.88714,17.25696 -18.65625,15.6875 -8.7691,-1.56946 -14.66487,-10.77344 -13.125,-21.34375 1.3955,-9.57934 8.39284,-16.17451 16.21875,-16.125 z m 130.09735,-24.04343 c 0,3.62036 -2.93488,6.55525 -6.55524,6.55525 -3.62036,0 -6.55524,-2.93489 -6.55524,-6.55525 0,-3.62036 2.93488,-6.55524 6.55524,-6.55524 3.62036,0 6.55524,2.93488 6.55524,6.55524 z m -11.15801,16.87173 0,51.92717 9.20553,0 0,-51.92717 z m -280.41892,6e-5 0,51.92717 9.20553,0 0,-51.92717 z m 11.15802,-16.87173 c 0,3.62036 -2.93488,6.55525 -6.55524,6.55525 -3.62037,0 -6.55525,-2.93489 -6.55525,-6.55525 0,-3.62036 2.93488,-6.55524 6.55525,-6.55524 3.62036,0 6.55524,2.93488 6.55524,6.55524 z m 91.82766,15.94962 c -17.68301,0 -26.96853,15.66588 -26.96875,26.8125 -3.2e-4,16.07708 10.57093,26.13091 23.6875,26.875 4.79063,0.27178 11.67595,-0.19435 17.96875,-6.34375 0.25,15.44904 -3.39617,22.87085 -13.875,23.25 -7.92125,0.28661 -13.39214,-3.93545 -15.75595,-10.70298 l -7.46875,0 c 1.52404,7.39528 6.81992,18.97887 23.75595,18.64048 16.96269,-0.33892 22.5625,-13.84938 22.5625,-30.6875 l 0,-29.5625 c -0.0225,-6.25597 0.90001,-12.00727 2.71875,-17.34375 l -7.4375,0 c -0.95827,2.12785 -1.63064,4.94081 -2.27681,7.63925 -3.53047,-5.63263 -9.91399,-8.57675 -16.91069,-8.57675 z m 15.09375,27.75 c 0,9.35634 -7.1389,18.15625 -17.21875,18.15625 -10.36378,0 -15.59375,-9.243 -15.59375,-18.28125 0,-7.95083 4.08876,-18.88021 16.15625,-19.65625 7.84943,-0.50479 16.39174,7.25265 16.65625,19.78125 z m -143.1507,-50.84375 0,29.03125 c -3.26199,-4.21342 -10.81819,-6.62398 -16.34375,-6.3125 -17.88151,1.00802 -25.3123,17.2168 -25.3125,27.25 -3.2e-4,16.07708 10.47719,26.7559 23.59375,27.5 5.19493,0.29471 13.81969,-1.57948 19.625,-9.1875 0.60295,2.26134 1.86305,5.37114 3.15625,7.65625 l 7.4375,0 c -2.12044,-5.15404 -2.9375,-10.37795 -2.9375,-18.53125 l 0,-57.40625 z m -16.34375,30.875 c 12.02937,-0.0869 16.24638,9.43483 16.65625,19.59375 0,11.03464 -8.39635,19.0625 -17.21875,19.0625 -9.45765,0 -15.76506,-9.58978 -15.53125,-18.625 0.20843,-8.0541 4.61687,-19.94837 16.09375,-20.03125 z m -54.5723,-7.71875 c -14.69916,0 -25.74033,13.03618 -25.75,27.4375 -0.01,14.78695 10.244,26.125 23.65625,26.125 13.17686,0 17.98713,-4.04194 21.40625,-7.1875 l -4.3125,-5.0625 c -3.0707,2.07296 -7.16015,4.5625 -15.96875,4.5625 -7.45652,0 -14.61337,-5.22342 -15.5625,-14.375 12.17349,2.42928 34.34076,3.97324 38.34375,-8.3125 4.15154,-12.74162 -9.23233,-23.1875 -21.8125,-23.1875 z m -0.1875,7.875 c 7.44103,-0.28295 15.86681,7.08099 13.34375,12.5625 -1.07884,2.34384 -4.36121,3.84759 -11.0625,4.1875 -4.72973,0.2399 -11.67545,0.0602 -18.53125,-1.53125 1.38994,-7.13675 6.98538,-14.86646 16.25,-15.21875 z m 138.94915,-7.84375 c -6.22358,0 -12.35769,2.10385 -17.4375,5.78125 l 3.75,5.65625 c 4.03537,-2.17319 9.28716,-3.79268 14.34375,-3.46875 6.55828,0.42013 14.7598,2.73287 14.7598,14.233 -1.85084,-1.38482 -9.08908,-2.44485 -13.54105,-2.57675 -13.63282,-0.40393 -22.07092,5.70413 -22.86428,15.3125 -1.14325,13.84598 10.26769,18.625 20.33303,18.625 7.39807,5.2e-4 15.35814,-5.72151 17,-8.4375 0.43984,2.49906 2.01961,5.57335 3.125,7.625 l 7.46875,0 c -2.12043,-5.15404 -2.96875,-10.37795 -2.96875,-18.53125 l 0,-9.84375 c 0,-24.39387 -18.81089,-24.375 -23.96875,-24.375 z m 0.78125,27.4375 c 8.05656,-0.0156 14.8125,1.66674 14.8125,4.01961 0,6.72106 -7.55371,13.8524 -16.4375,14.23039 -4.54841,0.19353 -11.57496,-2.09719 -11.48928,-9.59375 0.0808,-7.06964 7.87645,-8.64609 13.11428,-8.65625 z m -223.80458,-27.53125 c -7.78959,0 -12.57316,3.37364 -14.53125,6.625 -0.75834,-1.89688 -1.49654,-3.84633 -2.375,-5.6875 l -7.4375,0 c 2.20887,5.93379 2.73712,12.19296 2.71875,17.3125 l 0,34.59375 9.21875,0 0,-34.78125 c 0,-6.65558 6.44423,-10.26976 12.4375,-10.40625 6.57556,-0.14975 9.05752,3.56709 9.125,8.90625 l 0,36.28125 9.1875,0 0,-34.78125 c 0,-6.65558 6.44424,-10.26976 12.4375,-10.40625 6.57556,-0.14975 9.18251,3.56709 9.25,8.90625 l 0,36.28125 9.21875,0 0,-36.28125 c 0,-11.16352 -8.04836,-16.5625 -18.5,-16.5625 -7.68395,0 -13.41885,3.49982 -15.34375,6.53125 -3.21828,-4.38545 -8.81153,-6.53125 -15.40625,-6.53125 z m 435.58675,-23.11502 0,60.98954 c 0,4.50655 1.82444,11.36243 4.13429,14.95446 l 7.46542,0 c -1.71595,-4.95183 -2.38614,-11.95254 -2.38614,-18.52179 l 0,-57.42221 z m -59.85447,0.0213 0,57.40625 c 0,8.48573 -0.72207,13.98198 -2.5625,18.53125 l 7.46875,0 c 0.49268,-1.18272 1.50645,-4.57275 2.125,-6.375 3.2358,3.63861 9.91843,7.15293 16.6875,7.28125 17.0179,0 26.83165,-13.62855 27.09375,-25.84375 0.32424,-15.11836 -9.23098,-28.09919 -25.40625,-27.96875 -7.10965,0.0573 -12.81683,3.2018 -16.1875,7.1875 l 0,-30.21875 -9.21875,0 z m 25.125,30.96875 c 0.34959,-0.0146 0.70152,-0.008 1.0625,0 6.22899,0.13299 15.65387,5.56214 15.4375,19.65625 -0.16934,11.02718 -8.18402,18.37679 -16.84375,18.34375 -11.39711,-0.0435 -15.84382,-8.59471 -15.84375,-18.8125 0,-7.75719 5.35029,-18.73358 16.1875,-19.1875 z m 107.7562,-7.80926 c -7.78958,0 -13.83625,3.29749 -15.79433,6.54885 -0.67753,-1.63171 -1.5038,-3.80006 -2.38135,-5.68127 l -7.4404,0 c 2.20887,5.93379 2.75814,12.20005 2.73977,17.31959 l 0,34.58661 9.20554,0 0,-34.77561 c 0,-6.65558 7.70716,-9.7658 13.70041,-9.90229 6.57556,-0.14975 10.98867,3.05115 11.05615,8.39031 l 0,36.28759 9.20552,0 0,-36.28759 c 0,-11.16352 -9.83967,-16.48619 -20.29131,-16.48619 z"
+ inkscape:connector-curvature="0" />
+ </g>
+</svg>
diff --git a/mediagoblin/static/images/navigation_end.png b/mediagoblin/static/images/navigation_end.png
deleted file mode 100644
index b2f27296..00000000
--- a/mediagoblin/static/images/navigation_end.png
+++ /dev/null
Binary files differ
diff --git a/mediagoblin/static/images/navigation_left.png b/mediagoblin/static/images/navigation_left.png
deleted file mode 100644
index d1645120..00000000
--- a/mediagoblin/static/images/navigation_left.png
+++ /dev/null
Binary files differ
diff --git a/mediagoblin/static/images/navigation_right.png b/mediagoblin/static/images/navigation_right.png
deleted file mode 100644
index d4caa7b8..00000000
--- a/mediagoblin/static/images/navigation_right.png
+++ /dev/null
Binary files differ
diff --git a/mediagoblin/staticdirect.py b/mediagoblin/staticdirect.py
index 58175881..c6d2b374 100644
--- a/mediagoblin/staticdirect.py
+++ b/mediagoblin/staticdirect.py
@@ -21,24 +21,24 @@ import urlparse
# Staticdirect infrastructure.
# Borrowed largely from cc.engine
# by Chris Webber & Creative Commons
-#
+#
# This needs documentation!
####################################
import pkg_resources
import urlparse
+
class StaticDirect(object):
def __init__(self):
self.cache = {}
def __call__(self, filepath):
- if self.cache.has_key(filepath):
+ if filepath in self.cache:
return self.cache[filepath]
static_direction = self.cache[filepath] = self.get(filepath)
return static_direction
-
def get(self, filepath):
# should be implemented by the individual staticdirector
diff --git a/mediagoblin/storage/__init__.py b/mediagoblin/storage/__init__.py
index 8665d9e5..0840614b 100644
--- a/mediagoblin/storage/__init__.py
+++ b/mediagoblin/storage/__init__.py
@@ -21,7 +21,7 @@ import uuid
from werkzeug.utils import secure_filename
-from mediagoblin import util
+from mediagoblin.tools import common
########
# Errors
@@ -169,6 +169,18 @@ class StorageInterface(object):
with file(dest_path, 'wb') as dest_file:
dest_file.write(source_file.read())
+ def copy_local_to_storage(self, filename, filepath):
+ """
+ Copy this file from locally to the storage system.
+
+ This is kind of the opposite of copy_locally. It's likely you
+ could override this method with something more appropriate to
+ your storage system.
+ """
+ with self.get_file(filepath, 'wb') as dest_file:
+ with file(filename, 'rb') as source_file:
+ dest_file.write(source_file.read())
+
###########
# Utilities
@@ -236,5 +248,5 @@ def storage_system_from_config(config_section):
else:
storage_class = 'mediagoblin.storage.filestorage:BasicFileStorage'
- storage_class = util.import_component(storage_class)
+ storage_class = common.import_component(storage_class)
return storage_class(**config_params)
diff --git a/mediagoblin/storage/cloudfiles.py b/mediagoblin/storage/cloudfiles.py
index 85d52242..51b73579 100644
--- a/mediagoblin/storage/cloudfiles.py
+++ b/mediagoblin/storage/cloudfiles.py
@@ -27,6 +27,7 @@ from mediagoblin.storage import StorageInterface, clean_listy_filepath
import cloudfiles
import mimetypes
+
class CloudFilesStorage(StorageInterface):
'''
OpenStack/Rackspace Cloud's Swift/CloudFiles support
diff --git a/mediagoblin/storage/filestorage.py b/mediagoblin/storage/filestorage.py
index 22d6eb5a..a904865f 100644
--- a/mediagoblin/storage/filestorage.py
+++ b/mediagoblin/storage/filestorage.py
@@ -20,6 +20,7 @@ from mediagoblin.storage import (
NoWebServing)
import os
+import shutil
import urlparse
@@ -76,3 +77,16 @@ class BasicFileStorage(StorageInterface):
def get_local_path(self, filepath):
return self._resolve_filepath(filepath)
+
+ def copy_local_to_storage(self, filename, filepath):
+ """
+ Copy this file from locally to the storage system.
+ """
+ # Make directories if necessary
+ if len(filepath) > 1:
+ directory = self._resolve_filepath(filepath[:-1])
+ if not os.path.exists(directory):
+ os.makedirs(directory)
+
+ shutil.copy(
+ filename, self.get_local_path(filepath))
diff --git a/mediagoblin/storage/mountstorage.py b/mediagoblin/storage/mountstorage.py
index 6adb7a0d..7239931f 100644
--- a/mediagoblin/storage/mountstorage.py
+++ b/mediagoblin/storage/mountstorage.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 medigoblin.storage import StorageInterface, clean_listy_filepath
+from mediagoblin.storage import StorageInterface, clean_listy_filepath
class MountStorage(StorageInterface):
diff --git a/mediagoblin/submit/__init__.py b/mediagoblin/submit/__init__.py
index 576bd0f5..ba347c69 100644
--- a/mediagoblin/submit/__init__.py
+++ b/mediagoblin/submit/__init__.py
@@ -13,5 +13,3 @@
#
# 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/>.
-
-
diff --git a/mediagoblin/submit/forms.py b/mediagoblin/submit/forms.py
index a999c714..48a21f02 100644
--- a/mediagoblin/submit/forms.py
+++ b/mediagoblin/submit/forms.py
@@ -17,8 +17,8 @@
import wtforms
-from mediagoblin.util import tag_length_validator
-from mediagoblin.util import fake_ugettext_passthrough as _
+from mediagoblin.tools.text import tag_length_validator
+from mediagoblin.tools.translate import fake_ugettext_passthrough as _
class SubmitStartForm(wtforms.Form):
@@ -30,4 +30,6 @@ class SubmitStartForm(wtforms.Form):
_('Description of this work'))
tags = wtforms.TextField(
_('Tags'),
- [tag_length_validator])
+ [tag_length_validator],
+ description=_(
+ "Seperate tags by commas or spaces."))
diff --git a/mediagoblin/submit/security.py b/mediagoblin/submit/security.py
index 9d62a36e..6708baf7 100644
--- a/mediagoblin/submit/security.py
+++ b/mediagoblin/submit/security.py
@@ -16,9 +16,9 @@
from mimetypes import guess_type
-
ALLOWED = ['image/jpeg', 'image/png', 'image/tiff', 'image/gif']
+
def check_filetype(posted_file):
if not guess_type(posted_file.filename)[0] in ALLOWED:
return False
diff --git a/mediagoblin/submit/views.py b/mediagoblin/submit/views.py
index 78f52160..dd1c3d1b 100644
--- a/mediagoblin/submit/views.py
+++ b/mediagoblin/submit/views.py
@@ -22,10 +22,9 @@ from cgi import FieldStorage
from werkzeug.utils import secure_filename
from mediagoblin.db.util import ObjectId
-from mediagoblin.util import (
- render_to_response, redirect, cleaned_markdown_conversion, \
- convert_to_tag_list_of_dicts)
-from mediagoblin.util import pass_to_ugettext as _
+from mediagoblin.tools.text import cleaned_markdown_conversion, 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, security
from mediagoblin.process_media import mark_entry_failed
@@ -41,7 +40,7 @@ def submit_start(request):
submit_form = submit_forms.SubmitStartForm(request.POST)
if request.method == 'POST' and submit_form.validate():
- if not (request.POST.has_key('file')
+ if not ('file' in request.POST
and isinstance(request.POST['file'], FieldStorage)
and request.POST['file'].file):
submit_form.file.errors.append(
@@ -76,7 +75,7 @@ def submit_start(request):
# Now store generate the queueing related filename
queue_filepath = request.app.queue_store.get_unique_filepath(
['media_entries',
- unicode(entry['_id']),
+ unicode(entry._id),
secure_filename(filename)])
# queue appropriately
@@ -91,8 +90,10 @@ def submit_start(request):
# 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)
+
+ # (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
@@ -105,7 +106,7 @@ def submit_start(request):
# conditions with changes to the document via processing code)
try:
media_manager['processor'].apply_async(
- [unicode(entry['_id'])], {},
+ [unicode(entry._id)], {},
task_id=task_id)
except BaseException as exc:
# The purpose of this section is because when running in "lazy"
@@ -114,16 +115,16 @@ def submit_start(request):
# 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[u'_id'], exc)
+ # ... not completely the diaper pattern because the
+ # exception is re-raised :)
+ mark_entry_failed(entry._id, exc)
# re-raise the exception
raise
add_message(request, SUCCESS, _('Woohoo! Submitted!'))
return redirect(request, "mediagoblin.user_pages.user_home",
- user = request.user['username'])
+ user=request.user['username'])
return render_to_response(
request,
diff --git a/mediagoblin/templates/mediagoblin/auth/change_fp.html b/mediagoblin/templates/mediagoblin/auth/change_fp.html
index 4be7e065..fa972085 100644
--- a/mediagoblin/templates/mediagoblin/auth/change_fp.html
+++ b/mediagoblin/templates/mediagoblin/auth/change_fp.html
@@ -23,12 +23,14 @@
<form action="{{ request.urlgen('mediagoblin.auth.verify_forgot_password') }}"
method="POST" enctype="multipart/form-data">
+ {{ csrf_token }}
+
<div class="grid_6 prefix_1 suffix_1 form_box">
<h1>{% trans %}Enter your new password{% endtrans %}</h1>
{{ wtforms_util.render_divs(cp_form) }}
<div class="form_submit_buttons">
- <input type="submit" value="submit" class="button"/>
+ <input type="submit" value="submit" class="button_form"/>
</div>
</div>
diff --git a/mediagoblin/templates/mediagoblin/auth/forgot_password.html b/mediagoblin/templates/mediagoblin/auth/forgot_password.html
index 23fa9eb5..41940742 100644
--- a/mediagoblin/templates/mediagoblin/auth/forgot_password.html
+++ b/mediagoblin/templates/mediagoblin/auth/forgot_password.html
@@ -20,18 +20,15 @@
{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
{% block mediagoblin_content %}
-
<form action="{{ request.urlgen('mediagoblin.auth.forgot_password') }}"
method="POST" enctype="multipart/form-data">
+ {{ csrf_token }}
<div class="grid_6 prefix_1 suffix_1 form_box">
- <h1>{% trans %}Enter your username or email{% endtrans %}</h1>
-
+ <h1>{% trans %}Recover password{% endtrans %}</h1>
{{ wtforms_util.render_divs(fp_form) }}
<div class="form_submit_buttons">
- <input type="submit" value="submit" class="button"/>
+ <input type="submit" value="{% trans %}Send instructions{% endtrans %}" class="button_form"/>
</div>
-
</div>
</form>
{% endblock %}
-
diff --git a/mediagoblin/templates/mediagoblin/auth/fp_changed_success.html b/mediagoblin/templates/mediagoblin/auth/fp_changed_success.html
index d6633ec6..7cea312d 100644
--- a/mediagoblin/templates/mediagoblin/auth/fp_changed_success.html
+++ b/mediagoblin/templates/mediagoblin/auth/fp_changed_success.html
@@ -19,9 +19,9 @@
{% block mediagoblin_content %}
<p>
- {% trans %}
+ {% trans -%}
Your password has been changed. Try to log in now.
- {% endtrans %}
+ {%- endtrans %}
</p>
{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/auth/fp_email_sent.html b/mediagoblin/templates/mediagoblin/auth/fp_email_sent.html
index bc79b970..69aac6b3 100644
--- a/mediagoblin/templates/mediagoblin/auth/fp_email_sent.html
+++ b/mediagoblin/templates/mediagoblin/auth/fp_email_sent.html
@@ -19,9 +19,9 @@
{% block mediagoblin_content %}
<p>
- {% trans %}
+ {% trans -%}
Check your inbox. We sent an email with a URL for changing your password.
- {% endtrans %}
+ {%- endtrans %}
</p>
{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/auth/login.html b/mediagoblin/templates/mediagoblin/auth/login.html
index 3926a1df..c3807e5f 100644
--- a/mediagoblin/templates/mediagoblin/auth/login.html
+++ b/mediagoblin/templates/mediagoblin/auth/login.html
@@ -22,6 +22,7 @@
{% block mediagoblin_content %}
<form action="{{ request.urlgen('mediagoblin.auth.login') }}"
method="POST" enctype="multipart/form-data">
+ {{ csrf_token }}
<div class="grid_6 prefix_1 suffix_1 form_box">
<h1>{% trans %}Log in{% endtrans %}</h1>
{% if login_failed %}
@@ -29,27 +30,23 @@
{% trans %}Logging in failed!{% endtrans %}
</div>
{% endif %}
- {{ wtforms_util.render_divs(login_form) }}
- <div class="form_submit_buttons">
- <input type="submit" value="{% trans %}Log in{% endtrans %}" class="button"/>
- </div>
- {% if next %}
- <input type="hidden" name="next" value="{{ next }}" class="button"
- style="display: none;"/>
- {% endif %}
{% if allow_registration %}
<p>
- {% trans %}Don't have an account yet?{% endtrans %}
- <br />
- <a href="{{ request.urlgen('mediagoblin.auth.register') }}">
+ {% trans %}Don't have an account yet?{% endtrans %} <a href="{{ request.urlgen('mediagoblin.auth.register') }}">
{%- trans %}Create one here!{% endtrans %}</a>
</p>
+ {% endif %}
+ {{ wtforms_util.render_divs(login_form) }}
<p>
- {% trans %}Forgot your password?{% endtrans %}
- <br />
<a href="{{ request.urlgen('mediagoblin.auth.forgot_password') }}">
- {%- trans %}Change it!{% endtrans %}</a>
+ {% trans %}Forgot your password?{% endtrans %}</a>
</p>
+ <div class="form_submit_buttons">
+ <input type="submit" value="{% trans %}Log in{% endtrans %}" class="button_form"/>
+ </div>
+ {% if next %}
+ <input type="hidden" name="next" value="{{ next }}" class="button_form"
+ style="display: none;"/>
{% endif %}
</div>
</form>
diff --git a/mediagoblin/templates/mediagoblin/auth/register.html b/mediagoblin/templates/mediagoblin/auth/register.html
index e72b3a52..a0d0a277 100644
--- a/mediagoblin/templates/mediagoblin/auth/register.html
+++ b/mediagoblin/templates/mediagoblin/auth/register.html
@@ -26,9 +26,10 @@
<div class="grid_6 prefix_1 suffix_1 form_box">
<h1>{% trans %}Create an account!{% endtrans %}</h1>
{{ wtforms_util.render_divs(register_form) }}
+ {{ csrf_token }}
<div class="form_submit_buttons">
<input type="submit" value="{% trans %}Create{% endtrans %}"
- class="button" />
+ class="button_form" />
</div>
</div>
</form>
diff --git a/mediagoblin/templates/mediagoblin/base.html b/mediagoblin/templates/mediagoblin/base.html
index bad22e7e..3dd9c8ff 100644
--- a/mediagoblin/templates/mediagoblin/base.html
+++ b/mediagoblin/templates/mediagoblin/base.html
@@ -19,7 +19,7 @@
<html>
<head>
<meta charset="utf-8">
- <title>{% block title %}{% trans %}GNU MediaGoblin{% endtrans %}{% endblock title %}</title>
+ <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"
@@ -54,7 +54,7 @@
alt="{% trans %}MediaGoblin logo{% endtrans %}" /></a>
{% endblock %}
{% if request.user and request.user['status'] == 'active' %}
- <a class="header_submit"
+ <a class="button_action"
href="{{ request.urlgen('mediagoblin.submit.start') }}">
{% trans %}Submit media{% endtrans %}
</a>
@@ -66,15 +66,15 @@
{% if request.user.status == "needs_email_verification" %}
<a href="{{ request.urlgen('mediagoblin.user_pages.user_home',
user=request.user['username']) }}"
- class="header_submit">
- {% trans %}verify your email!{% endtrans %}</a>
+ class="button_action_highlight">
+ {% trans %}Verify your email!{% endtrans %}</a>
{% endif %}
<a href="{{ request.urlgen('mediagoblin.user_pages.user_home',
user= request.user['username']) }}">
{{ request.user['username'] }}</a>
- (<a href="{{ request.urlgen('mediagoblin.auth.logout') }}">log out</a>)
+ (<a href="{{ request.urlgen('mediagoblin.auth.logout') }}">{% trans %}log out{% endtrans %}</a>)
{% else %}
<a href="{{ request.urlgen('mediagoblin.auth.login') }}">
{% trans %}Log in{% endtrans %}</a>
diff --git a/mediagoblin/templates/mediagoblin/edit/attachments.html b/mediagoblin/templates/mediagoblin/edit/attachments.html
index 63b06581..576642cf 100644
--- a/mediagoblin/templates/mediagoblin/edit/attachments.html
+++ b/mediagoblin/templates/mediagoblin/edit/attachments.html
@@ -48,7 +48,8 @@
{{ 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" />
+ <input type="submit" value="Save changes" class="button_form" />
+ {{ csrf_token }}
</div>
</div>
</form>
diff --git a/mediagoblin/templates/mediagoblin/edit/edit.html b/mediagoblin/templates/mediagoblin/edit/edit.html
index 8c4e2efb..73c2bada 100644
--- a/mediagoblin/templates/mediagoblin/edit/edit.html
+++ b/mediagoblin/templates/mediagoblin/edit/edit.html
@@ -34,7 +34,8 @@
{{ wtforms_util.render_divs(form) }}
<div class="form_submit_buttons">
<a href="{{ media.url_for_self(request.urlgen) }}">{% trans %}Cancel{% endtrans %}</a>
- <input type="submit" value="{% trans %}Save changes{% endtrans %}" class="button" />
+ <input type="submit" value="{% trans %}Save changes{% endtrans %}" class="button_form" />
+ {{ csrf_token }}
</div>
</div>
</form>
diff --git a/mediagoblin/templates/mediagoblin/edit/edit_profile.html b/mediagoblin/templates/mediagoblin/edit/edit_profile.html
index 464c663d..bf8fe5c1 100644
--- a/mediagoblin/templates/mediagoblin/edit/edit_profile.html
+++ b/mediagoblin/templates/mediagoblin/edit/edit_profile.html
@@ -32,7 +32,8 @@
</h1>
{{ wtforms_util.render_divs(form) }}
<div class="form_submit_buttons">
- <input type="submit" value="{% trans %}Save changes{% endtrans %}" class="button" />
+ <input type="submit" value="{% trans %}Save changes{% endtrans %}" class="button_form" />
+ {{ csrf_token }}
</div>
</div>
</form>
diff --git a/mediagoblin/templates/mediagoblin/listings/tag.html b/mediagoblin/templates/mediagoblin/listings/tag.html
index 58863015..f797f72f 100644
--- a/mediagoblin/templates/mediagoblin/listings/tag.html
+++ b/mediagoblin/templates/mediagoblin/listings/tag.html
@@ -26,9 +26,13 @@
tag=tag_slug) }}">
{% endblock mediagoblin_head %}
+{% block title %}
+ {% trans %}Media tagged with: {{ tag_name }}{% endtrans %} &mdash; {{ super() }}
+{% endblock %}
+
{% block mediagoblin_content -%}
<h1>
- {% trans %}Media tagged with:{% endtrans %} {{ tag_name }}
+ {% trans %}Media tagged with: {{ tag_name }}{% endtrans %}
</h1>
<div class="container_16 media_gallery">
diff --git a/mediagoblin/templates/mediagoblin/root.html b/mediagoblin/templates/mediagoblin/root.html
index 854fca51..25ce9e96 100644
--- a/mediagoblin/templates/mediagoblin/root.html
+++ b/mediagoblin/templates/mediagoblin/root.html
@@ -24,30 +24,21 @@
<h1>{% trans %}Explore{% endtrans %}</h1>
{% else %}
<div class="grid_11 alpha">
- <h1>{% trans %}Hi there, media lover! MediaGoblin is...{% endtrans %}</h1>
- <ul>
- <li>{% trans %}The perfect place for your media!{% endtrans %}</li>
- <li>{% trans %}A place for people to collaborate and show off original and derived creations!{% endtrans %}</li>
- <li>{% trans %}Free, as in freedom. (We’re a <a href="http://gnu.org">GNU</a> project, after all.){% endtrans %}</li>
- <li>{% trans %}Aiming to make the world a better place through decentralization and (eventually, coming soon!) federation!{% endtrans %}</li>
- <li>{% trans %}Built for extensibility. (Multiple media types coming soon to the software, including video support!){% endtrans %}</li>
- <li>{% trans %}Powered by people like you. (<a href="http://mediagoblin.org/pages/join.html">You can help us improve this software!</a>){% endtrans %}</li>
- </ul>
-
+ <h1>{% trans %}Hi there, welcome to this MediaGoblin site!{% endtrans %}</h1>
+ <p>{% trans %}Your finest source for all goblin-related media.{% endtrans %}</p>
+ <p>{% trans %}To add your own media, place comments, save your favourites and more, you can log in with your MediaGoblin account.{% endtrans %}</p>
{% if allow_registration %}
- <p>{% trans %}Excited to join us?{% endtrans %}<p>
- {% trans register_url=request.urlgen('mediagoblin.auth.register') %}
- <a class="header_submit_highlight" href="{{ register_url }}">Create a free account</a>
+ <p>{% trans %}Don't have one yet? It's easy!{% endtrans %}</p>
+ {% trans register_url=request.urlgen('mediagoblin.auth.register') -%}
+ <a class="button_action_highlight" href="{{ register_url }}">Create an account at this site</a>
or
- <a class="header_submit" href="http://wiki.mediagoblin.org/HackingHowto">Set up MediaGoblin on your own server</a>
- {% endtrans %}
+ <a class="button_action" href="http://wiki.mediagoblin.org/HackingHowto">Set up MediaGoblin on your own server</a>
+ {%- endtrans %}
{% endif %}
</div>
-
<div class="grid_5 omega">
<img src="{{ request.staticdirect('/images/frontpage_image.png') }}" />
</div>
-
<div class="clear"></div>
{% endif %}
<h2>{% trans %}Most recent media{% endtrans %}</h2>
diff --git a/mediagoblin/templates/mediagoblin/submit/start.html b/mediagoblin/templates/mediagoblin/submit/start.html
index f2e844df..1a0dd4b7 100644
--- a/mediagoblin/templates/mediagoblin/submit/start.html
+++ b/mediagoblin/templates/mediagoblin/submit/start.html
@@ -26,7 +26,8 @@
<h1>{% trans %}Submit yer media{% endtrans %}</h1>
{{ wtforms_util.render_divs(submit_form) }}
<div class="form_submit_buttons">
- <input type="submit" value="{% trans %}Submit{% endtrans %}" class="button" />
+ {{ csrf_token }}
+ <input type="submit" value="{% trans %}Submit{% endtrans %}" class="button_form" />
</div>
</div>
</form>
diff --git a/mediagoblin/templates/mediagoblin/test_submit.html b/mediagoblin/templates/mediagoblin/test_submit.html
index 78b88ae8..38be8efc 100644
--- a/mediagoblin/templates/mediagoblin/test_submit.html
+++ b/mediagoblin/templates/mediagoblin/test_submit.html
@@ -25,7 +25,8 @@
{{ wtforms_util.render_table(image_form) }}
<tr>
<td></td>
- <td><input type="submit" value="submit" class="button" /></td>
+ <td><input type="submit" value="submit" class="button_form" /></td>
+ {{ csrf_token }}
</tr>
</table>
</form>
diff --git a/mediagoblin/templates/mediagoblin/user_pages/gallery.html b/mediagoblin/templates/mediagoblin/user_pages/gallery.html
index df931d9c..b066dd71 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/gallery.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/gallery.html
@@ -26,29 +26,30 @@
user=user.username) }}">
{% endblock mediagoblin_head %}
+{% block title %}
+ {%- trans username=user.username -%}
+ {{ username }}'s media
+ {%- endtrans %} &mdash; {{ super() }}
+{% endblock %}
+
{% block mediagoblin_content -%}
- {% if user %}
- <h1>
- {%- trans username=user.username,
- user_url=request.urlgen(
- 'mediagoblin.user_pages.user_home',
- user=user.username) -%}
- <a href="{{ user_url }}">{{ username }}</a>'s media
- {%- endtrans %}
- </h1>
+ <h1>
+ {%- trans username=user.username,
+ user_url=request.urlgen(
+ 'mediagoblin.user_pages.user_home',
+ user=user.username) -%}
+ <a href="{{ user_url }}">{{ username }}</a>'s media
+ {%- endtrans %}
+ </h1>
- <div class="container_16 media_gallery">
- {{ object_gallery(request, media_entries, pagination) }}
- </div>
+ <div class="container_16 media_gallery">
+ {{ object_gallery(request, media_entries, pagination) }}
+ </div>
- <div class="grid_16">
- {% set feed_url = request.urlgen(
- 'mediagoblin.user_pages.atom_feed',
- user=user.username) %}
- {% include "mediagoblin/utils/feed_link.html" %}
- </div>
- {% else %}
- {# This *should* not occur as the view makes sure we pass in a user. #}
- <p>{% trans %}Sorry, no such user found.{% endtrans %}<p/>
- {% endif %}
+ <div class="grid_16">
+ {% set feed_url = request.urlgen(
+ 'mediagoblin.user_pages.atom_feed',
+ user=user.username) %}
+ {% include "mediagoblin/utils/feed_link.html" %}
+ </div>
{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html
index 82a48e7c..f5d715d6 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/media.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/media.html
@@ -20,6 +20,8 @@
{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
{% from "mediagoblin/utils/pagination.html" import render_pagination %}
+{% block title %}{{ media.title }} &mdash; {{ super() }}{% endblock %}
+
{% block mediagoblin_content %}
{% if media %}
<div class="grid_11 alpha">
@@ -49,66 +51,61 @@
<h2 class="media_title">
{{ media.title }}
</h2>
-
+ {% autoescape False %}
+ <p>{{ media.description_html }}</p>
+ {% endautoescape %}
<p class="media_uploader">
{% trans date=media.created.strftime("%Y-%m-%d"),
user_url=request.urlgen(
'mediagoblin.user_pages.user_home',
user=media.uploader().username),
username=media.uploader().username -%}
- Uploaded on {{ date }} by <a href="{{ user_url }}">{{ username }}</a>
+ By <a href="{{ user_url }}">{{ username }}</a> on {{ date }}
{%- endtrans %}
</p>
-
- {% autoescape False %}
- <p>{{ media.description_html }}</p>
- {% endautoescape %}
-
- <br />
- <h3>{% trans %}Comments{% endtrans %}</h3>
-
- {% if request.user %}
- <form action="{{ request.urlgen('mediagoblin.user_pages.media_post_comment',
- user= media.uploader().username,
- media=media._id) }}" method="POST">
- {{ wtforms_util.render_divs(comment_form) }}
- <div class="form_submit_buttons">
- <input type="submit" value="{% trans %}Post comment!{% endtrans %}" class="button" />
- </div>
- </form>
+ <h3></h3>
+ {% if request.user and comments.count() %}
+ <p><a href="#comment_form">{% trans %}Post a comment{% endtrans %}</a></p>
{% endif %}
-
{% if comments %}
{% for comment in comments %}
{% set comment_author = comment.author() %}
{% if pagination.active_id == comment._id %}
- <div class="comment_wrapper comment_active" id="comment-{{ 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_content">
- {% autoescape False %}
- {{ comment.content_html }}
+ <div class="comment_content">{% autoescape False %}{{ comment.content_html }}
{% endautoescape %}
- </div>
-
- <div class="comment_author">&mdash;
- <a href="{{ request.urlgen('mediagoblin.user_pages.user_home',
+ <img src="{{ request.staticdirect('/images/icon_comment.png') }}" />
+ <a href="{{ request.urlgen('mediagoblin.user_pages.user_home',
user = comment_author['username']) }}">
{{ comment_author['username'] }}</a>
{% trans %}at{% endtrans %}
<a href="{{ request.urlgen('mediagoblin.user_pages.media_home.view_comment',
- comment = comment['_id'],
+ comment = comment._id,
user = media.uploader().username,
media = media._id) }}#comment">
- {{ comment.created.strftime("%Y-%m-%d %I:%M%p") }}
+ {{ comment.created.strftime("%I:%M%p %Y-%m-%d") }}
</a>
</div>
</div>
{% endfor %}
+ {% if request.user %}
+ <form action="{{ request.urlgen('mediagoblin.user_pages.media_post_comment',
+ user= media.uploader().username,
+ media=media._id) }}" method="POST">
+ {{ wtforms_util.render_divs(comment_form) }}
+ <div class="form_submit_buttons">
+ <input type="submit" value="{% trans %}Post comment!{% endtrans %}" class="button_form" />
+ {{ csrf_token }}
+ </div>
+ </form>
+ {% endif %}
+
{{ render_pagination(request, pagination,
request.urlgen('mediagoblin.user_pages.media_home',
user = media.uploader().username,
@@ -119,26 +116,19 @@
<div class="grid_5 omega">
{% include "mediagoblin/utils/prev_next.html" %}
- {% if media['uploader'] == request.user['_id'] or
+ {% if media['uploader'] == request.user._id or
request.user['is_admin'] %}
- <h3>Temporary button holder</h3>
<p>
{% set edit_url = request.urlgen('mediagoblin.edit.edit_media',
user= media.uploader().username,
media= media._id) %}
- <a href="{{ edit_url }}"
- ><img src="{{ request.staticdirect('/images/icon_edit.png') }}"
- class="media_icon" /></a>
- <a href="{{ edit_url }}">{% trans %}edit{% endtrans %}</a>
+ <a href="{{ edit_url }}">{% trans %}Edit{% endtrans %}</a>
</p>
<p>
{% set delete_url = request.urlgen('mediagoblin.user_pages.media_confirm_delete',
user= media.uploader().username,
media= media._id) %}
- <a href="{{ delete_url }}"
- ><img src="{{ request.staticdirect('/images/icon_delete.png') }}"
- class="media_icon" /></a>
- <a href="{{ delete_url }}">{% trans %}delete{% endtrans %}</a>
+ <a href="{{ delete_url }}">{% trans %}Delete{% endtrans %}</a>
</p>
{% endif %}
@@ -156,7 +146,7 @@
{% endif %}
{% if app_config['allow_attachments']
- and (media['uploader'] == request.user['_id']
+ and (media['uploader'] == request.user._id
or request.user['is_admin']) %}
<p>
<a href="{{ request.urlgen('mediagoblin.edit.attachments',
diff --git a/mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html b/mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html
index 01323a6e..c3a9d622 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html
@@ -41,13 +41,14 @@
<p class="delete_checkbox_box">
{{ form.confirm }}
- {{ _(form.confirm.label.text) }}
+ <label for="{{ (form.confirm.name) }}">{{ _(form.confirm.label.text) }}</label>
</p>
<div class="form_submit_buttons">
{# TODO: This isn't a button really... might do unexpected things :) #}
<a class="cancel_link" href="{{ media.url_for_self(request.urlgen) }}">{% trans %}Cancel{% endtrans %}</a>
- <input type="submit" value="{% trans %}Delete Permanently{% endtrans %}" class="button" />
+ <input type="submit" value="{% trans %}Delete Permanently{% endtrans %}" class="button_form" />
+ {{ csrf_token }}
</div>
</div>
</form>
diff --git a/mediagoblin/templates/mediagoblin/user_pages/user.html b/mediagoblin/templates/mediagoblin/user_pages/user.html
index c5beeaaa..5a39aaa5 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/user.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/user.html
@@ -26,6 +26,17 @@
user=user.username) }}">
{% endblock mediagoblin_head %}
+{% block title %}
+ {%- if user -%}
+ {%- trans username=user.username -%}
+ {{ username }}'s profile
+ {%- endtrans %} &mdash; {{ super() }}
+ {%- else -%}
+ {{ super() }}
+ {%- endif -%}
+{% endblock %}
+
+
{% block mediagoblin_content -%}
{# If no user... #}
{% if not user %}
@@ -51,7 +62,7 @@
<p>{% trans %}In case it doesn't:{% endtrans %}</p>
<a href="{{ request.urlgen('mediagoblin.auth.resend_verification') }}"
- class="button">{% trans %}Resend verification email{% endtrans %}</a>
+ class="button_action_highlight">{% trans %}Resend verification email{% endtrans %}</a>
</div>
{% else %}
{# if the user is not you, but still needs to verify their email #}
@@ -78,15 +89,15 @@
{%- trans username=user.username %}{{ username }}'s profile{% endtrans -%}
</h1>
- {% if not user['url'] and not user['profile'] %}
- {% if request.user['_id'] == user['_id'] %}
+ {% if not user['url'] and not user['bio'] %}
+ {% if request.user._id == user._id %}
<div class="grid_6 alpha 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="header_submit">
+ class="button_action">
{%- trans %}Edit profile{% endtrans -%}
</a>
</div>
@@ -102,7 +113,7 @@
{% else %}
<div class="grid_6 alpha">
{% include "mediagoblin/utils/profile.html" %}
- {% if request.user['_id'] == user['_id'] or request.user['is_admin'] %}
+ {% if request.user._id == user._id or request.user['is_admin'] %}
<a href="{{ request.urlgen('mediagoblin.edit.profile') }}?username={{
user.username }}">
{%- trans %}Edit profile{% endtrans -%}
@@ -129,14 +140,14 @@
{% include "mediagoblin/utils/feed_link.html" %}
</div>
{% else %}
- {% if request.user['_id'] == user['_id'] %}
+ {% if request.user._id == user._id %}
<div class="grid_10 omega empty_space">
<p>
{% trans -%}
This is where your media will appear, but you don't seem to have added anything yet.
{%- endtrans %}
</p>
- <a class="header_submit"
+ <a class="button_action"
href="{{ request.urlgen('mediagoblin.submit.start') }}">
{%- trans %}Add media{% endtrans -%}
</a>
diff --git a/mediagoblin/templates/mediagoblin/utils/pagination.html b/mediagoblin/templates/mediagoblin/utils/pagination.html
index 87e15e0f..84336103 100644
--- a/mediagoblin/templates/mediagoblin/utils/pagination.html
+++ b/mediagoblin/templates/mediagoblin/utils/pagination.html
@@ -21,7 +21,7 @@
{# only display if {{pagination}} is defined #}
{% if pagination and pagination.pages > 1 %}
{% if not base_url %}
- {% set base_url = request.path_info %}
+ {% set base_url = request.full_path %}
{% endif %}
{% if preserve_get_params %}
@@ -36,7 +36,7 @@
{% set prev_url = pagination.get_page_url_explicit(
base_url, get_params,
pagination.page - 1) %}
- <a href="{{ prev_url }}"><img class="pagination_arrow" src="/mgoblin_static/images/pagination_left.png" alt="Previous page" /></a>
+ <a href="{{ prev_url }}"><img class="pagination_arrow" src="{{ request.staticdirect('/images/pagination_left.png') }}" alt="Previous page" /></a>
<a href="{{ prev_url }}">{% trans %}Newer{% endtrans %}</a>
{% endif %}
{% if pagination.has_next %}
@@ -44,7 +44,7 @@
base_url, get_params,
pagination.page + 1) %}
<a href="{{ next_url }}">{% trans %}Older{% endtrans %}</a>
- <a href="{{ next_url }}"><img class="pagination_arrow" src="/mgoblin_static/images/pagination_right.png" alt="Next page" /></a>
+ <a href="{{ next_url }}"><img class="pagination_arrow" src="{{ request.staticdirect('/images/pagination_right.png') }}" alt="Next page" /></a>
{% endif %}
<br />
Go to page:
diff --git a/mediagoblin/templates/mediagoblin/utils/prev_next.html b/mediagoblin/templates/mediagoblin/utils/prev_next.html
index 74f855ed..3363891b 100644
--- a/mediagoblin/templates/mediagoblin/utils/prev_next.html
+++ b/mediagoblin/templates/mediagoblin/utils/prev_next.html
@@ -25,23 +25,23 @@
{# There are no previous entries for the very first media entry #}
{% if prev_entry_url %}
<a class="navigation_button navigation_left" href="{{ prev_entry_url }}">
- <img src="/mgoblin_static/images/navigation_left.png" alt="Previous image" />
+ &larr; newer
</a>
{% else %}
{# This is the first entry. display greyed-out 'previous' image #}
<p class="navigation_button navigation_left">
- <img src="/mgoblin_static/images/navigation_end.png" alt="No previous images" />
+ &larr; newer
</p>
{% endif %}
{# Likewise, this could be the very last media entry #}
{% if next_entry_url %}
<a class="navigation_button" href="{{ next_entry_url }}">
- <img src="/mgoblin_static/images/navigation_right.png" alt="Next image" />
+ older &rarr;
</a>
{% else %}
{# This is the last entry. display greyed-out 'next' image #}
<p class="navigation_button">
- <img src="/mgoblin_static/images/navigation_end.png" alt="No following images" />
+ older &rarr;
</p>
{% endif %}
</div>
diff --git a/mediagoblin/templates/mediagoblin/utils/tags.html b/mediagoblin/templates/mediagoblin/utils/tags.html
index 87e6a85f..c7dfc8eb 100644
--- a/mediagoblin/templates/mediagoblin/utils/tags.html
+++ b/mediagoblin/templates/mediagoblin/utils/tags.html
@@ -17,13 +17,25 @@
#}
{% block tags_content -%}
- <h3>Tags</h3>
- <ul class="mediaentry_tags">
+ <p>{% trans %}Tagged with{% endtrans %}
{% for tag in media.tags %}
- <li class="tag">
+ {% if loop.last %}
+ {# the 'and' should only appear if there is more than one tag #}
+ {% if media.tags|length > 1 %}
+ {% trans %}and{% endtrans %}
+ {% endif %}
<a href="{{ request.urlgen(
- 'mediagoblin.listings.tags_listing',
- tag=tag['slug']) }}">{{ tag['name'] }}</li>
+ 'mediagoblin.listings.tags_listing',
+ tag=tag['slug']) }}">{{ tag['name'] }}</a>.
+ {% elif loop.revindex == 2 %}
+ <a href="{{ request.urlgen(
+ 'mediagoblin.listings.tags_listing',
+ tag=tag['slug']) }}">{{ tag['name'] }}</a>
+ {% else %}
+ <a href="{{ request.urlgen(
+ 'mediagoblin.listings.tags_listing',
+ tag=tag['slug']) }}">{{ tag['name'] }}</a>,
+ {% endif %}
{% endfor %}
- </ul>
+ </p>
{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/utils/wtforms.html b/mediagoblin/templates/mediagoblin/utils/wtforms.html
index 6a86fd24..39dca7cc 100644
--- a/mediagoblin/templates/mediagoblin/utils/wtforms.html
+++ b/mediagoblin/templates/mediagoblin/utils/wtforms.html
@@ -18,18 +18,16 @@
{# Generically render a field #}
{% macro render_field_div(field) %}
- <div class="form_field_box">
- <div class="form_field_label">{{ _(field.label.text) }}</div>
- <div class="form_field_input">{{ field }}</div>
+ <p class="form_field_label"><label for="{{ field.name }}">{{ _(field.label.text) }}</label></p>
+ <div class="form_field_input">
+ {{ field }}
{%- if field.errors -%}
{% for error in field.errors %}
- <div class="form_field_error">
- {{ error }}
- </div>
+ <p class="form_field_error">{{ error }}</p>
{% endfor %}
{%- endif %}
{% if field.description -%}
- <div class="form_field_description">{{ _(field.description) }}</div>
+ <p class="form_field_description">{{ _(field.description) }}</p>
{%- endif %}
</div>
{%- endmacro %}
diff --git a/mediagoblin/tests/test_auth.py b/mediagoblin/tests/test_auth.py
index fbbe1613..153c6e53 100644
--- a/mediagoblin/tests/test_auth.py
+++ b/mediagoblin/tests/test_auth.py
@@ -22,7 +22,7 @@ from nose.tools import assert_equal
from mediagoblin.auth import lib as auth_lib
from mediagoblin.tests.tools import setup_fresh_app
from mediagoblin import mg_globals
-from mediagoblin import util
+from mediagoblin.tools import template, mail
########################
@@ -76,16 +76,16 @@ def test_register_views(test_app):
test_app.get('/auth/register/')
# Make sure it rendered with the appropriate template
- assert util.TEMPLATE_TEST_CONTEXT.has_key(
+ assert template.TEMPLATE_TEST_CONTEXT.has_key(
'mediagoblin/auth/register.html')
# Try to register without providing anything, should error
# --------------------------------------------------------
- util.clear_test_template_context()
+ template.clear_test_template_context()
test_app.post(
'/auth/register/', {})
- context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
form = context['register_form']
assert form.username.errors == [u'This field is required.']
assert form.password.errors == [u'This field is required.']
@@ -96,14 +96,14 @@ def test_register_views(test_app):
# --------------------------------------------------------
## too short
- util.clear_test_template_context()
+ template.clear_test_template_context()
test_app.post(
'/auth/register/', {
'username': 'l',
'password': 'o',
'confirm_password': 'o',
'email': 'l'})
- context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
form = context['register_form']
assert form.username.errors == [
@@ -112,12 +112,12 @@ def test_register_views(test_app):
u'Field must be between 6 and 30 characters long.']
## bad form
- util.clear_test_template_context()
+ template.clear_test_template_context()
test_app.post(
'/auth/register/', {
'username': '@_@',
'email': 'lollerskates'})
- context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
form = context['register_form']
assert form.username.errors == [
@@ -126,12 +126,12 @@ def test_register_views(test_app):
u'Invalid email address.']
## mismatching passwords
- util.clear_test_template_context()
+ template.clear_test_template_context()
test_app.post(
'/auth/register/', {
'password': 'herpderp',
'confirm_password': 'derpherp'})
- context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
form = context['register_form']
assert form.password.errors == [
@@ -142,7 +142,7 @@ def test_register_views(test_app):
# Successful register
# -------------------
- util.clear_test_template_context()
+ template.clear_test_template_context()
response = test_app.post(
'/auth/register/', {
'username': 'happygirl',
@@ -155,7 +155,7 @@ def test_register_views(test_app):
assert_equal(
urlparse.urlsplit(response.location)[2],
'/u/happygirl/')
- assert util.TEMPLATE_TEST_CONTEXT.has_key(
+ assert template.TEMPLATE_TEST_CONTEXT.has_key(
'mediagoblin/user_pages/user.html')
## Make sure user is in place
@@ -166,15 +166,15 @@ def test_register_views(test_app):
assert new_user['email_verified'] == False
## Make sure user is logged in
- request = util.TEMPLATE_TEST_CONTEXT[
+ 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(util.EMAIL_TEST_INBOX) == 1
- message = util.EMAIL_TEST_INBOX.pop()
+ assert len(mail.EMAIL_TEST_INBOX) == 1
+ message = mail.EMAIL_TEST_INBOX.pop()
assert message['To'] == 'happygrrl@example.org'
- email_context = util.TEMPLATE_TEST_CONTEXT[
+ email_context = template.TEMPLATE_TEST_CONTEXT[
'mediagoblin/auth/verification_email.txt']
assert email_context['verification_url'] in message.get_payload(decode=True)
@@ -185,17 +185,17 @@ 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']]
## Try verifying with bs verification key, shouldn't work
- util.clear_test_template_context()
+ 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 = util.TEMPLATE_TEST_CONTEXT[
+ context = template.TEMPLATE_TEST_CONTEXT[
'mediagoblin/user_pages/user.html']
# assert context['verification_successful'] == True
# TODO: Would be good to test messages here when we can do so...
@@ -206,10 +206,10 @@ def test_register_views(test_app):
assert new_user['email_verified'] == False
## Verify the email activation works
- util.clear_test_template_context()
+ template.clear_test_template_context()
response = test_app.get("%s?%s" % (path, get_params))
response.follow()
- context = util.TEMPLATE_TEST_CONTEXT[
+ context = template.TEMPLATE_TEST_CONTEXT[
'mediagoblin/user_pages/user.html']
# assert context['verification_successful'] == True
# TODO: Would be good to test messages here when we can do so...
@@ -222,7 +222,7 @@ def test_register_views(test_app):
# Uniqueness checks
# -----------------
## We shouldn't be able to register with that user twice
- util.clear_test_template_context()
+ template.clear_test_template_context()
response = test_app.post(
'/auth/register/', {
'username': 'happygirl',
@@ -230,7 +230,7 @@ def test_register_views(test_app):
'confirm_password': 'iamsohappy2',
'email': 'happygrrl2@example.org'})
- context = util.TEMPLATE_TEST_CONTEXT[
+ context = template.TEMPLATE_TEST_CONTEXT[
'mediagoblin/auth/register.html']
form = context['register_form']
assert form.username.errors == [
@@ -240,7 +240,7 @@ def test_register_views(test_app):
### Oops, forgot the password
# -------------------
- util.clear_test_template_context()
+ template.clear_test_template_context()
response = test_app.post(
'/auth/forgot_password/',
{'username': 'happygirl'})
@@ -250,14 +250,14 @@ def test_register_views(test_app):
assert_equal(
urlparse.urlsplit(response.location)[2],
'/auth/forgot_password/email_sent/')
- assert util.TEMPLATE_TEST_CONTEXT.has_key(
+ assert template.TEMPLATE_TEST_CONTEXT.has_key(
'mediagoblin/auth/fp_email_sent.html')
## Make sure link to change password is sent by email
- assert len(util.EMAIL_TEST_INBOX) == 1
- message = util.EMAIL_TEST_INBOX.pop()
+ assert len(mail.EMAIL_TEST_INBOX) == 1
+ message = mail.EMAIL_TEST_INBOX.pop()
assert message['To'] == 'happygrrl@example.org'
- email_context = util.TEMPLATE_TEST_CONTEXT[
+ email_context = template.TEMPLATE_TEST_CONTEXT[
'mediagoblin/auth/fp_verification_email.txt']
#TODO - change the name of verification_url to something forgot-password-ish
assert email_context['verification_url'] in message.get_payload(decode=True)
@@ -269,7 +269,7 @@ def test_register_views(test_app):
# user should have matching parameters
new_user = mg_globals.database.User.find_one({'username': '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
@@ -277,14 +277,14 @@ def test_register_views(test_app):
assert (new_user['fp_token_expire'] - datetime.datetime.now()).days == 9
## Try using a bs password-changing verification key, shouldn't work
- util.clear_test_template_context()
+ template.clear_test_template_context()
response = test_app.get(
"/auth/forgot_password/verify/?userid=%s&token=total_bs" % unicode(
- new_user['_id']), status=400)
+ new_user._id), status=400)
assert response.status == '400 Bad Request'
## Try using an expired token to change password, shouldn't work
- util.clear_test_template_context()
+ template.clear_test_template_context()
real_token_expiration = new_user['fp_token_expire']
new_user['fp_token_expire'] = datetime.datetime.now()
new_user.save()
@@ -294,12 +294,12 @@ def test_register_views(test_app):
new_user.save()
## Verify step 1 of password-change works -- can see form to change password
- util.clear_test_template_context()
+ template.clear_test_template_context()
response = test_app.get("%s?%s" % (path, get_params))
- assert util.TEMPLATE_TEST_CONTEXT.has_key('mediagoblin/auth/change_fp.html')
+ assert template.TEMPLATE_TEST_CONTEXT.has_key('mediagoblin/auth/change_fp.html')
## Verify step 2.1 of password-change works -- report success to user
- util.clear_test_template_context()
+ template.clear_test_template_context()
response = test_app.post(
'/auth/forgot_password/verify/', {
'userid': parsed_get_params['userid'],
@@ -307,11 +307,11 @@ def test_register_views(test_app):
'confirm_password': 'iamveryveryhappy',
'token': parsed_get_params['token']})
response.follow()
- assert util.TEMPLATE_TEST_CONTEXT.has_key(
+ assert template.TEMPLATE_TEST_CONTEXT.has_key(
'mediagoblin/auth/fp_changed_success.html')
## Verify step 2.2 of password-change works -- login w/ new password success
- util.clear_test_template_context()
+ template.clear_test_template_context()
response = test_app.post(
'/auth/login/', {
'username': u'happygirl',
@@ -322,7 +322,7 @@ def test_register_views(test_app):
assert_equal(
urlparse.urlsplit(response.location)[2],
'/')
- assert util.TEMPLATE_TEST_CONTEXT.has_key(
+ assert template.TEMPLATE_TEST_CONTEXT.has_key(
'mediagoblin/root.html')
@@ -341,61 +341,61 @@ def test_authentication_views(test_app):
# Get login
# ---------
test_app.get('/auth/login/')
- assert util.TEMPLATE_TEST_CONTEXT.has_key(
+ assert template.TEMPLATE_TEST_CONTEXT.has_key(
'mediagoblin/auth/login.html')
# Failed login - blank form
# -------------------------
- util.clear_test_template_context()
+ template.clear_test_template_context()
response = test_app.post('/auth/login/')
- context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
form = context['login_form']
assert form.username.errors == [u'This field is required.']
assert form.password.errors == [u'This field is required.']
# Failed login - blank user
# -------------------------
- util.clear_test_template_context()
+ template.clear_test_template_context()
response = test_app.post(
'/auth/login/', {
'password': u'toast'})
- context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
form = context['login_form']
assert form.username.errors == [u'This field is required.']
# Failed login - blank password
# -----------------------------
- util.clear_test_template_context()
+ template.clear_test_template_context()
response = test_app.post(
'/auth/login/', {
'username': u'chris'})
- context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
form = context['login_form']
assert form.password.errors == [u'This field is required.']
# Failed login - bad user
# -----------------------
- util.clear_test_template_context()
+ template.clear_test_template_context()
response = test_app.post(
'/auth/login/', {
'username': u'steve',
'password': 'toast'})
- context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
assert context['login_failed']
# Failed login - bad password
# ---------------------------
- util.clear_test_template_context()
+ template.clear_test_template_context()
response = test_app.post(
'/auth/login/', {
'username': u'chris',
'password': 'jam'})
- context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
assert context['login_failed']
# Successful login
# ----------------
- util.clear_test_template_context()
+ template.clear_test_template_context()
response = test_app.post(
'/auth/login/', {
'username': u'chris',
@@ -406,17 +406,17 @@ def test_authentication_views(test_app):
assert_equal(
urlparse.urlsplit(response.location)[2],
'/')
- assert util.TEMPLATE_TEST_CONTEXT.has_key(
+ assert template.TEMPLATE_TEST_CONTEXT.has_key(
'mediagoblin/root.html')
# Make sure user is in the session
- context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html']
+ 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
# -----------------
- util.clear_test_template_context()
+ template.clear_test_template_context()
response = test_app.get('/auth/logout/')
# Should be redirected to index page
@@ -424,17 +424,17 @@ def test_authentication_views(test_app):
assert_equal(
urlparse.urlsplit(response.location)[2],
'/')
- assert util.TEMPLATE_TEST_CONTEXT.has_key(
+ assert template.TEMPLATE_TEST_CONTEXT.has_key(
'mediagoblin/root.html')
# Make sure the user is not in the session
- context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html']
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html']
session = context['request'].session
assert session.has_key('user_id') == False
# User is redirected to custom URL if POST['next'] is set
# -------------------------------------------------------
- util.clear_test_template_context()
+ template.clear_test_template_context()
response = test_app.post(
'/auth/login/', {
'username': u'chris',
diff --git a/mediagoblin/tests/test_csrf_middleware.py b/mediagoblin/tests/test_csrf_middleware.py
new file mode 100644
index 00000000..691f10b9
--- /dev/null
+++ b/mediagoblin/tests/test_csrf_middleware.py
@@ -0,0 +1,71 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import urlparse
+import datetime
+
+from nose.tools import assert_equal
+
+from mediagoblin.tests.tools import setup_fresh_app
+from mediagoblin import mg_globals
+
+
+@setup_fresh_app
+def test_csrf_cookie_set(test_app):
+
+ cookie_name = mg_globals.app_config['csrf_cookie_name']
+
+ # get login page
+ response = test_app.get('/auth/login/')
+
+ # assert that the mediagoblin nonce cookie has been set
+ assert 'Set-Cookie' in response.headers
+ assert cookie_name in response.cookies_set
+
+ # assert that we're also sending a vary header
+ assert response.headers.get('Vary', False) == 'Cookie'
+
+
+@setup_fresh_app
+def test_csrf_token_must_match(test_app):
+
+ # construct a request with no cookie or form token
+ assert test_app.post('/auth/login/',
+ extra_environ={'gmg.verify_csrf': True},
+ expect_errors=True).status_int == 403
+
+ # construct a request with a cookie, but no form token
+ assert test_app.post('/auth/login/',
+ headers={'Cookie': str('%s=foo; ' %
+ mg_globals.app_config['csrf_cookie_name'])},
+ extra_environ={'gmg.verify_csrf': True},
+ expect_errors=True).status_int == 403
+
+ # 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; ' %
+ mg_globals.app_config['csrf_cookie_name'])},
+ extra_environ={'gmg.verify_csrf': True},
+ expect_errors=True).\
+ status_int == 403
+
+ assert test_app.post('/auth/login/',
+ {'csrf_token': 'foo'},
+ headers={'Cookie': str('%s=foo; ' %
+ mg_globals.app_config['csrf_cookie_name'])},
+ extra_environ={'gmg.verify_csrf': True}).\
+ status_int == 200
diff --git a/mediagoblin/tests/test_edit.py b/mediagoblin/tests/test_edit.py
new file mode 100644
index 00000000..3637b046
--- /dev/null
+++ b/mediagoblin/tests/test_edit.py
@@ -0,0 +1,112 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 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 import mg_globals
+from mediagoblin.tests.tools import setup_fresh_app
+from mediagoblin.tools import template
+from mediagoblin.auth.lib import bcrypt_check_password, \
+ bcrypt_gen_password_hash
+
+
+@setup_fresh_app
+def test_change_password(test_app):
+ """Test changing password correctly and incorrectly"""
+ # set up new user
+ test_user = mg_globals.database.User()
+ test_user['username'] = u'chris'
+ test_user['email'] = u'chris@example.com'
+ test_user['email_verified'] = True
+ test_user['status'] = u'active'
+ test_user['pw_hash'] = bcrypt_gen_password_hash('toast')
+ test_user.save()
+
+ 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/profile/', {
+ 'bio': u'',
+ 'url': u'',
+ 'old_password': 'toast',
+ 'new_password': '123456',
+ 'confirm_password': '123456'})
+
+ # test_user has to be fetched again in order to have the current values
+ test_user = mg_globals.database.User.one({'username': '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/profile/', {
+ 'bio': u'',
+ 'url': u'',
+ 'old_password': 'toast',
+ 'new_password': '098765',
+ 'confirm_password': '098765'})
+
+ test_user = mg_globals.database.User.one({'username': '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 = mg_globals.database.User()
+ test_user['username'] = u'chris'
+ test_user['email'] = u'chris@example.com'
+ test_user['email_verified'] = True
+ test_user['status'] = u'active'
+ test_user['pw_hash'] = bcrypt_gen_password_hash('toast')
+ test_user.save()
+
+ # 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': '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': '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
diff --git a/mediagoblin/tests/test_messages.py b/mediagoblin/tests/test_messages.py
index 9c57a151..2635f4d7 100644
--- a/mediagoblin/tests/test_messages.py
+++ b/mediagoblin/tests/test_messages.py
@@ -16,7 +16,7 @@
from mediagoblin.messages import fetch_messages, add_message
from mediagoblin.tests.tools import setup_fresh_app
-from mediagoblin import util
+from mediagoblin.tools import template
@setup_fresh_app
@@ -28,7 +28,7 @@ def test_messages(test_app):
"""
# Aquire a request object
test_app.get('/')
- context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html']
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html']
request = context['request']
# The message queue should be empty
diff --git a/mediagoblin/tests/test_mgoblin_app.ini b/mediagoblin/tests/test_mgoblin_app.ini
index ab32cccc..f979e810 100644
--- a/mediagoblin/tests/test_mgoblin_app.ini
+++ b/mediagoblin/tests/test_mgoblin_app.ini
@@ -1,5 +1,5 @@
[mediagoblin]
-direct_remote_path = /mgoblin_static/
+direct_remote_path = /test_static/
email_sender_address = "notice@mediagoblin.example.org"
email_debug_mode = true
db_name = __mediagoblin_tests__
diff --git a/mediagoblin/tests/test_migrations.py b/mediagoblin/tests/test_migrations.py
index fc2449f7..e7cef0a1 100644
--- a/mediagoblin/tests/test_migrations.py
+++ b/mediagoblin/tests/test_migrations.py
@@ -23,6 +23,7 @@ from mediagoblin.tests.tools import (
from mediagoblin.db.util import (
RegisterMigration, MigrationManager, ObjectId,
MissingCurrentMigration)
+from mediagoblin.db.migrations import add_table_field
# This one will get filled with local migrations
TEST_MIGRATION_REGISTRY = {}
@@ -45,10 +46,7 @@ def creature_add_magical_powers(database):
magical powers, all existing monsters, setting to an empty list is
fine.
"""
- database['creatures'].update(
- {'magical_powers': {'$exists': False}},
- {'$set': {'magical_powers': []}},
- multi=True)
+ add_table_field(database, 'creatures', 'magical_powers', [])
@RegisterMigration(2, TEST_MIGRATION_REGISTRY)
diff --git a/mediagoblin/tests/test_paste.ini b/mediagoblin/tests/test_paste.ini
index e7574b7a..bd57994b 100644
--- a/mediagoblin/tests/test_paste.ini
+++ b/mediagoblin/tests/test_paste.ini
@@ -5,7 +5,7 @@ debug = true
use = egg:Paste#urlmap
/ = mediagoblin
/mgoblin_media/ = publicstore_serve
-/mgoblin_static/ = mediagoblin_static
+/test_static/ = mediagoblin_static
[app:mediagoblin]
use = egg:mediagoblin#app
diff --git a/mediagoblin/tests/test_storage.py b/mediagoblin/tests/test_storage.py
index 46ecb2ec..eab4d032 100644
--- a/mediagoblin/tests/test_storage.py
+++ b/mediagoblin/tests/test_storage.py
@@ -57,6 +57,10 @@ class FakeRemoteStorage(storage.filestorage.BasicFileStorage):
# should force copying to the workbench
local_storage = False
+ def copy_local_to_storage(self, *args, **kwargs):
+ return storage.StorageInterface.copy_local_to_storage(
+ self, *args, **kwargs)
+
def test_storage_system_from_config():
this_storage = storage.storage_system_from_config(
@@ -252,3 +256,26 @@ def test_basic_storage_copy_locally():
this_storage.copy_locally(filepath, new_file_dest)
assert file(new_file_dest).read() == 'Testing this file'
+
+
+def _test_copy_local_to_storage_works(tmpdir, this_storage):
+ local_filename = tempfile.mktemp()
+ with file(local_filename, 'w') as tmpfile:
+ tmpfile.write('haha')
+
+ this_storage.copy_local_to_storage(
+ local_filename, ['dir1', 'dir2', 'copiedto.txt'])
+
+ assert file(
+ os.path.join(tmpdir, 'dir1/dir2/copiedto.txt'),
+ 'r').read() == 'haha'
+
+
+def test_basic_storage_copy_local_to_storage():
+ tmpdir, this_storage = get_tmp_filestorage()
+ _test_copy_local_to_storage_works(tmpdir, this_storage)
+
+
+def test_general_storage_copy_local_to_storage():
+ tmpdir, this_storage = get_tmp_filestorage(fake_remote=True)
+ _test_copy_local_to_storage_works(tmpdir, this_storage)
diff --git a/mediagoblin/tests/test_submission.py b/mediagoblin/tests/test_submission.py
index 007c0348..dec7118b 100644
--- a/mediagoblin/tests/test_submission.py
+++ b/mediagoblin/tests/test_submission.py
@@ -22,7 +22,7 @@ from nose.tools import assert_equal, assert_true, assert_false
from mediagoblin.auth import lib as auth_lib
from mediagoblin.tests.tools import setup_fresh_app, get_test_app
from mediagoblin import mg_globals
-from mediagoblin import util
+from mediagoblin.tools import template, common
GOOD_JPG = pkg_resources.resource_filename(
'mediagoblin.tests', 'test_submission/good.jpg')
@@ -63,20 +63,20 @@ class TestSubmission:
def test_missing_fields(self):
# Test blank form
# ---------------
- util.clear_test_template_context()
+ template.clear_test_template_context()
response = self.test_app.post(
'/submit/', {})
- context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html']
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html']
form = context['submit_form']
assert form.file.errors == [u'You must provide a file.']
# Test blank file
# ---------------
- util.clear_test_template_context()
+ template.clear_test_template_context()
response = self.test_app.post(
'/submit/', {
'title': 'test title'})
- context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html']
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html']
form = context['submit_form']
assert form.file.errors == [u'You must provide a file.']
@@ -84,7 +84,7 @@ class TestSubmission:
def test_normal_uploads(self):
# Test JPG
# --------
- util.clear_test_template_context()
+ template.clear_test_template_context()
response = self.test_app.post(
'/submit/', {
'title': 'Normal upload 1'
@@ -96,12 +96,12 @@ class TestSubmission:
assert_equal(
urlparse.urlsplit(response.location)[2],
'/u/chris/')
- assert util.TEMPLATE_TEST_CONTEXT.has_key(
+ assert template.TEMPLATE_TEST_CONTEXT.has_key(
'mediagoblin/user_pages/user.html')
# Test PNG
# --------
- util.clear_test_template_context()
+ template.clear_test_template_context()
response = self.test_app.post(
'/submit/', {
'title': 'Normal upload 2'
@@ -112,13 +112,13 @@ class TestSubmission:
assert_equal(
urlparse.urlsplit(response.location)[2],
'/u/chris/')
- assert util.TEMPLATE_TEST_CONTEXT.has_key(
+ assert template.TEMPLATE_TEST_CONTEXT.has_key(
'mediagoblin/user_pages/user.html')
def test_tags(self):
# Good tag string
# --------
- util.clear_test_template_context()
+ template.clear_test_template_context()
response = self.test_app.post(
'/submit/', {
'title': 'Balanced Goblin',
@@ -128,7 +128,7 @@ class TestSubmission:
# New media entry with correct tags should be created
response.follow()
- context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/user_pages/user.html']
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/user_pages/user.html']
request = context['request']
media = request.db.MediaEntry.find({'title': 'Balanced Goblin'})[0]
assert_equal(media['tags'],
@@ -137,7 +137,7 @@ class TestSubmission:
# Test tags that are too long
# ---------------
- util.clear_test_template_context()
+ template.clear_test_template_context()
response = self.test_app.post(
'/submit/', {
'title': 'Balanced Goblin',
@@ -146,14 +146,14 @@ class TestSubmission:
'file', GOOD_JPG)])
# Too long error should be raised
- context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html']
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html']
form = context['submit_form']
assert form.tags.errors == [
u'Tags must be shorter than 50 characters. Tags that are too long'\
': ffffffffffffffffffffffffffuuuuuuuuuuuuuuuuuuuuuuuuuu']
def test_delete(self):
- util.clear_test_template_context()
+ template.clear_test_template_context()
response = self.test_app.post(
'/submit/', {
'title': 'Balanced Goblin',
@@ -163,7 +163,7 @@ class TestSubmission:
# Post image
response.follow()
- request = util.TEMPLATE_TEST_CONTEXT[
+ request = template.TEMPLATE_TEST_CONTEXT[
'mediagoblin/user_pages/user.html']['request']
media = request.db.MediaEntry.find({'title': 'Balanced Goblin'})[0]
@@ -177,13 +177,13 @@ class TestSubmission:
request.urlgen('mediagoblin.user_pages.media_confirm_delete',
# No work: user=media.uploader().username,
user=self.test_user['username'],
- media=media['_id']),
+ media=media._id),
# no value means no confirm
{})
response.follow()
- request = util.TEMPLATE_TEST_CONTEXT[
+ request = template.TEMPLATE_TEST_CONTEXT[
'mediagoblin/user_pages/user.html']['request']
media = request.db.MediaEntry.find({'title': 'Balanced Goblin'})[0]
@@ -197,30 +197,30 @@ class TestSubmission:
request.urlgen('mediagoblin.user_pages.media_confirm_delete',
# No work: user=media.uploader().username,
user=self.test_user['username'],
- media=media['_id']),
+ media=media._id),
{'confirm': 'y'})
response.follow()
- request = util.TEMPLATE_TEST_CONTEXT[
+ request = template.TEMPLATE_TEST_CONTEXT[
'mediagoblin/user_pages/user.html']['request']
# Does media entry still exist?
assert_false(
request.db.MediaEntry.find(
- {'_id': media['_id']}).count())
+ {'_id': media._id}).count())
def test_malicious_uploads(self):
# Test non-suppoerted file with non-supported extension
# -----------------------------------------------------
- util.clear_test_template_context()
+ template.clear_test_template_context()
response = self.test_app.post(
'/submit/', {
'title': 'Malicious Upload 1'
}, upload_files=[(
'file', EVIL_FILE)])
- context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html']
+ context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html']
form = context['submit_form']
assert form.file.errors == ['The file doesn\'t seem to be an image!']
@@ -230,7 +230,7 @@ class TestSubmission:
# Test non-supported file with .jpg extension
# -------------------------------------------
- util.clear_test_template_context()
+ template.clear_test_template_context()
response = self.test_app.post(
'/submit/', {
'title': 'Malicious Upload 2'
@@ -250,7 +250,7 @@ class TestSubmission:
# Test non-supported file with .png extension
# -------------------------------------------
- util.clear_test_template_context()
+ template.clear_test_template_context()
response = self.test_app.post(
'/submit/', {
'title': 'Malicious Upload 3'
diff --git a/mediagoblin/tests/test_tags.py b/mediagoblin/tests/test_tags.py
index d4628795..a05831c9 100644
--- a/mediagoblin/tests/test_tags.py
+++ b/mediagoblin/tests/test_tags.py
@@ -15,9 +15,8 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from mediagoblin.tests.tools import setup_fresh_app
-from mediagoblin import util
from mediagoblin import mg_globals
-
+from mediagoblin.tools import text
@setup_fresh_app
def test_list_of_dicts_conversion(test_app):
@@ -28,23 +27,23 @@ def test_list_of_dicts_conversion(test_app):
function performs the reverse operation when populating a form to edit tags.
"""
# Leading, trailing, and internal whitespace should be removed and slugified
- assert util.convert_to_tag_list_of_dicts('sleep , 6 AM, chainsaw! ') == [
+ assert text.convert_to_tag_list_of_dicts('sleep , 6 AM, chainsaw! ') == [
{'name': u'sleep', 'slug': u'sleep'},
{'name': u'6 AM', 'slug': u'6-am'},
{'name': u'chainsaw!', 'slug': u'chainsaw'}]
# If the user enters two identical tags, record only one of them
- assert util.convert_to_tag_list_of_dicts('echo,echo') == [{'name': u'echo',
+ assert text.convert_to_tag_list_of_dicts('echo,echo') == [{'name': u'echo',
'slug': u'echo'}]
# Make sure converting the list of dicts to a string works
- assert util.media_tags_as_string([{'name': u'yin', 'slug': u'yin'},
+ assert text.media_tags_as_string([{'name': u'yin', 'slug': u'yin'},
{'name': u'yang', 'slug': u'yang'}]) == \
u'yin,yang'
# If the tag delimiter is a space then we expect different results
mg_globals.app_config['tags_delimiter'] = u' '
- assert util.convert_to_tag_list_of_dicts('unicorn ceramic nazi') == [
+ assert text.convert_to_tag_list_of_dicts('unicorn ceramic nazi') == [
{'name': u'unicorn', 'slug': u'unicorn'},
{'name': u'ceramic', 'slug': u'ceramic'},
{'name': u'nazi', 'slug': u'nazi'}]
diff --git a/mediagoblin/tests/test_util.py b/mediagoblin/tests/test_util.py
index c2a3a67f..48fa8669 100644
--- a/mediagoblin/tests/test_util.py
+++ b/mediagoblin/tests/test_util.py
@@ -16,10 +16,9 @@
import email
-from mediagoblin import util
+from mediagoblin.tools import common, url, translate, mail, text, testing
-
-util._activate_testing()
+testing._activate_testing()
def _import_component_testing_method(silly_string):
@@ -28,7 +27,7 @@ def _import_component_testing_method(silly_string):
def test_import_component():
- imported_func = util.import_component(
+ imported_func = common.import_component(
'mediagoblin.tests.test_util:_import_component_testing_method')
result = imported_func('hooobaladoobala')
expected = u"'hooobaladoobala' is the silliest string I've ever seen"
@@ -36,10 +35,10 @@ def test_import_component():
def test_send_email():
- util._clear_test_inboxes()
+ mail._clear_test_inboxes()
# send the email
- util.send_email(
+ mail.send_email(
"sender@mediagoblin.example.org",
["amanda@example.org", "akila@example.org"],
"Testing is so much fun!",
@@ -48,8 +47,8 @@ def test_send_email():
I hope you like unit tests JUST AS MUCH AS I DO!""")
# check the main inbox
- assert len(util.EMAIL_TEST_INBOX) == 1
- message = util.EMAIL_TEST_INBOX.pop()
+ assert len(mail.EMAIL_TEST_INBOX) == 1
+ message = mail.EMAIL_TEST_INBOX.pop()
assert message['From'] == "sender@mediagoblin.example.org"
assert message['To'] == "amanda@example.org, akila@example.org"
assert message['Subject'] == "Testing is so much fun!"
@@ -58,8 +57,8 @@ I hope you like unit tests JUST AS MUCH AS I DO!""")
I hope you like unit tests JUST AS MUCH AS I DO!"""
# Check everything that the FakeMhost.sendmail() method got is correct
- assert len(util.EMAIL_TEST_MBOX_INBOX) == 1
- mbox_dict = util.EMAIL_TEST_MBOX_INBOX.pop()
+ assert len(mail.EMAIL_TEST_MBOX_INBOX) == 1
+ mbox_dict = mail.EMAIL_TEST_MBOX_INBOX.pop()
assert mbox_dict['from'] == "sender@mediagoblin.example.org"
assert mbox_dict['to'] == ["amanda@example.org", "akila@example.org"]
mbox_message = email.message_from_string(mbox_dict['message'])
@@ -71,43 +70,43 @@ 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 util.slugify('a walk in the park') == 'a-walk-in-the-park'
- assert util.slugify('A Walk in the Park') == 'a-walk-in-the-park'
- assert util.slugify('a walk in the park') == 'a-walk-in-the-park'
- assert util.slugify('a walk in-the-park') == 'a-walk-in-the-park'
- assert util.slugify('a w@lk in the park?') == 'a-w-lk-in-the-park'
- assert util.slugify(u'a walk in the par\u0107') == 'a-walk-in-the-parc'
- assert util.slugify(u'\u00E0\u0042\u00E7\u010F\u00EB\u0066') == 'abcdef'
+ 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'
def test_locale_to_lower_upper():
"""
Test cc.i18n.util.locale_to_lower_upper()
"""
- assert util.locale_to_lower_upper('en') == 'en'
- assert util.locale_to_lower_upper('en_US') == 'en_US'
- assert util.locale_to_lower_upper('en-us') == 'en_US'
+ assert translate.locale_to_lower_upper('en') == 'en'
+ assert translate.locale_to_lower_upper('en_US') == 'en_US'
+ assert translate.locale_to_lower_upper('en-us') == 'en_US'
# crazy renditions. Useful?
- assert util.locale_to_lower_upper('en-US') == 'en_US'
- assert util.locale_to_lower_upper('en_us') == 'en_US'
+ assert translate.locale_to_lower_upper('en-US') == 'en_US'
+ assert translate.locale_to_lower_upper('en_us') == 'en_US'
def test_locale_to_lower_lower():
"""
Test cc.i18n.util.locale_to_lower_lower()
"""
- assert util.locale_to_lower_lower('en') == 'en'
- assert util.locale_to_lower_lower('en_US') == 'en-us'
- assert util.locale_to_lower_lower('en-us') == 'en-us'
+ assert translate.locale_to_lower_lower('en') == 'en'
+ assert translate.locale_to_lower_lower('en_US') == 'en-us'
+ assert translate.locale_to_lower_lower('en-us') == 'en-us'
# crazy renditions. Useful?
- assert util.locale_to_lower_lower('en-US') == 'en-us'
- assert util.locale_to_lower_lower('en_us') == 'en-us'
+ assert translate.locale_to_lower_lower('en-US') == 'en-us'
+ assert translate.locale_to_lower_lower('en_us') == 'en-us'
def test_html_cleaner():
# Remove images
- result = util.clean_html(
+ result = text.clean_html(
'<p>Hi everybody! '
'<img src="http://example.org/huge-purple-barney.png" /></p>\n'
'<p>:)</p>')
@@ -118,7 +117,7 @@ def test_html_cleaner():
'</div>')
# Remove evil javascript
- result = util.clean_html(
+ result = text.clean_html(
'<p><a href="javascript:nasty_surprise">innocent link!</a></p>')
assert result == (
'<p><a href="">innocent link!</a></p>')
diff --git a/mediagoblin/tests/tools.py b/mediagoblin/tests/tools.py
index 308e83ee..420d9ba8 100644
--- a/mediagoblin/tests/tools.py
+++ b/mediagoblin/tests/tools.py
@@ -21,7 +21,8 @@ import os, shutil
from paste.deploy import loadapp
from webtest import TestApp
-from mediagoblin import util
+from mediagoblin import mg_globals
+from mediagoblin.tools import testing
from mediagoblin.init.config import read_mediagoblin_config
from mediagoblin.decorators import _make_safe
from mediagoblin.db.open import setup_connection_and_db_from_config
@@ -49,6 +50,51 @@ $ CELERY_CONFIG_MODULE=mediagoblin.init.celery.from_tests ./bin/nosetests"""
class BadCeleryEnviron(Exception): pass
+class TestingMiddleware(object):
+ """
+ Middleware for the Unit tests
+
+ It might make sense to perform some tests on all
+ requests/responses. Or prepare them in a special
+ manner. For example all html responses could be tested
+ for being valid html *after* being rendered.
+
+ This module is getting inserted at the front of the
+ middleware list, which means: requests are handed here
+ first, responses last. So this wraps up the "normal"
+ app.
+
+ If you need to add a test, either add it directly to
+ the appropiate process_request or process_response, or
+ create a new method and call it from process_*.
+ """
+
+ def __init__(self, mg_app):
+ self.app = mg_app
+
+ def process_request(self, request):
+ pass
+
+ def process_response(self, request, response):
+ # All following tests should be for html only!
+ if response.content_type != "text/html":
+ # Get out early
+ return
+
+ # If the template contains a reference to
+ # /mgoblin_static/ instead of using
+ # /request.staticdirect(), error out here.
+ # This could probably be implemented as a grep on
+ # the shipped templates easier...
+ if response.text.find("/mgoblin_static/") >= 0:
+ raise AssertionError(
+ "Response HTML contains reference to /mgoblin_static/ "
+ "instead of staticdirect. Request was for: "
+ + request.full_path)
+
+ return
+
+
def suicide_if_bad_celery_environ():
if not os.environ.get('CELERY_CONFIG_MODULE') == \
'mediagoblin.init.celery.from_tests':
@@ -59,7 +105,7 @@ def get_test_app(dump_old_app=True):
suicide_if_bad_celery_environ()
# Make sure we've turned on testing
- util._activate_testing()
+ testing._activate_testing()
# Leave this imported as it sets up celery.
from mediagoblin.init.celery import from_tests
@@ -103,6 +149,12 @@ def get_test_app(dump_old_app=True):
test_app = loadapp(
'config:' + TEST_SERVER_CONFIG)
+ # Insert the TestingMiddleware, which can do some
+ # sanity checks on every request/response.
+ # Doing it this way is probably not the cleanest way.
+ # We'll fix it, when we have plugins!
+ mg_globals.app.middleware.insert(0, TestingMiddleware(mg_globals.app))
+
app = TestApp(test_app)
MGOBLIN_APP = app
@@ -117,7 +169,7 @@ def setup_fresh_app(func):
"""
def wrapper(*args, **kwargs):
test_app = get_test_app()
- util.clear_test_buckets()
+ testing.clear_test_buckets()
return func(test_app, *args, **kwargs)
return _make_safe(wrapper, func)
diff --git a/mediagoblin/tools/__init__.py b/mediagoblin/tools/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/mediagoblin/tools/__init__.py
diff --git a/mediagoblin/tools/common.py b/mediagoblin/tools/common.py
new file mode 100644
index 00000000..12d8309e
--- /dev/null
+++ b/mediagoblin/tools/common.py
@@ -0,0 +1,38 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# 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
+
+DISPLAY_IMAGE_FETCHING_ORDER = [u'medium', u'original', u'thumb']
+
+global TESTS_ENABLED
+TESTS_ENABLED = False
+
+
+def import_component(import_string):
+ """
+ Import a module component defined by STRING. Probably a method,
+ class, or global variable.
+
+ Args:
+ - import_string: a string that defines what to import. Written
+ in the format of "module1.module2:component"
+ """
+ module_name, func_name = import_string.split(':', 1)
+ __import__(module_name)
+ module = sys.modules[module_name]
+ func = getattr(module, func_name)
+ return func
diff --git a/mediagoblin/tools/files.py b/mediagoblin/tools/files.py
new file mode 100644
index 00000000..e0bf0569
--- /dev/null
+++ b/mediagoblin/tools/files.py
@@ -0,0 +1,32 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 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 import mg_globals
+
+def delete_media_files(media):
+ """
+ Delete all files associated with a MediaEntry
+
+ Arguments:
+ - media: A MediaEntry document
+ """
+ for listpath in media['media_files'].itervalues():
+ mg_globals.public_store.delete_file(
+ listpath)
+
+ for attachment in media['attachment_files']:
+ mg_globals.public_store.delete_file(
+ attachment['filepath'])
diff --git a/mediagoblin/tools/mail.py b/mediagoblin/tools/mail.py
new file mode 100644
index 00000000..9e00be7d
--- /dev/null
+++ b/mediagoblin/tools/mail.py
@@ -0,0 +1,123 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 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 smtplib
+from email.MIMEText import MIMEText
+from mediagoblin import mg_globals
+from mediagoblin.tools import common
+
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+### Special email test stuff begins HERE
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+# We have two "test inboxes" here:
+#
+# EMAIL_TEST_INBOX:
+# ----------------
+# If you're writing test views, you'll probably want to check this.
+# It contains a list of MIMEText messages.
+#
+# EMAIL_TEST_MBOX_INBOX:
+# ----------------------
+# This collects the messages from the FakeMhost inbox. It's reslly
+# just here for testing the send_email method itself.
+#
+# Anyway this contains:
+# - from
+# - to: a list of email recipient addresses
+# - message: not just the body, but the whole message, including
+# headers, etc.
+#
+# ***IMPORTANT!***
+# ----------------
+# Before running tests that call functions which send email, you should
+# always call _clear_test_inboxes() to "wipe" the inboxes clean.
+
+EMAIL_TEST_INBOX = []
+EMAIL_TEST_MBOX_INBOX = []
+
+
+class FakeMhost(object):
+ """
+ Just a fake mail host so we can capture and test messages
+ from send_email
+ """
+ def login(self, *args, **kwargs):
+ pass
+
+ def sendmail(self, from_addr, to_addrs, message):
+ EMAIL_TEST_MBOX_INBOX.append(
+ {'from': from_addr,
+ 'to': to_addrs,
+ 'message': message})
+
+
+def _clear_test_inboxes():
+ global EMAIL_TEST_INBOX
+ global EMAIL_TEST_MBOX_INBOX
+ EMAIL_TEST_INBOX = []
+ EMAIL_TEST_MBOX_INBOX = []
+
+
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+### </Special email test stuff>
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+def send_email(from_addr, to_addrs, subject, message_body):
+ """
+ Simple email sending wrapper, use this so we can capture messages
+ for unit testing purposes.
+
+ Args:
+ - from_addr: address you're sending the email from
+ - to_addrs: list of recipient email addresses
+ - subject: subject of the email
+ - message_body: email body text
+ """
+ if common.TESTS_ENABLED or mg_globals.app_config['email_debug_mode']:
+ mhost = FakeMhost()
+ elif not mg_globals.app_config['email_debug_mode']:
+ mhost = smtplib.SMTP(
+ mg_globals.app_config['email_smtp_host'],
+ mg_globals.app_config['email_smtp_port'])
+
+ # SMTP.__init__ Issues SMTP.connect implicitly if host
+ if not mg_globals.app_config['email_smtp_host']: # e.g. host = ''
+ mhost.connect() # We SMTP.connect explicitly
+
+ if mg_globals.app_config['email_smtp_user'] \
+ or mg_globals.app_config['email_smtp_pass']:
+ mhost.login(
+ mg_globals.app_config['email_smtp_user'],
+ mg_globals.app_config['email_smtp_pass'])
+
+ message = MIMEText(message_body.encode('utf-8'), 'plain', 'utf-8')
+ message['Subject'] = subject
+ message['From'] = from_addr
+ message['To'] = ', '.join(to_addrs)
+
+ if common.TESTS_ENABLED:
+ EMAIL_TEST_INBOX.append(message)
+
+ if mg_globals.app_config['email_debug_mode']:
+ print u"===== Email ====="
+ print u"From address: %s" % message['From']
+ print u"To addresses: %s" % message['To']
+ print u"Subject: %s" % message['Subject']
+ print u"-- Body: --"
+ print message.get_payload(decode=True)
+
+ return mhost.sendmail(from_addr, to_addrs, message.as_string())
diff --git a/mediagoblin/tools/pagination.py b/mediagoblin/tools/pagination.py
new file mode 100644
index 00000000..5ebc3c5a
--- /dev/null
+++ b/mediagoblin/tools/pagination.py
@@ -0,0 +1,111 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 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 copy
+from math import ceil, floor
+from itertools import izip, count
+
+
+PAGINATION_DEFAULT_PER_PAGE = 30
+
+
+class Pagination(object):
+ """
+ Pagination class for mongodb queries.
+
+ Initialization through __init__(self, cursor, page=1, per_page=2),
+ get actual data slice through __call__().
+ """
+
+ def __init__(self, page, cursor, per_page=PAGINATION_DEFAULT_PER_PAGE,
+ jump_to_id=False):
+ """
+ Initializes Pagination
+
+ Args:
+ - 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.
+ """
+ self.page = page
+ self.per_page = per_page
+ self.cursor = cursor
+ self.total_count = self.cursor.count()
+ self.active_id = None
+
+ if jump_to_id:
+ cursor = copy.copy(self.cursor)
+
+ for (doc, increment) in izip(cursor, count(0)):
+ if doc._id == jump_to_id:
+ self.page = 1 + int(floor(increment / self.per_page))
+
+ self.active_id = jump_to_id
+ break
+
+
+ def __call__(self):
+ """
+ Returns slice of objects for the requested page
+ """
+ return self.cursor.skip(
+ (self.page - 1) * self.per_page).limit(self.per_page)
+
+ @property
+ def pages(self):
+ return int(ceil(self.total_count / float(self.per_page)))
+
+ @property
+ def has_prev(self):
+ return self.page > 1
+
+ @property
+ def has_next(self):
+ return self.page < self.pages
+
+ def iter_pages(self, left_edge=2, left_current=2,
+ right_current=5, right_edge=2):
+ last = 0
+ for num in xrange(1, self.pages + 1):
+ if num <= left_edge or \
+ (num > self.page - left_current - 1 and \
+ num < self.page + right_current) or \
+ num > self.pages - right_edge:
+ if last + 1 != num:
+ yield None
+ yield num
+ last = num
+
+ def get_page_url_explicit(self, base_url, get_params, page_no):
+ """
+ Get a page url by adding a page= parameter to the base url
+ """
+ new_get_params = copy.copy(get_params or {})
+ new_get_params['page'] = page_no
+ return "%s?%s" % (
+ base_url, urllib.urlencode(new_get_params))
+
+ def get_page_url(self, request, page_no):
+ """
+ Get a new page url based of the request, and the new page number.
+
+ This is a nice wrapper around get_page_url_explicit()
+ """
+ return self.get_page_url_explicit(
+ request.full_path, request.GET, page_no)
diff --git a/mediagoblin/tools/request.py b/mediagoblin/tools/request.py
new file mode 100644
index 00000000..b1cbe119
--- /dev/null
+++ b/mediagoblin/tools/request.py
@@ -0,0 +1,37 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 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.util import ObjectId
+
+def setup_user_in_request(request):
+ """
+ Examine a request and tack on a request.user parameter if that's
+ appropriate.
+ """
+ if not request.session.has_key('user_id'):
+ request.user = None
+ return
+
+ user = None
+ user = request.app.db.User.one(
+ {'_id': ObjectId(request.session['user_id'])})
+
+ if not user:
+ # Something's wrong... this user doesn't exist? Invalidate
+ # this session.
+ request.session.invalidate()
+
+ request.user = user
diff --git a/mediagoblin/tools/response.py b/mediagoblin/tools/response.py
new file mode 100644
index 00000000..b01d31a2
--- /dev/null
+++ b/mediagoblin/tools/response.py
@@ -0,0 +1,47 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 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 webob import Response, exc
+from mediagoblin.tools.template import render_template
+
+
+def render_to_response(request, template, context, status=200):
+ """Much like Django's shortcut.render()"""
+ return Response(
+ render_template(request, template, context),
+ status=status)
+
+
+def render_404(request):
+ """
+ Render a 404.
+ """
+ return render_to_response(
+ request, 'mediagoblin/404.html', {}, status=400)
+
+
+def redirect(request, *args, **kwargs):
+ """Returns a HTTPFound(), takes a request and then urlgen params"""
+
+ querystring = None
+ if kwargs.get('querystring'):
+ querystring = kwargs.get('querystring')
+ del kwargs['querystring']
+
+ return exc.HTTPFound(
+ location=''.join([
+ request.urlgen(*args, **kwargs),
+ querystring if querystring else '']))
diff --git a/mediagoblin/tools/template.py b/mediagoblin/tools/template.py
new file mode 100644
index 00000000..0986761b
--- /dev/null
+++ b/mediagoblin/tools/template.py
@@ -0,0 +1,122 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 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 math import ceil
+import jinja2
+from babel.localedata import exists
+from mediagoblin import mg_globals
+from mediagoblin import messages
+from mediagoblin.tools import common
+from mediagoblin.tools.translate import setup_gettext
+from mediagoblin.middleware.csrf import render_csrf_form_token
+
+
+SETUP_JINJA_ENVS = {}
+
+
+def get_jinja_env(template_loader, locale):
+ """
+ Set up the Jinja environment,
+
+ (In the future we may have another system for providing theming;
+ for now this is good enough.)
+ """
+ setup_gettext(locale)
+
+ # If we have a jinja environment set up with this locale, just
+ # return that one.
+ if SETUP_JINJA_ENVS.has_key(locale):
+ return SETUP_JINJA_ENVS[locale]
+
+ template_env = jinja2.Environment(
+ loader=template_loader, autoescape=True,
+ extensions=['jinja2.ext.i18n', 'jinja2.ext.autoescape'])
+
+ template_env.install_gettext_callables(
+ mg_globals.translations.ugettext,
+ mg_globals.translations.ungettext)
+
+ # All templates will know how to ...
+ # ... fetch all waiting messages and remove them from the queue
+ # ... 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
+
+ if exists(locale):
+ SETUP_JINJA_ENVS[locale] = template_env
+
+ return template_env
+
+
+# We'll store context information here when doing unit tests
+TEMPLATE_TEST_CONTEXT = {}
+
+
+def render_template(request, template_path, context):
+ """
+ Render a template with context.
+
+ Always inserts the request into the context, so you don't have to.
+ Also stores the context if we're doing unit tests. Helpful!
+ """
+ template = request.template_env.get_template(
+ template_path)
+ context['request'] = request
+ context['csrf_token'] = render_csrf_form_token(request)
+ rendered = template.render(context)
+
+ if common.TESTS_ENABLED:
+ TEMPLATE_TEST_CONTEXT[template_path] = context
+
+ return rendered
+
+
+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/testing.py b/mediagoblin/tools/testing.py
new file mode 100644
index 00000000..39435ca5
--- /dev/null
+++ b/mediagoblin/tools/testing.py
@@ -0,0 +1,45 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+from mediagoblin.tools import common
+from mediagoblin.tools.template import clear_test_template_context
+from mediagoblin.tools.mail import EMAIL_TEST_INBOX, EMAIL_TEST_MBOX_INBOX
+
+def _activate_testing():
+ """
+ Call this to activate testing in util.py
+ """
+
+ common.TESTS_ENABLED = True
+
+def clear_test_buckets():
+ """
+ We store some things for testing purposes that should be cleared
+ when we want a "clean slate" of information for our next round of
+ tests. Call this function to wipe all that stuff clean.
+
+ Also wipes out some other things we might redefine during testing,
+ like the jinja envs.
+ """
+ global SETUP_JINJA_ENVS
+ SETUP_JINJA_ENVS = {}
+
+ global EMAIL_TEST_INBOX
+ global EMAIL_TEST_MBOX_INBOX
+ EMAIL_TEST_INBOX = []
+ EMAIL_TEST_MBOX_INBOX = []
+
+ clear_test_template_context()
diff --git a/mediagoblin/tools/text.py b/mediagoblin/tools/text.py
new file mode 100644
index 00000000..be1adb00
--- /dev/null
+++ b/mediagoblin/tools/text.py
@@ -0,0 +1,124 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import wtforms
+import markdown
+from lxml.html.clean import Cleaner
+
+from mediagoblin import mg_globals
+from mediagoblin.tools import url
+
+
+# A super strict version of the lxml.html cleaner class
+HTML_CLEANER = Cleaner(
+ scripts=True,
+ javascript=True,
+ comments=True,
+ style=True,
+ links=True,
+ page_structure=True,
+ processing_instructions=True,
+ embedded=True,
+ frames=True,
+ forms=True,
+ annoying_tags=True,
+ allow_tags=[
+ 'div', 'b', 'i', 'em', 'strong', 'p', 'ul', 'ol', 'li', 'a', 'br'],
+ remove_unknown_tags=False, # can't be used with allow_tags
+ safe_attrs_only=True,
+ add_nofollow=True, # for now
+ host_whitelist=(),
+ whitelist_tags=set([]))
+
+
+def clean_html(html):
+ # clean_html barfs on an empty string
+ if not html:
+ return u''
+
+ return HTML_CLEANER.clean_html(html)
+
+
+def convert_to_tag_list_of_dicts(tag_string):
+ """
+ Filter input from incoming string containing user tags,
+
+ Strips trailing, leading, and internal whitespace, and also converts
+ the "tags" text into an array of tags
+ """
+ taglist = []
+ if tag_string:
+
+ # Strip out internal, trailing, and leading whitespace
+ stripped_tag_string = u' '.join(tag_string.strip().split())
+
+ # Split the tag string into a list of tags
+ for tag in stripped_tag_string.split(
+ mg_globals.app_config['tags_delimiter']):
+
+ # Ignore empty or duplicate tags
+ if tag.strip() and tag.strip() not in [t['name'] for t in taglist]:
+
+ taglist.append({'name': tag.strip(),
+ 'slug': url.slugify(tag.strip())})
+ return taglist
+
+
+def media_tags_as_string(media_entry_tags):
+ """
+ Generate a string from a media item's tags, stored as a list of dicts
+
+ This is the opposite of convert_to_tag_list_of_dicts
+ """
+ media_tag_string = ''
+ if media_entry_tags:
+ media_tag_string = mg_globals.app_config['tags_delimiter'].join(
+ [tag['name'] for tag in media_entry_tags])
+ return media_tag_string
+
+
+TOO_LONG_TAG_WARNING = \
+ u'Tags must be shorter than %s characters. Tags that are too long: %s'
+
+
+def tag_length_validator(form, field):
+ """
+ Make sure tags do not exceed the maximum tag length.
+ """
+ tags = convert_to_tag_list_of_dicts(field.data)
+ too_long_tags = [
+ tag['name'] for tag in tags
+ if len(tag['name']) > mg_globals.app_config['tags_max_length']]
+
+ if too_long_tags:
+ raise wtforms.ValidationError(
+ TOO_LONG_TAG_WARNING % (mg_globals.app_config['tags_max_length'], \
+ ', '.join(too_long_tags)))
+
+
+MARKDOWN_INSTANCE = markdown.Markdown(safe_mode='escape')
+
+
+def cleaned_markdown_conversion(text):
+ """
+ Take a block of text, run it through MarkDown, and clean its HTML.
+ """
+ # Markdown will do nothing with and clean_html can do nothing with
+ # an empty string :)
+ if not text:
+ return u''
+
+ return clean_html(MARKDOWN_INSTANCE.convert(text))
diff --git a/mediagoblin/tools/translate.py b/mediagoblin/tools/translate.py
new file mode 100644
index 00000000..b99c4aa4
--- /dev/null
+++ b/mediagoblin/tools/translate.py
@@ -0,0 +1,172 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 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 gettext
+import pkg_resources
+from babel.localedata import exists
+from babel.support import LazyProxy
+
+from mediagoblin import mg_globals
+
+###################
+# Translation tools
+###################
+
+
+TRANSLATIONS_PATH = pkg_resources.resource_filename(
+ 'mediagoblin', 'i18n')
+
+
+def locale_to_lower_upper(locale):
+ """
+ Take a locale, regardless of style, and format it like "en-us"
+ """
+ if '-' in locale:
+ lang, country = locale.split('-', 1)
+ return '%s_%s' % (lang.lower(), country.upper())
+ elif '_' in locale:
+ lang, country = locale.split('_', 1)
+ return '%s_%s' % (lang.lower(), country.upper())
+ else:
+ return locale.lower()
+
+
+def locale_to_lower_lower(locale):
+ """
+ Take a locale, regardless of style, and format it like "en_US"
+ """
+ if '_' in locale:
+ lang, country = locale.split('_', 1)
+ return '%s-%s' % (lang.lower(), country.lower())
+ else:
+ return locale.lower()
+
+
+def get_locale_from_request(request):
+ """
+ Figure out what target language is most appropriate based on the
+ request
+ """
+ request_form = request.GET or request.POST
+
+ if request_form.has_key('lang'):
+ return locale_to_lower_upper(request_form['lang'])
+
+ # Your routing can explicitly specify a target language
+ matchdict = request.matchdict or {}
+
+ if matchdict.has_key('locale'):
+ target_lang = matchdict['locale']
+ elif request.session.has_key('target_lang'):
+ target_lang = request.session['target_lang']
+ # Pull the first acceptable language or English
+ else:
+ # WebOb recently changed how it handles determining best language.
+ # Here's a compromise commit that handles either/or...
+ if hasattr(request.accept_language, "best_matches"):
+ accept_lang_matches = request.accept_language.best_matches()
+ if accept_lang_matches:
+ target_lang = accept_lang_matches[0]
+ else:
+ target_lang = 'en'
+ else:
+ target_lang = request.accept.best_match(
+ request.accept_language, 'en')
+
+ return locale_to_lower_upper(target_lang)
+
+SETUP_GETTEXTS = {}
+
+def setup_gettext(locale):
+ """
+ Setup the gettext instance based on this locale
+ """
+ # Later on when we have plugins we may want to enable the
+ # multi-translations system they have so we can handle plugin
+ # translations too
+
+ # TODO: fallback nicely on translations from pt_PT to pt if not
+ # available, etc.
+ if SETUP_GETTEXTS.has_key(locale):
+ this_gettext = SETUP_GETTEXTS[locale]
+ else:
+ this_gettext = gettext.translation(
+ 'mediagoblin', TRANSLATIONS_PATH, [locale], fallback=True)
+ if exists(locale):
+ SETUP_GETTEXTS[locale] = this_gettext
+
+ mg_globals.setup_globals(
+ translations=this_gettext)
+
+
+# Force en to be setup before anything else so that
+# mg_globals.translations is never None
+setup_gettext('en')
+
+
+def pass_to_ugettext(*args, **kwargs):
+ """
+ Pass a translation on to the appropriate ugettext method.
+
+ The reason we can't have a global ugettext method is because
+ mg_globals gets swapped out by the application per-request.
+ """
+ return mg_globals.translations.ugettext(
+ *args, **kwargs)
+
+
+def lazy_pass_to_ugettext(*args, **kwargs):
+ """
+ Lazily pass to ugettext.
+
+ 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.
+ """
+ return LazyProxy(pass_to_ugettext, *args, **kwargs)
+
+
+def pass_to_ngettext(*args, **kwargs):
+ """
+ Pass a translation on to the appropriate ngettext method.
+
+ The reason we can't have a global ngettext method is because
+ mg_globals gets swapped out by the application per-request.
+ """
+ return mg_globals.translations.ngettext(
+ *args, **kwargs)
+
+
+def lazy_pass_to_ngettext(*args, **kwargs):
+ """
+ Lazily pass to ngettext.
+
+ 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.
+ """
+ return LazyProxy(pass_to_ngettext, *args, **kwargs)
+
+
+def fake_ugettext_passthrough(string):
+ """
+ Fake a ugettext call for extraction's sake ;)
+
+ In wtforms there's a separate way to define a method to translate
+ things... so we just need to mark up the text so that it can be
+ extracted, not so that it's actually run through gettext.
+ """
+ return string
diff --git a/mediagoblin/tools/url.py b/mediagoblin/tools/url.py
new file mode 100644
index 00000000..78b5dd63
--- /dev/null
+++ b/mediagoblin/tools/url.py
@@ -0,0 +1,33 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# 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 re
+import translitcodec
+
+
+_punct_re = re.compile(r'[\t !"#$%&\'()*\-/<=>?@\[\\\]^_`{|},.]+')
+
+
+def slugify(text, delim=u'-'):
+ """
+ Generates an ASCII-only slug. Taken from http://flask.pocoo.org/snippets/5/
+ """
+ result = []
+ for word in _punct_re.split(text.lower()):
+ word = word.encode('translit/long')
+ if word:
+ result.append(word)
+ return unicode(delim.join(result))
diff --git a/mediagoblin/user_pages/__init__.py b/mediagoblin/user_pages/__init__.py
index 576bd0f5..ba347c69 100644
--- a/mediagoblin/user_pages/__init__.py
+++ b/mediagoblin/user_pages/__init__.py
@@ -13,5 +13,3 @@
#
# 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/>.
-
-
diff --git a/mediagoblin/user_pages/forms.py b/mediagoblin/user_pages/forms.py
index 57061d34..301f1f0a 100644
--- a/mediagoblin/user_pages/forms.py
+++ b/mediagoblin/user_pages/forms.py
@@ -16,7 +16,7 @@
import wtforms
-from mediagoblin.util import fake_ugettext_passthrough as _
+from mediagoblin.tools.translate import fake_ugettext_passthrough as _
class MediaCommentForm(wtforms.Form):
diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py
index 5458c694..097696b8 100644
--- a/mediagoblin/user_pages/views.py
+++ b/mediagoblin/user_pages/views.py
@@ -18,10 +18,11 @@ from webob import exc
from mediagoblin import messages, mg_globals
from mediagoblin.db.util import DESCENDING, ObjectId
-from mediagoblin.util import (
- Pagination, render_to_response, redirect, cleaned_markdown_conversion,
- render_404, delete_media_files)
-from mediagoblin.util import pass_to_ugettext as _
+from mediagoblin.tools.text import cleaned_markdown_conversion
+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.decorators import (uses_pagination, get_user_media_entry,
@@ -46,7 +47,7 @@ def user_home(request, page):
{'user': user})
cursor = request.db.MediaEntry.find(
- {'uploader': user['_id'],
+ {'uploader': user._id,
'state': 'processed'}).sort('created', DESCENDING)
pagination = Pagination(page, cursor)
@@ -55,7 +56,7 @@ def user_home(request, page):
#if no data is available, return NotFound
if media_entries == None:
return render_404(request)
-
+
user_gallery_url = request.urlgen(
'mediagoblin.user_pages.user_gallery',
user=user['username'])
@@ -68,6 +69,7 @@ def user_home(request, page):
'media_entries': media_entries,
'pagination': pagination})
+
@uses_pagination
def user_gallery(request, page):
"""'Gallery' of a User()"""
@@ -78,7 +80,7 @@ def user_gallery(request, page):
return render_404(request)
cursor = request.db.MediaEntry.find(
- {'uploader': user['_id'],
+ {'uploader': user._id,
'state': 'processed'}).sort('created', DESCENDING)
pagination = Pagination(page, cursor)
@@ -87,7 +89,7 @@ def user_gallery(request, page):
#if no data is available, return NotFound
if media_entries == None:
return render_404(request)
-
+
return render_to_response(
request,
'mediagoblin/user_pages/gallery.html',
@@ -97,6 +99,7 @@ def user_gallery(request, page):
MEDIA_COMMENTS_PER_PAGE = 50
+
@get_user_media_entry
@uses_pagination
def media_home(request, media, page, **kwargs):
@@ -105,11 +108,15 @@ def media_home(request, media, page, **kwargs):
"""
if ObjectId(request.matchdict.get('comment')):
pagination = Pagination(
- page, media.get_comments(), MEDIA_COMMENTS_PER_PAGE,
+ page, media.get_comments(
+ mg_globals.app_config['comments_ascending']),
+ MEDIA_COMMENTS_PER_PAGE,
ObjectId(request.matchdict.get('comment')))
else:
pagination = Pagination(
- page, media.get_comments(), MEDIA_COMMENTS_PER_PAGE)
+ page, media.get_comments(
+ mg_globals.app_config['comments_ascending']),
+ MEDIA_COMMENTS_PER_PAGE)
comments = pagination()
@@ -127,27 +134,34 @@ def media_home(request, media, page, **kwargs):
'app_config': mg_globals.app_config})
+@get_user_media_entry
@require_active_login
-def media_post_comment(request):
+def media_post_comment(request, media):
"""
recieves POST from a MediaEntry() comment form, saves the comment.
"""
+ assert request.method == 'POST'
+
comment = request.db.MediaComment()
- comment['media_entry'] = ObjectId(request.matchdict['media'])
- comment['author'] = request.user['_id']
+ comment['media_entry'] = media._id
+ comment['author'] = request.user._id
comment['content'] = unicode(request.POST['comment_content'])
-
comment['content_html'] = cleaned_markdown_conversion(comment['content'])
- comment.save()
+ if not comment['content'].strip():
+ messages.add_message(
+ request,
+ messages.ERROR,
+ _("Empty comments are not allowed."))
+ else:
+ comment.save()
- messages.add_message(
- request, messages.SUCCESS,
- 'Comment posted!')
+ messages.add_message(
+ request, messages.SUCCESS,
+ _('Comment posted!'))
- return redirect(request, 'mediagoblin.user_pages.media_home',
- media = request.matchdict['media'],
- user = request.matchdict['user'])
+ return exc.HTTPFound(
+ location=media.url_for_self(request.urlgen))
@get_user_media_entry
@@ -173,7 +187,7 @@ def media_confirm_delete(request, media):
location=media.url_for_self(request.urlgen))
if ((request.user[u'is_admin'] and
- request.user[u'_id'] != media.uploader()[u'_id'])):
+ request.user._id != media.uploader()._id)):
messages.add_message(
request, messages.WARNING,
_("You are about to delete another user's media. "
@@ -188,6 +202,7 @@ def media_confirm_delete(request, media):
ATOM_DEFAULT_NR_OF_UPDATED_ITEMS = 15
+
def atom_feed(request):
"""
generates the atom feed with the newest images
@@ -200,7 +215,7 @@ def atom_feed(request):
return render_404(request)
cursor = request.db.MediaEntry.find({
- 'uploader': user['_id'],
+ 'uploader': user._id,
'state': 'processed'}) \
.sort('created', DESCENDING) \
.limit(ATOM_DEFAULT_NR_OF_UPDATED_ITEMS)
@@ -208,7 +223,7 @@ def atom_feed(request):
feed = AtomFeed(request.matchdict['user'],
feed_url=request.url,
url=request.host_url)
-
+
for entry in cursor:
feed.add(entry.get('title'),
entry.get('description_html'),
@@ -244,7 +259,7 @@ def processing_panel(request):
#
# 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[u'_id'] == request.user[u'_id']
+ if not (user._id == request.user._id
or request.user.is_admin):
# No? Let's simply redirect to this user's homepage then.
return redirect(
@@ -253,12 +268,12 @@ def processing_panel(request):
# Get media entries which are in-processing
processing_entries = request.db.MediaEntry.find(
- {'uploader': user['_id'],
+ {'uploader': user._id,
'state': 'processing'}).sort('created', DESCENDING)
# Get media entries which have failed to process
failed_entries = request.db.MediaEntry.find(
- {'uploader': user['_id'],
+ {'uploader': user._id,
'state': 'failed'}).sort('created', DESCENDING)
# Render to response
diff --git a/mediagoblin/util.py b/mediagoblin/util.py
deleted file mode 100644
index 7ff3ec7f..00000000
--- a/mediagoblin/util.py
+++ /dev/null
@@ -1,698 +0,0 @@
-# GNU MediaGoblin -- federated, autonomous media hosting
-# Copyright (C) 2011 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 __future__ import division
-
-from email.MIMEText import MIMEText
-import gettext
-import pkg_resources
-import smtplib
-import sys
-import re
-import urllib
-from math import ceil, floor
-import copy
-import wtforms
-
-from babel.localedata import exists
-from babel.support import LazyProxy
-import jinja2
-import translitcodec
-from webob import Response, exc
-from lxml.html.clean import Cleaner
-import markdown
-from wtforms.form import Form
-
-from mediagoblin import mg_globals
-from mediagoblin import messages
-from mediagoblin.db.util import ObjectId
-
-from itertools import izip, count
-
-DISPLAY_IMAGE_FETCHING_ORDER = [u'medium', u'original', u'thumb']
-
-TESTS_ENABLED = False
-def _activate_testing():
- """
- Call this to activate testing in util.py
- """
- global TESTS_ENABLED
- TESTS_ENABLED = True
-
-
-def clear_test_buckets():
- """
- We store some things for testing purposes that should be cleared
- when we want a "clean slate" of information for our next round of
- tests. Call this function to wipe all that stuff clean.
-
- Also wipes out some other things we might redefine during testing,
- like the jinja envs.
- """
- global SETUP_JINJA_ENVS
- SETUP_JINJA_ENVS = {}
-
- global EMAIL_TEST_INBOX
- global EMAIL_TEST_MBOX_INBOX
- EMAIL_TEST_INBOX = []
- EMAIL_TEST_MBOX_INBOX = []
-
- clear_test_template_context()
-
-
-SETUP_JINJA_ENVS = {}
-
-
-def get_jinja_env(template_loader, locale):
- """
- Set up the Jinja environment,
-
- (In the future we may have another system for providing theming;
- for now this is good enough.)
- """
- setup_gettext(locale)
-
- # If we have a jinja environment set up with this locale, just
- # return that one.
- if SETUP_JINJA_ENVS.has_key(locale):
- return SETUP_JINJA_ENVS[locale]
-
- template_env = jinja2.Environment(
- loader=template_loader, autoescape=True,
- extensions=['jinja2.ext.i18n', 'jinja2.ext.autoescape'])
-
- template_env.install_gettext_callables(
- mg_globals.translations.ugettext,
- mg_globals.translations.ungettext)
-
- # All templates will know how to ...
- # ... fetch all waiting messages and remove them from the queue
- # ... construct a grid of thumbnails or other media
- template_env.globals['fetch_messages'] = messages.fetch_messages
- template_env.globals['gridify_list'] = gridify_list
- template_env.globals['gridify_cursor'] = gridify_cursor
-
- if exists(locale):
- SETUP_JINJA_ENVS[locale] = template_env
-
- return template_env
-
-
-# We'll store context information here when doing unit tests
-TEMPLATE_TEST_CONTEXT = {}
-
-
-def render_template(request, template_path, context):
- """
- Render a template with context.
-
- Always inserts the request into the context, so you don't have to.
- Also stores the context if we're doing unit tests. Helpful!
- """
- template = request.template_env.get_template(
- template_path)
- context['request'] = request
- rendered = template.render(context)
-
- if TESTS_ENABLED:
- TEMPLATE_TEST_CONTEXT[template_path] = context
-
- return rendered
-
-
-def clear_test_template_context():
- global TEMPLATE_TEST_CONTEXT
- TEMPLATE_TEST_CONTEXT = {}
-
-
-def render_to_response(request, template, context, status=200):
- """Much like Django's shortcut.render()"""
- return Response(
- render_template(request, template, context),
- status=status)
-
-
-def redirect(request, *args, **kwargs):
- """Returns a HTTPFound(), takes a request and then urlgen params"""
-
- querystring = None
- if kwargs.get('querystring'):
- querystring = kwargs.get('querystring')
- del kwargs['querystring']
-
- return exc.HTTPFound(
- location=''.join([
- request.urlgen(*args, **kwargs),
- querystring if querystring else '']))
-
-
-def setup_user_in_request(request):
- """
- Examine a request and tack on a request.user parameter if that's
- appropriate.
- """
- if not request.session.has_key('user_id'):
- request.user = None
- return
-
- user = None
- user = request.app.db.User.one(
- {'_id': ObjectId(request.session['user_id'])})
-
- if not user:
- # Something's wrong... this user doesn't exist? Invalidate
- # this session.
- request.session.invalidate()
-
- request.user = user
-
-
-def import_component(import_string):
- """
- Import a module component defined by STRING. Probably a method,
- class, or global variable.
-
- Args:
- - import_string: a string that defines what to import. Written
- in the format of "module1.module2:component"
- """
- module_name, func_name = import_string.split(':', 1)
- __import__(module_name)
- module = sys.modules[module_name]
- func = getattr(module, func_name)
- return func
-
-_punct_re = re.compile(r'[\t !"#$%&\'()*\-/<=>?@\[\\\]^_`{|},.]+')
-
-def slugify(text, delim=u'-'):
- """
- Generates an ASCII-only slug. Taken from http://flask.pocoo.org/snippets/5/
- """
- result = []
- for word in _punct_re.split(text.lower()):
- word = word.encode('translit/long')
- if word:
- result.append(word)
- return unicode(delim.join(result))
-
-### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-### Special email test stuff begins HERE
-### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-# We have two "test inboxes" here:
-#
-# EMAIL_TEST_INBOX:
-# ----------------
-# If you're writing test views, you'll probably want to check this.
-# It contains a list of MIMEText messages.
-#
-# EMAIL_TEST_MBOX_INBOX:
-# ----------------------
-# This collects the messages from the FakeMhost inbox. It's reslly
-# just here for testing the send_email method itself.
-#
-# Anyway this contains:
-# - from
-# - to: a list of email recipient addresses
-# - message: not just the body, but the whole message, including
-# headers, etc.
-#
-# ***IMPORTANT!***
-# ----------------
-# Before running tests that call functions which send email, you should
-# always call _clear_test_inboxes() to "wipe" the inboxes clean.
-
-EMAIL_TEST_INBOX = []
-EMAIL_TEST_MBOX_INBOX = []
-
-
-class FakeMhost(object):
- """
- Just a fake mail host so we can capture and test messages
- from send_email
- """
- def login(self, *args, **kwargs):
- pass
-
- def sendmail(self, from_addr, to_addrs, message):
- EMAIL_TEST_MBOX_INBOX.append(
- {'from': from_addr,
- 'to': to_addrs,
- 'message': message})
-
-def _clear_test_inboxes():
- global EMAIL_TEST_INBOX
- global EMAIL_TEST_MBOX_INBOX
- EMAIL_TEST_INBOX = []
- EMAIL_TEST_MBOX_INBOX = []
-
-### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-### </Special email test stuff>
-### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-def send_email(from_addr, to_addrs, subject, message_body):
- """
- Simple email sending wrapper, use this so we can capture messages
- for unit testing purposes.
-
- Args:
- - from_addr: address you're sending the email from
- - to_addrs: list of recipient email addresses
- - subject: subject of the email
- - message_body: email body text
- """
- if TESTS_ENABLED or mg_globals.app_config['email_debug_mode']:
- mhost = FakeMhost()
- elif not mg_globals.app_config['email_debug_mode']:
- mhost = smtplib.SMTP(
- mg_globals.app_config['email_smtp_host'],
- mg_globals.app_config['email_smtp_port'])
-
- # SMTP.__init__ Issues SMTP.connect implicitly if host
- if not mg_globals.app_config['email_smtp_host']: # e.g. host = ''
- mhost.connect() # We SMTP.connect explicitly
-
- if mg_globals.app_config['email_smtp_user'] \
- or mg_globals.app_config['email_smtp_pass']:
- mhost.login(
- mg_globals.app_config['email_smtp_user'],
- mg_globals.app_config['email_smtp_pass'])
-
- message = MIMEText(message_body.encode('utf-8'), 'plain', 'utf-8')
- message['Subject'] = subject
- message['From'] = from_addr
- message['To'] = ', '.join(to_addrs)
-
- if TESTS_ENABLED:
- EMAIL_TEST_INBOX.append(message)
-
- if mg_globals.app_config['email_debug_mode']:
- print u"===== Email ====="
- print u"From address: %s" % message['From']
- print u"To addresses: %s" % message['To']
- print u"Subject: %s" % message['Subject']
- print u"-- Body: --"
- print message.get_payload(decode=True)
-
- return mhost.sendmail(from_addr, to_addrs, message.as_string())
-
-
-###################
-# Translation tools
-###################
-
-
-TRANSLATIONS_PATH = pkg_resources.resource_filename(
- 'mediagoblin', 'i18n')
-
-
-def locale_to_lower_upper(locale):
- """
- Take a locale, regardless of style, and format it like "en-us"
- """
- if '-' in locale:
- lang, country = locale.split('-', 1)
- return '%s_%s' % (lang.lower(), country.upper())
- elif '_' in locale:
- lang, country = locale.split('_', 1)
- return '%s_%s' % (lang.lower(), country.upper())
- else:
- return locale.lower()
-
-
-def locale_to_lower_lower(locale):
- """
- Take a locale, regardless of style, and format it like "en_US"
- """
- if '_' in locale:
- lang, country = locale.split('_', 1)
- return '%s-%s' % (lang.lower(), country.lower())
- else:
- return locale.lower()
-
-
-def get_locale_from_request(request):
- """
- Figure out what target language is most appropriate based on the
- request
- """
- request_form = request.GET or request.POST
-
- if request_form.has_key('lang'):
- return locale_to_lower_upper(request_form['lang'])
-
- accept_lang_matches = request.accept_language.best_matches()
-
- # Your routing can explicitly specify a target language
- matchdict = request.matchdict or {}
-
- if matchdict.has_key('locale'):
- target_lang = matchdict['locale']
- elif request.session.has_key('target_lang'):
- target_lang = request.session['target_lang']
- # Pull the first acceptable language
- elif accept_lang_matches:
- target_lang = accept_lang_matches[0]
- # Fall back to English
- else:
- target_lang = 'en'
-
- return locale_to_lower_upper(target_lang)
-
-
-# A super strict version of the lxml.html cleaner class
-HTML_CLEANER = Cleaner(
- scripts=True,
- javascript=True,
- comments=True,
- style=True,
- links=True,
- page_structure=True,
- processing_instructions=True,
- embedded=True,
- frames=True,
- forms=True,
- annoying_tags=True,
- allow_tags=[
- 'div', 'b', 'i', 'em', 'strong', 'p', 'ul', 'ol', 'li', 'a', 'br'],
- remove_unknown_tags=False, # can't be used with allow_tags
- safe_attrs_only=True,
- add_nofollow=True, # for now
- host_whitelist=(),
- whitelist_tags=set([]))
-
-
-def clean_html(html):
- # clean_html barfs on an empty string
- if not html:
- return u''
-
- return HTML_CLEANER.clean_html(html)
-
-
-def convert_to_tag_list_of_dicts(tag_string):
- """
- Filter input from incoming string containing user tags,
-
- Strips trailing, leading, and internal whitespace, and also converts
- the "tags" text into an array of tags
- """
- taglist = []
- if tag_string:
-
- # Strip out internal, trailing, and leading whitespace
- stripped_tag_string = u' '.join(tag_string.strip().split())
-
- # Split the tag string into a list of tags
- for tag in stripped_tag_string.split(
- mg_globals.app_config['tags_delimiter']):
-
- # Ignore empty or duplicate tags
- if tag.strip() and tag.strip() not in [t['name'] for t in taglist]:
-
- taglist.append({'name': tag.strip(),
- 'slug': slugify(tag.strip())})
- return taglist
-
-
-def media_tags_as_string(media_entry_tags):
- """
- Generate a string from a media item's tags, stored as a list of dicts
-
- This is the opposite of convert_to_tag_list_of_dicts
- """
- media_tag_string = ''
- if media_entry_tags:
- media_tag_string = mg_globals.app_config['tags_delimiter'].join(
- [tag['name'] for tag in media_entry_tags])
- return media_tag_string
-
-TOO_LONG_TAG_WARNING = \
- u'Tags must be shorter than %s characters. Tags that are too long: %s'
-
-def tag_length_validator(form, field):
- """
- Make sure tags do not exceed the maximum tag length.
- """
- tags = convert_to_tag_list_of_dicts(field.data)
- too_long_tags = [
- tag['name'] for tag in tags
- if len(tag['name']) > mg_globals.app_config['tags_max_length']]
-
- if too_long_tags:
- raise wtforms.ValidationError(
- TOO_LONG_TAG_WARNING % (mg_globals.app_config['tags_max_length'], \
- ', '.join(too_long_tags)))
-
-
-MARKDOWN_INSTANCE = markdown.Markdown(safe_mode='escape')
-
-def cleaned_markdown_conversion(text):
- """
- Take a block of text, run it through MarkDown, and clean its HTML.
- """
- # Markdown will do nothing with and clean_html can do nothing with
- # an empty string :)
- if not text:
- return u''
-
- return clean_html(MARKDOWN_INSTANCE.convert(text))
-
-
-SETUP_GETTEXTS = {}
-
-def setup_gettext(locale):
- """
- Setup the gettext instance based on this locale
- """
- # Later on when we have plugins we may want to enable the
- # multi-translations system they have so we can handle plugin
- # translations too
-
- # TODO: fallback nicely on translations from pt_PT to pt if not
- # available, etc.
- if SETUP_GETTEXTS.has_key(locale):
- this_gettext = SETUP_GETTEXTS[locale]
- else:
- this_gettext = gettext.translation(
- 'mediagoblin', TRANSLATIONS_PATH, [locale], fallback=True)
- if exists(locale):
- SETUP_GETTEXTS[locale] = this_gettext
-
- mg_globals.setup_globals(
- translations=this_gettext)
-
-
-# Force en to be setup before anything else so that
-# mg_globals.translations is never None
-setup_gettext('en')
-
-
-def pass_to_ugettext(*args, **kwargs):
- """
- Pass a translation on to the appropriate ugettext method.
-
- The reason we can't have a global ugettext method is because
- mg_globals gets swapped out by the application per-request.
- """
- return mg_globals.translations.ugettext(
- *args, **kwargs)
-
-
-def lazy_pass_to_ugettext(*args, **kwargs):
- """
- Lazily pass to ugettext.
-
- 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.
- """
- return LazyProxy(pass_to_ugettext, *args, **kwargs)
-
-
-def pass_to_ngettext(*args, **kwargs):
- """
- Pass a translation on to the appropriate ngettext method.
-
- The reason we can't have a global ngettext method is because
- mg_globals gets swapped out by the application per-request.
- """
- return mg_globals.translations.ngettext(
- *args, **kwargs)
-
-
-def lazy_pass_to_ngettext(*args, **kwargs):
- """
- Lazily pass to ngettext.
-
- 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.
- """
- return LazyProxy(pass_to_ngettext, *args, **kwargs)
-
-
-def fake_ugettext_passthrough(string):
- """
- Fake a ugettext call for extraction's sake ;)
-
- In wtforms there's a separate way to define a method to translate
- things... so we just need to mark up the text so that it can be
- extracted, not so that it's actually run through gettext.
- """
- return string
-
-
-PAGINATION_DEFAULT_PER_PAGE = 30
-
-class Pagination(object):
- """
- Pagination class for mongodb queries.
-
- Initialization through __init__(self, cursor, page=1, per_page=2),
- get actual data slice through __call__().
- """
-
- def __init__(self, page, cursor, per_page=PAGINATION_DEFAULT_PER_PAGE,
- jump_to_id=False):
- """
- Initializes Pagination
-
- Args:
- - 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.
- """
- self.page = page
- self.per_page = per_page
- self.cursor = cursor
- self.total_count = self.cursor.count()
- self.active_id = None
-
- if jump_to_id:
- cursor = copy.copy(self.cursor)
-
- for (doc, increment) in izip(cursor, count(0)):
- if doc['_id'] == jump_to_id:
- self.page = 1 + int(floor(increment / self.per_page))
-
- self.active_id = jump_to_id
- break
-
-
- def __call__(self):
- """
- Returns slice of objects for the requested page
- """
- return self.cursor.skip(
- (self.page - 1) * self.per_page).limit(self.per_page)
-
- @property
- def pages(self):
- return int(ceil(self.total_count / float(self.per_page)))
-
- @property
- def has_prev(self):
- return self.page > 1
-
- @property
- def has_next(self):
- return self.page < self.pages
-
- def iter_pages(self, left_edge=2, left_current=2,
- right_current=5, right_edge=2):
- last = 0
- for num in xrange(1, self.pages + 1):
- if num <= left_edge or \
- (num > self.page - left_current - 1 and \
- num < self.page + right_current) or \
- num > self.pages - right_edge:
- if last + 1 != num:
- yield None
- yield num
- last = num
-
- def get_page_url_explicit(self, base_url, get_params, page_no):
- """
- Get a page url by adding a page= parameter to the base url
- """
- new_get_params = copy.copy(get_params or {})
- new_get_params['page'] = page_no
- return "%s?%s" % (
- base_url, urllib.urlencode(new_get_params))
-
- def get_page_url(self, request, page_no):
- """
- Get a new page url based of the request, and the new page number.
-
- This is a nice wrapper around get_page_url_explicit()
- """
- return self.get_page_url_explicit(
- request.path_info, request.GET, page_no)
-
-
-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)
-
-
-def render_404(request):
- """
- Render a 404.
- """
- return render_to_response(
- request, 'mediagoblin/404.html', {}, status=400)
-
-def delete_media_files(media):
- """
- Delete all files associated with a MediaEntry
-
- Arguments:
- - media: A MediaEntry document
- """
- for listpath in media['media_files'].itervalues():
- mg_globals.public_store.delete_file(
- listpath)
-
- for attachment in media['attachment_files']:
- mg_globals.public_store.delete_file(
- attachment['filepath'])
diff --git a/mediagoblin/views.py b/mediagoblin/views.py
index c2e3e80a..cd6aba9b 100644
--- a/mediagoblin/views.py
+++ b/mediagoblin/views.py
@@ -17,12 +17,14 @@
import sys
from mediagoblin import mg_globals
-from mediagoblin.util import render_to_response, Pagination
+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
from mediagoblin import media_types
+
@uses_pagination
def root_view(request, page):
cursor = request.db.MediaEntry.find(
diff --git a/mediagoblin/workbench.py b/mediagoblin/workbench.py
index b5e8eac5..9578494c 100644
--- a/mediagoblin/workbench.py
+++ b/mediagoblin/workbench.py
@@ -42,8 +42,10 @@ class Workbench(object):
def __unicode__(self):
return unicode(self.dir)
+
def __str__(self):
return str(self.dir)
+
def __repr__(self):
try:
return str(self)
@@ -143,7 +145,7 @@ class WorkbenchManager(object):
self.base_workbench_dir = os.path.abspath(base_workbench_dir)
if not os.path.exists(self.base_workbench_dir):
os.makedirs(self.base_workbench_dir)
-
+
def create_workbench(self):
"""
Create and return the path to a new workbench (directory).
diff --git a/paste.ini b/paste.ini
index fc459989..c729e41d 100644
--- a/paste.ini
+++ b/paste.ini
@@ -1,3 +1,6 @@
+# If you want to make changes to this file, first copy it to
+# paste_local.ini, then make the changes there.
+
[DEFAULT]
# Set to true to enable web-based debugging messages and etc.
debug = false
@@ -14,15 +17,17 @@ use = egg:Paste#urlmap
[app:mediagoblin]
use = egg:mediagoblin#app
filter-with = beaker
-config = %(here)s/mediagoblin.ini
+config = %(here)s/mediagoblin_local.ini %(here)s/mediagoblin.ini
[app:publicstore_serve]
use = egg:Paste#static
document_root = %(here)s/user_dev/media/public/
+cache_max_age = 604800
[app:mediagoblin_static]
use = egg:Paste#static
document_root = %(here)s/mediagoblin/static/
+cache_max_age = 86400
[filter:beaker]
use = egg:Beaker#beaker_session
@@ -36,7 +41,38 @@ beaker.session.lock_dir = %(here)s/user_dev/beaker/sessions/lock
use = egg:mediagoblin#errors
debug = false
+
+##############################
+# Server configuration options
+##############################
+
+# The server that is run by default.
+# By default, should only be accessable locally
[server:main]
use = egg:Paste#http
host = 127.0.0.1
port = 6543
+
+#######################
+# Helper server configs
+# ---------------------
+# If you are configuring the paste config manually, you can remove
+# these.
+
+# Use this if you want to run on port 6543 and have MediaGoblin be
+# viewable externally
+[server:broadcast]
+use = egg:Paste#http
+host = 0.0.0.0
+port = 6543
+
+# Use this if you want to connect via fastcgi
+[server:fcgi]
+use = egg:flup#fcgi_fork
+host = %(fcgi_host)s
+port = %(fcgi_port)s
+
+[server:http]
+use = egg:Paste#http
+host = %(http_host)s
+port = %(http_port)s
diff --git a/setup.py b/setup.py
index ccd1f653..c3c2f86f 100644
--- a/setup.py
+++ b/setup.py
@@ -29,23 +29,24 @@ def get_version():
if mo:
return mo.group(1)
else:
- raise RuntimeError("Unable to find version string in %s." % VERSIONFILE)
+ raise RuntimeError("Unable to find version string in %s." %
+ VERSIONFILE)
setup(
- name = "mediagoblin",
- version = get_version(),
+ name="mediagoblin",
+ version=get_version(),
packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
zip_safe=False,
# scripts and dependencies
- install_requires = [
+ install_requires=[
'setuptools',
'PasteScript',
'beaker',
'routes',
'pymongo',
'mongokit',
- 'webob',
+ 'webob<=1.2a2',
'wtforms',
'py-bcrypt',
'nose',
@@ -67,7 +68,7 @@ setup(
],
requires=['gst'],
test_suite='nose.collector',
- entry_points = """\
+ entry_points="""\
[console_scripts]
gmg = mediagoblin.gmg_commands:main_cli
pybabel = mediagoblin.babel.messages.frontend:main
@@ -84,7 +85,6 @@ setup(
[babel.extractors]
jinja2 = jinja2.ext:babel_extract
""",
-
license='AGPLv3',
author='Free Software Foundation and contributors',
author_email='cwebber@gnu.org',