aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.tx/config8
-rw-r--r--babel.ini2
-rw-r--r--docs/source/about_mediagoblin.rst (renamed from docs/source/mediagoblin.rst)0
-rw-r--r--docs/source/foreword.rst29
-rw-r--r--docs/source/git.rst224
-rw-r--r--docs/source/index.rst5
-rw-r--r--mediagoblin.ini10
-rw-r--r--mediagoblin/app.py37
-rw-r--r--mediagoblin/auth/forms.py16
-rw-r--r--mediagoblin/auth/views.py45
-rw-r--r--mediagoblin/config_spec.ini19
-rw-r--r--mediagoblin/db/migrations.py40
-rw-r--r--mediagoblin/db/models.py19
-rw-r--r--mediagoblin/decorators.py16
-rw-r--r--mediagoblin/edit/forms.py21
-rw-r--r--mediagoblin/edit/views.py108
-rw-r--r--mediagoblin/errormiddleware.py60
-rw-r--r--mediagoblin/gmg_commands/__init__.py8
-rw-r--r--mediagoblin/gmg_commands/import_export.py250
-rw-r--r--mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.mobin0 -> 8634 bytes
-rw-r--r--mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.po399
-rw-r--r--mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.mobin0 -> 8090 bytes
-rw-r--r--mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.po405
-rw-r--r--mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po382
-rw-r--r--mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.mobin0 -> 7946 bytes
-rw-r--r--mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.po402
-rw-r--r--mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.mobin0 -> 8315 bytes
-rw-r--r--mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.po416
-rw-r--r--mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.mobin0 -> 8263 bytes
-rw-r--r--mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.po407
-rw-r--r--mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.mobin0 -> 8482 bytes
-rw-r--r--mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.po393
-rw-r--r--mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.mobin0 -> 7962 bytes
-rw-r--r--mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.po399
-rw-r--r--mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.mobin0 -> 7739 bytes
-rw-r--r--mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.po397
-rw-r--r--mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.mobin0 -> 7906 bytes
-rw-r--r--mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.po397
-rw-r--r--mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.mobin0 -> 8238 bytes
-rw-r--r--mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.po414
-rw-r--r--mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.mobin0 -> 8393 bytes
-rw-r--r--mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.po387
-rw-r--r--mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.mobin0 -> 8028 bytes
-rw-r--r--mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.po411
-rw-r--r--mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.mobin0 -> 7885 bytes
-rw-r--r--mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.po385
-rw-r--r--mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.mobin0 -> 8114 bytes
-rw-r--r--mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.po408
-rw-r--r--mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.mobin0 -> 7758 bytes
-rw-r--r--mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.po393
-rw-r--r--mediagoblin/init/__init__.py11
-rw-r--r--mediagoblin/process_media/__init__.py112
-rw-r--r--mediagoblin/process_media/errors.py44
-rw-r--r--mediagoblin/static/css/base.css129
-rw-r--r--mediagoblin/static/images/404.pngbin0 -> 156189 bytes
-rw-r--r--mediagoblin/static/images/frontpage_image.pngbin0 -> 65174 bytes
-rw-r--r--mediagoblin/static/images/goblin.icobin0 -> 318 bytes
-rw-r--r--mediagoblin/static/images/goblin.pngbin0 -> 413 bytes
-rw-r--r--mediagoblin/static/images/icon_feed.pngbin522 -> 378 bytes
-rw-r--r--mediagoblin/static/images/logo.pngbin839 -> 3340 bytes
-rw-r--r--mediagoblin/storage.py167
-rw-r--r--mediagoblin/submit/forms.py8
-rw-r--r--mediagoblin/submit/views.py54
-rw-r--r--mediagoblin/templates/mediagoblin/404.html34
-rw-r--r--mediagoblin/templates/mediagoblin/auth/login.html15
-rw-r--r--mediagoblin/templates/mediagoblin/auth/register.html5
-rw-r--r--mediagoblin/templates/mediagoblin/auth/resent_verification_email.html2
-rw-r--r--mediagoblin/templates/mediagoblin/auth/verification_email.txt10
-rw-r--r--mediagoblin/templates/mediagoblin/base.html23
-rw-r--r--mediagoblin/templates/mediagoblin/edit/attachments.html55
-rw-r--r--mediagoblin/templates/mediagoblin/edit/edit.html6
-rw-r--r--mediagoblin/templates/mediagoblin/edit/edit_profile.html8
-rw-r--r--mediagoblin/templates/mediagoblin/listings/tag.html13
-rw-r--r--mediagoblin/templates/mediagoblin/root.html45
-rw-r--r--mediagoblin/templates/mediagoblin/submit/start.html9
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/gallery.html25
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/media.html124
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/processing_panel.html67
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/user.html126
-rw-r--r--mediagoblin/templates/mediagoblin/utils/feed_link.html23
-rw-r--r--mediagoblin/templates/mediagoblin/utils/object_gallery.html50
-rw-r--r--mediagoblin/templates/mediagoblin/utils/tags.html2
-rw-r--r--mediagoblin/templates/mediagoblin/utils/wtforms.html25
-rw-r--r--mediagoblin/tests/test_mgoblin_app.ini10
-rw-r--r--mediagoblin/tests/test_paste.ini2
-rw-r--r--mediagoblin/tests/test_storage.py21
-rw-r--r--mediagoblin/tests/test_submission.py59
-rw-r--r--mediagoblin/translations/en/LC_MESSAGES/mediagoblin.mobin502 -> 0 bytes
-rw-r--r--mediagoblin/translations/en/LC_MESSAGES/mediagoblin.po23
-rw-r--r--mediagoblin/user_pages/forms.py9
-rw-r--r--mediagoblin/user_pages/routing.py11
-rw-r--r--mediagoblin/user_pages/views.py70
-rw-r--r--mediagoblin/util.py120
-rw-r--r--paste.ini12
-rw-r--r--setup.py4
95 files changed, 8165 insertions, 680 deletions
diff --git a/.tx/config b/.tx/config
new file mode 100644
index 00000000..711b5d94
--- /dev/null
+++ b/.tx/config
@@ -0,0 +1,8 @@
+[mediagoblin.mediagoblin]
+file_filter = mediagoblin/i18n/<lang>/LC_MESSAGES/mediagoblin.po
+source_file = mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po
+source_lang = en
+
+[main]
+host = https://www.transifex.net
+
diff --git a/babel.ini b/babel.ini
index 666270df..a4e3267a 100644
--- a/babel.ini
+++ b/babel.ini
@@ -10,4 +10,4 @@ encoding = utf-8
# # Extraction from JavaScript files
# [javascript: mediagoblin/static/js/**.js]
-# extract_messages = $._, jQuery._ \ No newline at end of file
+# extract_messages = $._, jQuery._
diff --git a/docs/source/mediagoblin.rst b/docs/source/about_mediagoblin.rst
index af6658f3..af6658f3 100644
--- a/docs/source/mediagoblin.rst
+++ b/docs/source/about_mediagoblin.rst
diff --git a/docs/source/foreword.rst b/docs/source/foreword.rst
index 1d423f08..4fd96842 100644
--- a/docs/source/foreword.rst
+++ b/docs/source/foreword.rst
@@ -8,26 +8,19 @@ About this manual
This is the GNU MediaGoblin manual. This documentation targets the
following groups of individuals:
-* people who want to use the software
-* people who want to deploy the software
-* contributors
-
-This manual is a living document and is in the ``mediagoblin``
-repository in the ``docs/`` directory.
+* people who want to try the software locally
+* people who want to deploy and administrate the software
+This manual doesn't cover contributors to the codebase. But we want
+and love contributors! To join as a contributor please visit the
+following pages instead:
-Who wrote this documentation?
-=============================
+* http://mediagoblin.org/pages/join.html for general "join us" information
+* http://wiki.mediagoblin.org/ for our contributor-focused wiki
-In no particular order:
-
-* Chris
-* Will
-* Deb
-* Greg
-* Karen
-* Matt
-* Asheesh
+If you are viewing this from http://docs.mediagoblin.org be aware that
+this manual is a living document and is in the ``mediagoblin``
+repository in the ``docs/`` directory.
I found an error in the docs---who do I tell?
@@ -35,7 +28,7 @@ I found an error in the docs---who do I tell?
There are a few ways---please pick the one most convenient to you!
-1. Write up a bug report in the bug tracker at http://bugs.foocorp.net/ .
+1. Write up a bug report in the bug tracker at http://bugs.foocorp.net/projects/mediagoblin/issues
2. Tell someone on IRC ``#mediagoblin`` on Freenode.
3. Send an email to Will ``willg at bluesock dot org``.
diff --git a/docs/source/git.rst b/docs/source/git.rst
deleted file mode 100644
index ab3206b6..00000000
--- a/docs/source/git.rst
+++ /dev/null
@@ -1,224 +0,0 @@
-==========================
- Git, Cloning and Patches
-==========================
-
-.. contents:: Sections
- :local:
-
-
-GNU MediaGoblin uses git for all our version control and we have the
-repositories hosted on `Gitorious <http://gitorious.org/>`_. We have
-two repositories:
-
-* MediaGoblin software: http://gitorious.org/mediagoblin/mediagoblin
-* MediaGoblin website: http://gitorious.org/mediagoblin/mediagoblin-website
-
-It's most likely you want to look at the software repository--not the
-website one.
-
-The rest of this chapter talks about using the software repository.
-
-
-How to clone the project
-========================
-
-Do::
-
- git clone git://gitorious.org/mediagoblin/mediagoblin.git
-
-
-How to contribute changes
-=========================
-
-Tie your changes to issues in the issue tracker
------------------------------------------------
-
-All patches should be tied to issues in the `issue tracker
-<http://bugs.foocorp.net/projects/mediagoblin/issues>`_. That makes
-it a lot easier for everyone to track proposed changes and make sure
-your hard work doesn't get dropped on the floor! If there isn't an
-issue for what you're working on, please create one. The better the
-description of what it is you're trying to fix/implement, the better
-everyone else is able to understand why you're doing what you're
-doing.
-
-
-Use bugfix branches to make changes
------------------------------------
-
-The best way to isolate your changes is to create a branch based off
-of the MediaGoblin repository master branch, do the changes related to
-that one issue there, and then let us know how to get it.
-
-It's much easier on us if you isolate your changes to a branch focused
-on the issue. Then we don't have to sift through things.
-
-It's much easier on you if you isolate your changes to a branch
-focused on the issue. Then when we merge your changes in, you just
-have to do a ``git fetch`` and that's it. This is especially true if
-we reject some of your changes, but accept others or otherwise tweak
-your changes.
-
-Further, if you isolate your changes to a branch, then you can work on
-multiple issues at the same time and they don't conflict with one
-another.
-
-Name your branches using the isue number and something that makes it clear
-what it's about. For example, if you were working on tagging, you
-might name your branch ``360_tagging``.
-
-
-Properly document your changes
-------------------------------
-
-Include comments in the code.
-
-Write comprehensive commit messages. The better your commit message
-is at describing what you did and why, the easier it is for us to
-quickly accept your patch.
-
-Write comprehensive comments in the issue tracker about what you're
-doing and why.
-
-
-How to send us your changes
----------------------------
-
-There are two ways to let us know how to get it:
-
-1. *(preferred)* **push changes to publicly available git clone and
- let us know where to find it**
-
- Push your feature/bugfix/issue branch to your publicly available
- git clone and add a comment to the issue with the url for your
- clone and the branch to look at.
-
-2. **attaching the patch files to the issue**
-
- Run::
-
- git format-patch --stdout <remote>/master > issue_<number>.patch
-
- ``format-patch`` creates a patch of all the commits that are in
- your branch that aren't in ``<remote>/master``. The ``--stdout``
- flag causes all this output to go to stdout where it's redirected
- to a file named ``issue_<number>.patch``. That file should be
- based on the issue you're working with. For example,
- ``issue_42.patch`` is a good filename and ``issue_42_rev2.patch``
- is good if you did a revision of it.
-
- Having said all that, the filename isn't wildly important.
-
-
-Example workflow
-================
-
-Here's an example workflow.
-
-
-Contributing changes
---------------------
-
-Slartibartfast from the planet Magrathea far off in the universe has
-decided that he is bored with fjords and wants to fix issue 42 (the
-meaning of life bug) and send us the changes.
-
-Slartibartfast has cloned the MediaGoblin repository and his clone
-lives on gitorious.
-
-Slartibartfast works locally. The remote named ``origin`` points to
-his clone on gitorious. The remote named ``gmg`` points to the
-MediaGoblin repository.
-
-Slartibartfast does the following:
-
-1. Fetches the latest from the MediaGoblin repository::
-
- git fetch --all -p
-
- This tells ``git fetch`` to fetch all the recent data from all of
- the remotes (``--all``) and prune any branches that have been
- deleted in the remotes (``-p``).
-
-2. Creates a branch from the tip of the MediaGoblin repository (the
- remote is named ``gmg``) master branch called ``bug42_meaning_of_life``::
-
- git checkout -b bug42_meaning_of_life gmg/master
-
- This creates a new branch (``-b``) named ``bug42_meaning_of_life`` based
- on the tip of the ``master`` branch of the remote named ``gmg`` and checks
- it out.
-
-3. Slartibartfast works hard on his changes in the ``bug42_meaning_of_life``
- branch. When done, he wants to notify us that he has made changes
- he wants us to see.
-
-4. Slartibartfast pushes his changes to his clone::
-
- git push origin bug42_meaning_of_life --set-upstream
-
- This pushes the changes in the ``bug42_meaning_of_life`` branch to the
- remote named ``origin``.
-
-5. Slartibartfast adds a comment to issue 42 with the url for his
- repository and the name of the branch he put the code in. He also
- explains what he did and why it addresses the issue.
-
-
-Updating a contribution
------------------------
-
-Slartibartfast brushes his hands off with the sense of accomplishment
-that comes with the knowledge of a job well done. He stands, wanders
-over to get a cup of water, then realizes that he forgot to run the
-unit tests!
-
-He runs the unit tests and discovers there's a bug in the code!
-
-Then he does this:
-
-1. He checks out the ``bug42_meaning_of_life`` branch::
-
- git checkout bug42_meaning_of_life
-
-2. He fixes the bug and checks it into the ``bug42_meaning_of_life`` branch.
-
-3. He pushes his changes to his clone (the remote is named ``origin``)::
-
- git push origin bug42_meaning_of_life
-
-4. He adds another comment to issue 42 explaining about the mistake
- and how he fixed it and that he's pushed the new change to the
- ``bug42_meaning_of_life`` branch of his publicly available clone.
-
-
-What happens next
------------------
-
-Slartibartfast is once again happy with his work. He finds issue 42
-in the issue tracker and adds a comment saying he submitted a merge
-request with his changes and explains what they are.
-
-Later, someone checks out his code and finds a problem with it. He
-adds a comment to the issue tracker specifying the problem and asks
-Slartibartfast to fix it. Slartibartfst goes through the above steps
-again, fixes the issue, pushes it to his ``bug42_meaning_of_life`` branch and adds
-another comment to the issue tracker about how he fixed it.
-
-Later, someone checks out his code and is happy with it. Someone
-pulls it into the master branch of the MediaGoblin repository and adds
-another comment to the issue and probably closes the issue out.
-
-Slartibartfast is notified of this. Slartibartfast does a::
-
- git fetch --all
-
-The changes show up in the ``master`` branch of the ``gmg`` remote.
-Slartibartfast now deletes his ``bug42_meaning_of_life`` branch
-because he doesn't need it anymore.
-
-
-How to learn git
-================
-
-Check out `the wiki <http://wiki.mediagoblin.org/>`_.
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 8c00869a..79f2653e 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -12,11 +12,10 @@ Table of Contents:
:maxdepth: 2
foreword
- mediagoblin
- contributinghowto
+ about_mediagoblin
deploymenthowto
theminghowto
- git
+ contributinghowto
codebase
vision
diff --git a/mediagoblin.ini b/mediagoblin.ini
index e889646a..c22d12d7 100644
--- a/mediagoblin.ini
+++ b/mediagoblin.ini
@@ -1,7 +1,4 @@
[mediagoblin]
-queuestore_base_dir = %(here)s/user_dev/media/queue
-publicstore_base_dir = %(here)s/user_dev/media/public
-publicstore_base_url = /mgoblin_media/
direct_remote_path = /mgoblin_static/
email_sender_address = "notice@mediagoblin.example.org"
@@ -14,5 +11,12 @@ allow_registration = true
## Uncomment this to put some user-overriding templates here
#local_templates = %(here)s/user_dev/templates/
+[storage:queuestore]
+base_dir = %(here)s/user_dev/media/queue
+
+[storage:publicstore]
+base_dir = %(here)s/user_dev/media/public
+base_url = /mgoblin_media/
+
[celery]
# Put celery stuff here
diff --git a/mediagoblin/app.py b/mediagoblin/app.py
index c1ee3d77..3030929d 100644
--- a/mediagoblin/app.py
+++ b/mediagoblin/app.py
@@ -101,6 +101,23 @@ class MediaGoblinApp(object):
## Routing / controller loading stuff
route_match = self.routing.match(path_info)
+ ## Attach utilities to the request object
+ request.matchdict = route_match
+ request.urlgen = routes.URLGenerator(self.routing, environ)
+ # Do we really want to load this via middleware? Maybe?
+ request.session = request.environ['beaker.session']
+ # 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.template_env = util.get_jinja_env(
+ self.template_loader, request.locale)
+ request.db = self.db
+ request.staticdirect = self.staticdirector
+
+ util.setup_user_in_request(request)
+
# No matching page?
if route_match is None:
# Try to do see if we have a match with a trailing slash
@@ -116,28 +133,12 @@ class MediaGoblinApp(object):
return request.get_response(redirect)(environ, start_response)
# Okay, no matches. 404 time!
- return exc.HTTPNotFound()(environ, start_response)
+ request.matchdict = {} # in case our template expects it
+ return util.render_404(request)(environ, start_response)
controller = util.import_component(route_match['controller'])
request.start_response = start_response
- ## Attach utilities to the request object
- request.matchdict = route_match
- request.urlgen = routes.URLGenerator(self.routing, environ)
- # Do we really want to load this via middleware? Maybe?
- request.session = request.environ['beaker.session']
- # 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.template_env = util.get_jinja_env(
- self.template_loader, request.locale)
- request.db = self.db
- request.staticdirect = self.staticdirector
-
- util.setup_user_in_request(request)
-
return controller(request)(environ, start_response)
diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py
index 7bc0aeb1..917909c5 100644
--- a/mediagoblin/auth/forms.py
+++ b/mediagoblin/auth/forms.py
@@ -16,34 +16,36 @@
import wtforms
+from mediagoblin.util import fake_ugettext_passthrough as _
+
class RegistrationForm(wtforms.Form):
username = wtforms.TextField(
- 'Username',
+ _('Username'),
[wtforms.validators.Required(),
wtforms.validators.Length(min=3, max=30),
wtforms.validators.Regexp(r'^\w+$')])
password = wtforms.PasswordField(
- 'Password',
+ _('Password'),
[wtforms.validators.Required(),
wtforms.validators.Length(min=6, max=30),
wtforms.validators.EqualTo(
'confirm_password',
- 'Passwords must match.')])
+ _('Passwords must match.'))])
confirm_password = wtforms.PasswordField(
- 'Confirm password',
+ _('Confirm password'),
[wtforms.validators.Required()])
email = wtforms.TextField(
- 'Email address',
+ _('Email address'),
[wtforms.validators.Required(),
wtforms.validators.Email()])
class LoginForm(wtforms.Form):
username = wtforms.TextField(
- 'Username',
+ _('Username'),
[wtforms.validators.Required(),
wtforms.validators.Regexp(r'^\w+$')])
password = wtforms.PasswordField(
- 'Password',
+ _('Password'),
[wtforms.validators.Required()])
diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py
index df7e2a88..4c4a34fd 100644
--- a/mediagoblin/auth/views.py
+++ b/mediagoblin/auth/views.py
@@ -20,7 +20,8 @@ from webob import exc
from mediagoblin import messages
from mediagoblin import mg_globals
-from mediagoblin.util import render_to_response, redirect
+from mediagoblin.util import render_to_response, redirect, render_404
+from mediagoblin.util import pass_to_ugettext as _
from mediagoblin.db.util import ObjectId
from mediagoblin.auth import lib as auth_lib
from mediagoblin.auth import forms as auth_forms
@@ -36,7 +37,7 @@ def register(request):
messages.add_message(
request,
messages.WARNING,
- ('Sorry, registration is disabled on this instance.'))
+ _('Sorry, registration is disabled on this instance.'))
return redirect(request, "index")
register_form = auth_forms.RegistrationForm(request.POST)
@@ -44,20 +45,27 @@ def register(request):
if request.method == 'POST' and register_form.validate():
# TODO: Make sure the user doesn't exist already
- users_with_username = \
- request.db.User.find({
- 'username': request.POST['username'].lower()
- }).count()
+ users_with_username = request.db.User.find(
+ {'username': request.POST['username'].lower()}).count()
+ users_with_email = request.db.User.find(
+ {'email': request.POST['email'].lower()}).count()
+
+ extra_validation_passes = True
if users_with_username:
register_form.username.errors.append(
- u'Sorry, a user with that name already exists.')
-
- else:
+ _(u'Sorry, a user with that name already exists.'))
+ extra_validation_passes = False
+ if users_with_email:
+ register_form.email.errors.append(
+ _(u'Sorry, that email address has already been taken.'))
+ extra_validation_passes = False
+
+ if extra_validation_passes:
# Create the user
user = request.db.User()
user['username'] = request.POST['username'].lower()
- user['email'] = request.POST['email']
+ user['email'] = request.POST['email'].lower()
user['pw_hash'] = auth_lib.bcrypt_gen_password_hash(
request.POST['password'])
user.save(validate=True)
@@ -136,7 +144,7 @@ def verify_email(request):
"""
# 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'):
- return exc.HTTPNotFound()
+ return render_404(request)
user = request.db.User.find_one(
{'_id': ObjectId(unicode(request.GET['userid']))})
@@ -148,16 +156,17 @@ def verify_email(request):
messages.add_message(
request,
messages.SUCCESS,
- ('Your email address has been verified. '
- 'You may now login, edit your profile, and submit images!'))
+ _("Your email address has been verified. "
+ "You may now login, edit your profile, and submit images!"))
else:
- messages.add_message(request,
- messages.ERROR,
- 'The verification key or user id is incorrect')
+ messages.add_message(
+ request,
+ messages.ERROR,
+ _('The verification key or user id is incorrect'))
return redirect(
request, 'mediagoblin.user_pages.user_home',
- user=request.user['username'])
+ user=user['username'])
def resend_activation(request):
@@ -174,7 +183,7 @@ def resend_activation(request):
messages.add_message(
request,
messages.INFO,
- 'Resent your verification email.')
+ _('Resent your verification email.'))
return redirect(
request, 'mediagoblin.user_pages.user_home',
user=request.user['username'])
diff --git a/mediagoblin/config_spec.ini b/mediagoblin/config_spec.ini
index 0bc7d6ad..a0fbde09 100644
--- a/mediagoblin/config_spec.ini
+++ b/mediagoblin/config_spec.ini
@@ -4,15 +4,10 @@ db_host = string()
db_name = string(default="mediagoblin")
db_port = integer()
-#
-queuestore_base_dir = string(default="%(here)s/user_dev/media/queue")
-publicstore_base_dir = string(default="%(here)s/user_dev/media/public")
# Where temporary files used in processing and etc are kept
workbench_path = string(default="%(here)s/user_dev/media/workbench")
-#
-publicstore_base_url = string(default="/mgoblin_media/")
# Where mediagoblin-builtin static assets are kept
direct_remote_path = string(default="/mgoblin_static/")
@@ -41,6 +36,20 @@ local_templates = string()
# itself)
celery_setup_elsewhere = boolean(default=False)
+# Whether or not users are able to upload files of any filetype with
+# their media entries -- This is useful if you want to provide the
+# source files for a media file but can also be a HUGE security risk.
+allow_attachments = boolean(default=False)
+
+
+[storage:publicstore]
+base_dir = string(default="%(here)s/user_dev/media/public")
+base_url = string(default="/mgoblin_media/")
+
+[storage:queuestore]
+base_dir = string(default="%(here)s/user_dev/media/queue")
+
+
[celery]
# known booleans
celery_result_persistent = boolean()
diff --git a/mediagoblin/db/migrations.py b/mediagoblin/db/migrations.py
index 6a8ebcf9..5456b248 100644
--- a/mediagoblin/db/migrations.py
+++ b/mediagoblin/db/migrations.py
@@ -52,3 +52,43 @@ def mediaentry_mediafiles_main_to_original(database):
document['media_files']['original'] = original
collection.save(document)
+
+
+@RegisterMigration(3)
+def mediaentry_remove_thumbnail_file(database):
+ """
+ Use media_files['thumb'] instead of media_entries['thumbnail_file']
+ """
+ database['media_entries'].update(
+ {'thumbnail_file': {'$exists': True}},
+ {'$unset': {'thumbnail_file': 1}},
+ multi=True)
+
+
+@RegisterMigration(4)
+def mediaentry_add_queued_task_id(database):
+ """
+ Add the 'queued_task_id' field for entries that don't have it.
+ """
+ collection = database['media_entries']
+ collection.update(
+ {'queued_task_id': {'$exists': False}},
+ {'$set': {'queued_task_id': None}},
+ multi=True)
+
+
+@RegisterMigration(5)
+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)
diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py
index 4ef2d928..b6e52441 100644
--- a/mediagoblin/db/models.py
+++ b/mediagoblin/db/models.py
@@ -162,6 +162,8 @@ class MediaEntry(Document):
queued for processing. This is stored in the mg_globals.queue_store
storage system.
+ - queued_task_id: celery task id. Use this to fetch the task state.
+
- media_files: Files relevant to this that have actually been processed
and are available for various types of display. Stored like:
{'thumb': ['dir1', 'dir2', 'pic.png'}
@@ -170,7 +172,8 @@ class MediaEntry(Document):
critical to this piece of media but may be usefully relevant to people
viewing the work. (currently unused.)
- - thumbnail_file: Deprecated... we should remove this ;)
+ - fail_error: path to the exception raised
+ - fail_metadata:
"""
__collection__ = 'media_entries'
@@ -190,6 +193,7 @@ class MediaEntry(Document):
# For now let's assume there can only be one main file queued
# at a time
'queued_media_file': [unicode],
+ 'queued_task_id': unicode,
# A dictionary of logical names to filepaths
'media_files': dict,
@@ -198,8 +202,10 @@ class MediaEntry(Document):
# record form
'attachment_files': list,
- # This one should just be a single file record
- 'thumbnail_file': [unicode]}
+ # If things go badly in processing things, we'll store that
+ # data here
+ 'fail_error': unicode,
+ 'fail_metadata': dict}
required_fields = [
'uploader', 'created', 'media_type', 'slug']
@@ -291,6 +297,13 @@ class MediaEntry(Document):
def uploader(self):
return self.db.User.find_one({'_id': self['uploader']})
+ def get_fail_exception(self):
+ """
+ Get the exception that's appropriate for this error
+ """
+ if self['fail_error']:
+ return util.import_component(self['fail_error'])
+
class MediaComment(Document):
"""
diff --git a/mediagoblin/decorators.py b/mediagoblin/decorators.py
index 2e90274e..c66049ca 100644
--- a/mediagoblin/decorators.py
+++ b/mediagoblin/decorators.py
@@ -17,7 +17,7 @@
from webob import exc
-from mediagoblin.util import redirect
+from mediagoblin.util import redirect, render_404
from mediagoblin.db.util import ObjectId, InvalidId
@@ -60,9 +60,9 @@ def uses_pagination(controller):
try:
page = int(request.GET.get('page', 1))
if page < 0:
- return exc.HTTPNotFound()
+ return render_404(request)
except ValueError:
- return exc.HTTPNotFound()
+ return render_404(request)
return controller(request, page=page, *args, **kwargs)
@@ -78,7 +78,7 @@ def get_user_media_entry(controller):
{'username': request.matchdict['user']})
if not user:
- return exc.HTTPNotFound()
+ return render_404(request)
media = request.db.MediaEntry.find_one(
{'slug': request.matchdict['media'],
@@ -93,11 +93,11 @@ def get_user_media_entry(controller):
'state': 'processed',
'uploader': user['_id']})
except InvalidId:
- return exc.HTTPNotFound()
+ return render_404(request)
# Still no media? Okay, 404.
if not media:
- return exc.HTTPNotFound()
+ return render_404(request)
return controller(request, media=media, *args, **kwargs)
@@ -113,11 +113,11 @@ def get_media_entry_by_id(controller):
{'_id': ObjectId(request.matchdict['media']),
'state': 'processed'})
except InvalidId:
- return exc.HTTPNotFound()
+ return render_404(request)
# Still no media? Okay, 404.
if not media:
- return exc.HTTPNotFound()
+ return render_404(request)
return controller(request, media=media, *args, **kwargs)
diff --git a/mediagoblin/edit/forms.py b/mediagoblin/edit/forms.py
index a1783a72..c5ab9fd9 100644
--- a/mediagoblin/edit/forms.py
+++ b/mediagoblin/edit/forms.py
@@ -16,25 +16,34 @@
import wtforms
+
from mediagoblin.util import tag_length_validator, TOO_LONG_TAG_WARNING
+from mediagoblin.util import fake_ugettext_passthrough as _
class EditForm(wtforms.Form):
title = wtforms.TextField(
- 'Title',
+ _('Title'),
[wtforms.validators.Length(min=0, max=500)])
slug = wtforms.TextField(
- 'Slug',
- [wtforms.validators.Required(message="The slug can't be empty")])
+ _('Slug'),
+ [wtforms.validators.Required(message=_("The slug can't be empty"))])
description = wtforms.TextAreaField('Description of this work')
tags = wtforms.TextField(
- 'Tags',
+ _('Tags'),
[tag_length_validator])
class EditProfileForm(wtforms.Form):
- bio = wtforms.TextAreaField('Bio',
+ bio = wtforms.TextAreaField(
+ _('Bio'),
[wtforms.validators.Length(min=0, max=500)])
url = wtforms.TextField(
- 'Website',
+ _('Website'),
[wtforms.validators.Optional(),
wtforms.validators.URL(message='Improperly formed URL')])
+
+class EditAttachmentsForm(wtforms.Form):
+ attachment_name = wtforms.TextField(
+ 'Title')
+ attachment_file = wtforms.FileField(
+ 'File')
diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py
index 5cbaadb5..b0145a04 100644
--- a/mediagoblin/edit/views.py
+++ b/mediagoblin/edit/views.py
@@ -17,12 +17,17 @@
from webob import exc
from string import split
+from cgi import FieldStorage
+from datetime import datetime
+
+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.edit import forms
from mediagoblin.edit.lib import may_edit_media
from mediagoblin.decorators import require_active_login, get_user_media_entry
@@ -34,11 +39,18 @@ def edit_media(request, media):
if not may_edit_media(request, media):
return exc.HTTPForbidden()
- form = forms.EditForm(request.POST,
- title = media['title'],
- slug = media['slug'],
- description = media['description'],
- tags = media_tags_as_string(media['tags']))
+ defaults = dict(
+ title=media['title'],
+ slug=media['slug'],
+ description=media['description'],
+ tags=media_tags_as_string(media['tags']))
+
+ if len(media['attachment_files']):
+ defaults['attachment_name'] = media['attachment_files'][0]['name']
+
+ form = forms.EditForm(
+ request.POST,
+ **defaults)
if request.method == 'POST' and form.validate():
# Make sure there isn't already a MediaEntry with such a slug
@@ -47,19 +59,27 @@ def edit_media(request, media):
{'slug': request.POST['slug'],
'uploader': media['uploader'],
'_id': {'$ne': media['_id']}}).count()
-
+
if existing_user_slug_entries:
form.slug.errors.append(
- u'An entry with that slug already exists for this user.')
+ _(u'An entry with that slug already exists for this user.'))
else:
media['title'] = request.POST['title']
media['description'] = request.POST.get('description')
media['tags'] = convert_to_tag_list_of_dicts(
request.POST.get('tags'))
-
+
media['description_html'] = cleaned_markdown_conversion(
media['description'])
+ if 'attachment_name' in request.POST:
+ media['attachment_files'][0]['name'] = \
+ request.POST['attachment_name']
+
+ if 'attachment_delete' in request.POST \
+ and 'y' == request.POST['attachment_delete']:
+ del media['attachment_files'][0]
+
media['slug'] = request.POST['slug']
media.save()
@@ -71,19 +91,69 @@ def edit_media(request, media):
and request.method != 'POST':
messages.add_message(
request, messages.WARNING,
- "You are editing another user's media. Proceed with caution.")
-
+ _("You are editing another user's media. Proceed with caution."))
return render_to_response(
request,
'mediagoblin/edit/edit.html',
{'media': media,
'form': form})
-
+
+@get_user_media_entry
@require_active_login
-def edit_profile(request):
+def edit_attachments(request, media):
+ if mg_globals.app_config['allow_attachments']:
+ form = forms.EditAttachmentsForm()
+
+ # Add any attachements
+ if ('attachment_file' in request.POST
+ and isinstance(request.POST['attachment_file'], FieldStorage)
+ and request.POST['attachment_file'].file):
+
+ attachment_public_filepath \
+ = mg_globals.public_store.get_unique_filepath(
+ ['media_entries', unicode(media['_id']), 'attachment',
+ secure_filename(request.POST['attachment_file'].filename)])
+
+ attachment_public_file = mg_globals.public_store.get_file(
+ attachment_public_filepath, 'wb')
+
+ try:
+ attachment_public_file.write(
+ request.POST['attachment_file'].file.read())
+ finally:
+ request.POST['attachment_file'].file.close()
+
+ media['attachment_files'].append(dict(
+ name=request.POST['attachment_name'] \
+ or request.POST['attachment_file'].filename,
+ filepath=attachment_public_filepath,
+ created=datetime.utcnow()
+ ))
+ media.save()
+
+ messages.add_message(
+ request, messages.SUCCESS,
+ "You added the attachment %s!" \
+ % (request.POST['attachment_name']
+ or request.POST['attachment_file'].filename))
+
+ return redirect(request, 'mediagoblin.user_pages.media_home',
+ user=media.uploader()['username'],
+ media=media['slug'])
+ return render_to_response(
+ request,
+ 'mediagoblin/edit/attachments.html',
+ {'media': media,
+ 'form': form})
+ else:
+ return exc.HTTPForbidden()
+
+
+@require_active_login
+def edit_profile(request):
# admins may edit any user profile given a username in the querystring
edit_username = request.GET.get('username')
if request.user['is_admin'] and request.user['username'] != edit_username:
@@ -92,13 +162,13 @@ def edit_profile(request):
if request.method != 'POST':
messages.add_message(
request, messages.WARNING,
- "You are editing a user's profile. Proceed with caution.")
+ _("You are editing a user's profile. Proceed with caution."))
else:
user = request.user
form = forms.EditProfileForm(request.POST,
- url = user.get('url'),
- bio = user.get('bio'))
+ url=user.get('url'),
+ bio=user.get('bio'))
if request.method == 'POST' and form.validate():
user['url'] = request.POST['url']
@@ -108,12 +178,12 @@ def edit_profile(request):
user.save()
- messages.add_message(request,
- messages.SUCCESS,
- 'Profile edited!')
+ messages.add_message(request,
+ messages.SUCCESS,
+ 'Profile edited!')
return redirect(request,
'mediagoblin.user_pages.user_home',
- user=edit_username)
+ user=edit_username)
return render_to_response(
request,
diff --git a/mediagoblin/errormiddleware.py b/mediagoblin/errormiddleware.py
new file mode 100644
index 00000000..352dc891
--- /dev/null
+++ b/mediagoblin/errormiddleware.py
@@ -0,0 +1,60 @@
+# 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/>.
+
+from paste.exceptions.errormiddleware import make_error_middleware
+
+MGOBLIN_ERROR_MESSAGE = """\
+<div style="text-align:center;font-family: monospace">
+ <h1>YEOWCH... that's an error!</h1>
+ <pre>
+.-------------------------.
+| __ _ |
+| -, \_,------,_// |
+| <\ ,-- --.\ |
+| / (x ) ( X ) |
+| ' '--, ,--'\ |
+| / \ -v-v-u-v / |
+| . '.__.--__'.\ |
+| / ',___/ / \__/' |
+| | | ,'\_'/, || |
+| \_| | | | | || |
+| W',_ ||| |||_'' |
+| | '------'| |
+| |__| |_|_ |
+| ,,,-' '-,,, |
+'-------------------------'
+ </pre>
+ <p>Something bad happened, and things broke.</p>
+ <p>If this is not your website, you may want to alert the owner.</p>
+ <br><br>
+ <p>
+ Powered... er broken... by
+ <a href="http://www.mediagoblin.org">MediaGoblin</a>,
+ a <a href="http://www.gnu.org">GNU Project</a>.
+ </p>
+</div>"""
+
+
+def mgoblin_error_middleware(app, global_conf, **kw):
+ """
+ MediaGoblin wrapped error middleware.
+
+ This is really just wrapping the error middleware from Paste.
+ It should take all of Paste's default options, so see:
+ http://pythonpaste.org/modules/exceptions.html
+ """
+ kw['error_message'] = MGOBLIN_ERROR_MESSAGE
+ return make_error_middleware(app, global_conf, **kw)
diff --git a/mediagoblin/gmg_commands/__init__.py b/mediagoblin/gmg_commands/__init__.py
index 921f0430..8226fd0e 100644
--- a/mediagoblin/gmg_commands/__init__.py
+++ b/mediagoblin/gmg_commands/__init__.py
@@ -44,6 +44,14 @@ SUBCOMMAND_MAP = {
'setup': 'mediagoblin.gmg_commands.wipealldata:wipe_parser_setup',
'func': 'mediagoblin.gmg_commands.wipealldata:wipe',
'help': 'Wipes **all** the data for this MediaGoblin instance'},
+ 'env_export': {
+ 'setup': 'mediagoblin.gmg_commands.import_export:import_export_parse_setup',
+ 'func': 'mediagoblin.gmg_commands.import_export:env_export',
+ 'help': 'Exports the data for this MediaGoblin instance'},
+ 'env_import': {
+ 'setup': 'mediagoblin.gmg_commands.import_export:import_export_parse_setup',
+ 'func': 'mediagoblin.gmg_commands.import_export:env_import',
+ 'help': 'Exports the data for this MediaGoblin instance'},
}
diff --git a/mediagoblin/gmg_commands/import_export.py b/mediagoblin/gmg_commands/import_export.py
new file mode 100644
index 00000000..367924a5
--- /dev/null
+++ b/mediagoblin/gmg_commands/import_export.py
@@ -0,0 +1,250 @@
+# 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/>.
+
+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 import BasicFileStorage
+from mediagoblin.init import setup_storage, setup_global_and_app_config
+
+import shutil
+import tarfile
+import tempfile
+import subprocess
+import os.path
+import os
+import sys
+from contextlib import closing
+
+
+def import_export_parse_setup(subparser):
+ # TODO: Add default
+ 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(
+ '--mongorestore_path', default='mongorestore',
+ help='mongorestore binary')
+ subparser.add_argument(
+ '--cache_path',
+ help='Temporary directory where files will be temporarily dumped')
+
+
+def _import_media(db, args):
+ """
+ Import media files
+
+ Must be called after _import_database()
+ """
+ print "\n== Importing media ==\n"
+
+ media_cache = BasicFileStorage(
+ args._cache_path['media'])
+
+ # TODO: Add import of queue files
+ queue_cache = BasicFileStorage(
+ args._cache_path['queue'])
+
+ for entry in db.media_entries.find():
+ for name, path in entry['media_files'].items():
+ media_file = mg_globals.public_store.get_file(path, mode='wb')
+ media_file.write(
+ media_cache.get_file(path, mode='rb').read())
+
+ print "\n== Media imported ==\n"
+
+
+def _import_database(db, args):
+ """
+ Restore mongo database from ___.bson files
+ """
+ print "\n== Importing database ==\n"
+
+ p = subprocess.Popen([
+ args.mongorestore_path,
+ '-d', db.name,
+ os.path.join(args._cache_path['database'], db.name)])
+
+ p.wait()
+
+ print "\n== Database imported ==\n"
+
+
+def env_import(args):
+ """
+ Restore mongo database and media files from a tar archive
+ """
+ if not args.cache_path:
+ args.cache_path = tempfile.mkdtemp()
+
+ setup_global_and_app_config(args.conf_file)
+
+ # Creates mg_globals.public_store and mg_globals.queue_store
+ setup_storage()
+
+ config, validation_result = read_mediagoblin_config(args.conf_file)
+ connection, db = setup_connection_and_db_from_config(
+ config['mediagoblin'], use_pymongo=True)
+
+ tf = tarfile.open(
+ args.tar_file,
+ mode='r|gz')
+
+ tf.extractall(args.cache_path)
+
+ args.cache_path = os.path.join(
+ args.cache_path, 'mediagoblin-data')
+ args = _setup_paths(args)
+
+ # Import database from extracted data
+ _import_database(db, args)
+
+ _import_media(db, args)
+
+ _clean(args)
+
+
+def _setup_paths(args):
+ """
+ Populate ``args`` variable with cache subpaths
+ """
+ args._cache_path = dict()
+ PATH_MAP = {
+ 'media': 'media',
+ 'queue': 'queue',
+ 'database': 'database'}
+
+ for key, val in PATH_MAP.items():
+ args._cache_path[key] = os.path.join(args.cache_path, val)
+
+ return args
+
+
+def _create_archive(args):
+ """
+ Create the tar archive
+ """
+ print "\n== Compressing to archive ==\n"
+
+ tf = tarfile.open(
+ args.tar_file,
+ mode='w|gz')
+
+ with closing(tf):
+ tf.add(args.cache_path, 'mediagoblin-data/')
+
+ print "\n== Archiving done ==\n"
+
+
+def _clean(args):
+ """
+ Remove cache directory
+ """
+ shutil.rmtree(args.cache_path)
+
+
+def _export_check(args):
+ """
+ Run security checks for export command
+ """
+ if os.path.exists(args.tar_file):
+ overwrite = raw_input(
+ 'The output file already exists. '
+ 'Are you **SURE** you want to overwrite it? '
+ '(yes/no)> ')
+ if not overwrite == 'yes':
+ print "Aborting."
+
+ return False
+
+ return True
+
+
+def _export_database(db, args):
+ print "\n== Exporting database ==\n"
+
+ command = '{mongodump_path} -d {database} -o {mongodump_cache}'.format(
+ mongodump_path=args.mongodump_path,
+ database=db.name,
+ mongodump_cache=args._cache_path['database'])
+
+ p = subprocess.Popen([
+ args.mongodump_path,
+ '-d', db.name,
+ '-o', args._cache_path['database']])
+
+ p.wait()
+
+ print "\n== Database exported ==\n"
+
+
+def _export_media(db, args):
+ print "\n== Exporting media ==\n"
+
+ media_cache = BasicFileStorage(
+ args._cache_path['media'])
+
+ # TODO: Add export of queue files
+ queue_cache = BasicFileStorage(
+ args._cache_path['queue'])
+
+ for entry in db.media_entries.find():
+ for name, path in entry['media_files'].items():
+ mc_file = media_cache.get_file(path, mode='wb')
+ mc_file.write(
+ mg_globals.public_store.get_file(path, mode='rb').read())
+
+ print "\n== Media exported ==\n"
+
+
+def env_export(args):
+ """
+ Export database and media files to a tar archive
+ """
+ if args.cache_path:
+ if os.path.exists(args.cache_path):
+ print 'The cache directory must not exist before you run this script'
+ print 'Cache directory: ', args.cache_path
+
+ return False
+ else:
+ args.cache_path = tempfile.mkdtemp()
+
+ args = _setup_paths(args)
+
+ if not _export_check(args):
+ print "\n== Checks did not pass, exiting ==\n"
+ sys.exit(0)
+
+ setup_global_and_app_config(args.conf_file)
+ setup_storage()
+
+ config, validation_result = read_mediagoblin_config(args.conf_file)
+ connection, db = setup_connection_and_db_from_config(
+ config['mediagoblin'], use_pymongo=True)
+
+ _export_database(db, args)
+
+ _export_media(db, args)
+
+ _create_archive(args)
+
+ _clean(args)
diff --git a/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.mo
new file mode 100644
index 00000000..aa0cd03b
--- /dev/null
+++ 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
new file mode 100644
index 00000000..201f2611
--- /dev/null
+++ b/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.po
@@ -0,0 +1,399 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+#
+# Majid Al-Dharrab <majid@aldharrab.com>, 2011.
+# <osamak@gnu.org>, 2011.
+# <Omar.w.kh@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-08-25 07:41-0500\n"
+"PO-Revision-Date: 2011-08-25 12:41+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: ar\n"
+"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5\n"
+
+#: mediagoblin/auth/forms.py:24 mediagoblin/auth/forms.py:46
+msgid "Username"
+msgstr "اسم المستخدم"
+
+#: mediagoblin/auth/forms.py:29 mediagoblin/auth/forms.py:50
+msgid "Password"
+msgstr "كلمة المرور"
+
+#: mediagoblin/auth/forms.py:34
+msgid "Passwords must match."
+msgstr "يجب أن تتطابق كلمتا المرور."
+
+#: mediagoblin/auth/forms.py:36
+msgid "Confirm password"
+msgstr "تأكيد كلمة المرور"
+
+#: mediagoblin/auth/forms.py:39
+msgid "Email address"
+msgstr "عنوان البريد الإلكتروني"
+
+#: mediagoblin/auth/views.py:40
+msgid "Sorry, registration is disabled on this instance."
+msgstr "عفوًا، التسجيل غير متاح هنا."
+
+#: mediagoblin/auth/views.py:57
+msgid "Sorry, a user with that name already exists."
+msgstr "عذرا، مستخدم بهذا الاسم موجود فعلا."
+
+#: mediagoblin/auth/views.py:61
+msgid "Sorry, that email address has already been taken."
+msgstr "عفوًا، هذا العنوان البريدي مستخدم."
+
+#: mediagoblin/auth/views.py:159
+msgid ""
+"Your email address has been verified. You may now login, edit your profile, "
+"and submit images!"
+msgstr ""
+"تم التحقق من بريدك الإلكتروني. يمكنك الآن الولوج، تحرير ملفك، وإرسال الصور!"
+
+#: mediagoblin/auth/views.py:165
+msgid "The verification key or user id is incorrect"
+msgstr "مفتاح التحقق أو معرف المستخدم خاطئ"
+
+#: mediagoblin/auth/views.py:186
+#: mediagoblin/templates/mediagoblin/auth/resent_verification_email.html:22
+msgid "Resent your verification email."
+msgstr "أعيد إرسال رسالة التحقق."
+
+#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+msgid "Title"
+msgstr "العنوان"
+
+#: mediagoblin/edit/forms.py:29
+msgid "Slug"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:30
+msgid "The slug can't be empty"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:31
+msgid "Tags"
+msgstr "الوسوم"
+
+#: mediagoblin/edit/forms.py:38
+msgid "Bio"
+msgstr "السيرة"
+
+#: mediagoblin/edit/forms.py:41
+msgid "Website"
+msgstr "الموقع الإلكتروني"
+
+#: mediagoblin/edit/views.py:65
+msgid "An entry with that slug already exists for this user."
+msgstr ""
+
+#: mediagoblin/edit/views.py:94
+msgid "You are editing another user's media. Proceed with caution."
+msgstr ""
+
+#: mediagoblin/edit/views.py:165
+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/views.py:47
+msgid "You must provide a file."
+msgstr ""
+
+#: mediagoblin/submit/views.py:50
+msgid "The file doesn't seem to be an image!"
+msgstr "لا يبدو أن هذا الملف صورة!"
+
+#: mediagoblin/submit/views.py:122
+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:26
+#: mediagoblin/templates/mediagoblin/auth/login.html:34
+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 project</a>"
+msgstr ""
+"مدعوم بواسطة <a href=\"http://mediagoblin.org\">ميدياغوبلن</a>، <a "
+"href=\"http://gnu.org/\">مشروع غنو</a>"
+
+#: 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/auth/login.html:29
+msgid "Logging in failed!"
+msgstr "فشل الولوج!"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:42
+msgid "Don't have an account yet?"
+msgstr "ألا تملك حسابا؟"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:45
+msgid "Create one here!"
+msgstr "أنشئ حسابا هنا!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:27
+msgid "Create an account!"
+msgstr "أنشئ حسابا!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:30
+msgid "Create"
+msgstr "أنشئ"
+
+#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19
+#, python-format
+msgid ""
+"Hi %(username)s,\n"
+"\n"
+"to activate your GNU MediaGoblin account, open the following URL in\n"
+"your web browser:\n"
+"\n"
+"%(verification_url)s"
+msgstr ""
+"أهلا %(username)s،\n"
+"\n"
+"لتفعيل حسابك في غنو ميدياغوبلن، افتح الرابط التالي\n"
+"في متصفحك:\n"
+"\n"
+"%(verification_url)s"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:29
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "تعديل %(media_title)s"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:36
+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 "تعديل ملف %(username)s"
+
+#: 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:29
+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 "وسائط <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 "عذرا، لا يوجد مستخدم مماثل"
+
+#: 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 ""
+"إن كنت أنت ذلك الشخص لكنك فقدت رسالة التحقق، يمكنك <a "
+"href=\"%(login_url)s\">الولوج</a> وإعادة إرسالها."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:78
+#, python-format
+msgid "%(username)s's profile"
+msgstr "ملف %(username)s'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 "اعرض كل وسائط %(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 "هنا ستظهر وسائطك، ولكن يبدو أنك لم تضف شيئًا بعد."
+
+#: 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/user_pages/forms.py:24
+msgid "Comment"
+msgstr ""
+
+
diff --git a/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.mo
new file mode 100644
index 00000000..47b24367
--- /dev/null
+++ 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
new file mode 100644
index 00000000..fa8a9b45
--- /dev/null
+++ b/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.po
@@ -0,0 +1,405 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+#
+# Rafael Maguiña <rafael.maguina@gmail.com>, 2011.
+# <benjamin@lebsanft.org>, 2011.
+# <mediagoblin.org@samba-tng.org>, 2011.
+# Elrond <elrond+mediagoblin.org@samba-tng.org>, 2011.
+# <cwebber@dustycloud.org>, 2011.
+# Jan-Christoph Borchardt <JanCBorchardt@fsfe.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-08-25 07:41-0500\n"
+"PO-Revision-Date: 2011-08-25 12:41+0000\n"
+"Last-Translator: cwebber <cwebber@dustycloud.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"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 0.9.6\n"
+"Language: de\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+
+#: mediagoblin/auth/forms.py:24 mediagoblin/auth/forms.py:46
+msgid "Username"
+msgstr "Benutzername"
+
+#: mediagoblin/auth/forms.py:29 mediagoblin/auth/forms.py:50
+msgid "Password"
+msgstr "Passwort"
+
+#: mediagoblin/auth/forms.py:34
+msgid "Passwords must match."
+msgstr "Passwörter müssen übereinstimmen."
+
+#: mediagoblin/auth/forms.py:36
+msgid "Confirm password"
+msgstr "Passwort wiederholen"
+
+#: mediagoblin/auth/forms.py:39
+msgid "Email address"
+msgstr "Email-Adresse"
+
+#: mediagoblin/auth/views.py:40
+msgid "Sorry, registration is disabled on this instance."
+msgstr "Registrierung ist auf dieser Instanz leider deaktiviert."
+
+#: mediagoblin/auth/views.py:57
+msgid "Sorry, a user with that name already exists."
+msgstr "Leider gibt es bereits einen Benutzer mit diesem Namen."
+
+#: mediagoblin/auth/views.py:61
+msgid "Sorry, that email address has already been taken."
+msgstr "Tut und Leid, aber diese E-Mail Adresse wird bereits verwendet."
+
+#: mediagoblin/auth/views.py:159
+msgid ""
+"Your email address has been verified. You may now login, edit your profile, "
+"and submit images!"
+msgstr ""
+"Deine Email-Adresse wurde bestätigt. Du kannst dich nun anmelden, Dein "
+"Profil bearbeiten und Bilder hochladen!"
+
+#: mediagoblin/auth/views.py:165
+msgid "The verification key or user id is incorrect"
+msgstr "Der Bestätigungssschlüssel oder die Nutzernummer ist falsch."
+
+#: mediagoblin/auth/views.py:186
+#: mediagoblin/templates/mediagoblin/auth/resent_verification_email.html:22
+msgid "Resent your verification email."
+msgstr "Bestätigungs-Email wurde erneut versand."
+
+#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+msgid "Title"
+msgstr "Titel"
+
+#: mediagoblin/edit/forms.py:29
+msgid "Slug"
+msgstr "Kurztitel"
+
+#: mediagoblin/edit/forms.py:30
+msgid "The slug can't be empty"
+msgstr "Bitte gib einen Kurztitel ein"
+
+#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:31
+msgid "Tags"
+msgstr "Markierungen"
+
+#: mediagoblin/edit/forms.py:38
+msgid "Bio"
+msgstr "Biographie"
+
+#: mediagoblin/edit/forms.py:41
+msgid "Website"
+msgstr "Webseite"
+
+#: mediagoblin/edit/views.py:65
+msgid "An entry with that slug already exists for this user."
+msgstr "Diesen Kurztitel hast du bereits vergeben."
+
+#: mediagoblin/edit/views.py:94
+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:165
+msgid "You are editing a user's profile. Proceed with caution."
+msgstr "Du bearbeitest das Profil eines Anderen. Bitte sei vorsichtig."
+
+#: mediagoblin/process_media/errors.py:44
+msgid "Invalid file given for media type."
+msgstr ""
+
+#: mediagoblin/submit/forms.py:25
+msgid "File"
+msgstr "Datei"
+
+#: mediagoblin/submit/views.py:47
+msgid "You must provide a file."
+msgstr "Du musst eine Datei angeben."
+
+#: mediagoblin/submit/views.py:50
+msgid "The file doesn't seem to be an image!"
+msgstr "Diese Datei scheint kein Bild zu sein!"
+
+#: mediagoblin/submit/views.py:122
+msgid "Woohoo! Submitted!"
+msgstr "Yeeeaaah! Geschafft!"
+
+#: 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 "GNU MediaGoblin"
+
+#: mediagoblin/templates/mediagoblin/base.html:47
+msgid "MediaGoblin logo"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/base.html:52
+msgid "Submit media"
+msgstr "Medien hochladen"
+
+#: mediagoblin/templates/mediagoblin/base.html:63
+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
+msgid "Log in"
+msgstr "Anmelden"
+
+#: mediagoblin/templates/mediagoblin/base.html:89
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
+"href=\"http://gnu.org/\">GNU project</a>"
+msgstr ""
+"Läuft mit <a href=\"http://mediagoblin.org\">MediaGoblin</a>, einem <a "
+"href=\"http://gnu.org/\">GNU-Projekt</a>"
+
+#: 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/auth/login.html:29
+msgid "Logging in failed!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:42
+msgid "Don't have an account yet?"
+msgstr "Hast du noch kein Konto?"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:45
+msgid "Create one here!"
+msgstr "Registriere dich!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:27
+msgid "Create an account!"
+msgstr "Neues Konto registrieren!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:30
+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 ""
+"Hi %(username)s,\n"
+"\n"
+"um dein Konto bei GNU MediaGoblin zu aktivieren, musst du folgende Adresse in einem Webbrowser öffnen:\n"
+"\n"
+"%(verification_url)s"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:29
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "%(media_title)s bearbeiten"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:36
+msgid "Cancel"
+msgstr "Abbrechen"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:37
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
+msgid "Save changes"
+msgstr "Änderungen speichern"
+
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:29
+#, python-format
+msgid "Editing %(username)s's profile"
+msgstr "%(username)ss Profil barbeiten"
+
+#: mediagoblin/templates/mediagoblin/listings/tag.html:31
+msgid "Media tagged with:"
+msgstr "Medien markiert mit:"
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:26
+msgid "Submit yer media"
+msgstr "Medien hochladen"
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:29
+msgid "Submit"
+msgstr "Bestätigen"
+
+#: 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 Medien"
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:32
+msgid "Sorry, no such user found."
+msgstr "Dieser Benutzer wurde leider nicht gefunden."
+
+#: 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 ""
+"Gleich solltest du eine Email bekommen, die dir sagt, was du noch machen "
+"musst."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:51
+msgid "In case it doesn't:"
+msgstr "Wenn sie nicht ankommt:"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:54
+msgid "Resend verification email"
+msgstr "Bestätigung erneut senden"
+
+#: 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 ""
+"Wenn dir dieses Konto gehört und die Bestätigungsmail verloren gegangen ist,"
+" kannst du dich <a href=\"%(login_url)s\">anmelden</a> und sie erneut "
+"senden."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:78
+#, python-format
+msgid "%(username)s's profile"
+msgstr "%(username)ss Profil"
+
+#: 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 "Profil bearbeiten"
+
+#: 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 "Alle Medien von %(username)s anschauen"
+
+#: 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/user_pages/forms.py:24
+msgid "Comment"
+msgstr "Kommentar"
+
+
diff --git a/mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po
new file mode 100644
index 00000000..3f5539c6
--- /dev/null
+++ b/mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po
@@ -0,0 +1,382 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PROJECT VERSION\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2011-08-25 07:41-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"
+"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"
+
+#: mediagoblin/auth/forms.py:24 mediagoblin/auth/forms.py:46
+msgid "Username"
+msgstr ""
+
+#: mediagoblin/auth/forms.py:29 mediagoblin/auth/forms.py:50
+msgid "Password"
+msgstr ""
+
+#: mediagoblin/auth/forms.py:34
+msgid "Passwords must match."
+msgstr ""
+
+#: mediagoblin/auth/forms.py:36
+msgid "Confirm password"
+msgstr ""
+
+#: mediagoblin/auth/forms.py:39
+msgid "Email address"
+msgstr ""
+
+#: mediagoblin/auth/views.py:40
+msgid "Sorry, registration is disabled on this instance."
+msgstr ""
+
+#: mediagoblin/auth/views.py:57
+msgid "Sorry, a user with that name already exists."
+msgstr ""
+
+#: mediagoblin/auth/views.py:61
+msgid "Sorry, that email address has already been taken."
+msgstr ""
+
+#: mediagoblin/auth/views.py:159
+msgid ""
+"Your email address has been verified. You may now login, edit your "
+"profile, and submit images!"
+msgstr ""
+
+#: mediagoblin/auth/views.py:165
+msgid "The verification key or user id is incorrect"
+msgstr ""
+
+#: mediagoblin/auth/views.py:186
+#: mediagoblin/templates/mediagoblin/auth/resent_verification_email.html:22
+msgid "Resent your verification email."
+msgstr ""
+
+#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+msgid "Title"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:29
+msgid "Slug"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:30
+msgid "The slug can't be empty"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:31
+msgid "Tags"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:38
+msgid "Bio"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:41
+msgid "Website"
+msgstr ""
+
+#: mediagoblin/edit/views.py:65
+msgid "An entry with that slug already exists for this user."
+msgstr ""
+
+#: mediagoblin/edit/views.py:94
+msgid "You are editing another user's media. Proceed with caution."
+msgstr ""
+
+#: mediagoblin/edit/views.py:165
+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/views.py:47
+msgid "You must provide a file."
+msgstr ""
+
+#: mediagoblin/submit/views.py:50
+msgid "The file doesn't seem to be an image!"
+msgstr ""
+
+#: mediagoblin/submit/views.py:122
+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:26
+#: mediagoblin/templates/mediagoblin/auth/login.html:34
+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 project</a>"
+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/auth/login.html:29
+msgid "Logging in failed!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:42
+msgid "Don't have an account yet?"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:45
+msgid "Create one here!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:27
+msgid "Create an account!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:30
+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
+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:29
+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/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/user_pages/forms.py:24
+msgid "Comment"
+msgstr ""
+
diff --git a/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.mo
new file mode 100644
index 00000000..72347f29
--- /dev/null
+++ 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
new file mode 100644
index 00000000..ab15f0af
--- /dev/null
+++ b/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.po
@@ -0,0 +1,402 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+#
+# <deletesoftware@yandex.ru>, 2011.
+# <john_w1954@fastmail.fm>, 2011.
+# Fernando Inocencio <faigos@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-08-25 07:41-0500\n"
+"PO-Revision-Date: 2011-08-25 12:41+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: eo\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+
+#: mediagoblin/auth/forms.py:24 mediagoblin/auth/forms.py:46
+msgid "Username"
+msgstr "Uzantnomo"
+
+#: mediagoblin/auth/forms.py:29 mediagoblin/auth/forms.py:50
+msgid "Password"
+msgstr "Pasvorto"
+
+#: mediagoblin/auth/forms.py:34
+msgid "Passwords must match."
+msgstr "Pasvortoj devas esti egalaj."
+
+#: mediagoblin/auth/forms.py:36
+msgid "Confirm password"
+msgstr "Retajpu pasvorton"
+
+#: mediagoblin/auth/forms.py:39
+msgid "Email address"
+msgstr "Retpoŝtadreso"
+
+#: mediagoblin/auth/views.py:40
+msgid "Sorry, registration is disabled on this instance."
+msgstr "Bedaŭrinde, registrado estas malaktivigita en tiu ĉi instalaĵo."
+
+#: mediagoblin/auth/views.py:57
+msgid "Sorry, a user with that name already exists."
+msgstr "Bedaŭrinde, uzanto kun tiu nomo jam ekzistas."
+
+#: mediagoblin/auth/views.py:61
+msgid "Sorry, that email address has already been taken."
+msgstr "Tiu retpoŝtadreso jam estas uzata."
+
+#: mediagoblin/auth/views.py:159
+msgid ""
+"Your email address has been verified. You may now login, edit your profile, "
+"and submit images!"
+msgstr ""
+"Via retpoŝtadreso estas konfirmita. Vi povas nun ensaluti, redakti vian "
+"profilon, kaj alŝuti bildojn!"
+
+#: mediagoblin/auth/views.py:165
+msgid "The verification key or user id is incorrect"
+msgstr "La kontrol-kodo aŭ la uzantonomo ne estas korekta"
+
+#: mediagoblin/auth/views.py:186
+#: mediagoblin/templates/mediagoblin/auth/resent_verification_email.html:22
+msgid "Resent your verification email."
+msgstr "Resendi vian kontrol-mesaĝon."
+
+#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+msgid "Title"
+msgstr "Titolo"
+
+#: mediagoblin/edit/forms.py:29
+msgid "Slug"
+msgstr "La distingiga adresparto"
+
+#: mediagoblin/edit/forms.py:30
+msgid "The slug can't be empty"
+msgstr "La distingiga adresparto ne povas esti malplena"
+
+#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:31
+msgid "Tags"
+msgstr "Etikedoj"
+
+#: mediagoblin/edit/forms.py:38
+msgid "Bio"
+msgstr "Bio"
+
+#: mediagoblin/edit/forms.py:41
+msgid "Website"
+msgstr "Retejo"
+
+#: mediagoblin/edit/views.py:65
+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:94
+msgid "You are editing another user's media. Proceed with caution."
+msgstr "Vi priredaktas dosieron de alia uzanto. Agu singardeme."
+
+#: mediagoblin/edit/views.py:165
+msgid "You are editing a user's profile. Proceed with caution."
+msgstr "Vi redaktas profilon de alia uzanto. Agu singardeme."
+
+#: mediagoblin/process_media/errors.py:44
+msgid "Invalid file given for media type."
+msgstr ""
+
+#: mediagoblin/submit/forms.py:25
+msgid "File"
+msgstr "Dosiero"
+
+#: mediagoblin/submit/views.py:47
+msgid "You must provide a file."
+msgstr "Vi devas provizi dosieron."
+
+#: mediagoblin/submit/views.py:50
+msgid "The file doesn't seem to be an image!"
+msgstr "La dosiero ŝajnas ne esti bildo!"
+
+#: mediagoblin/submit/views.py:122
+msgid "Woohoo! Submitted!"
+msgstr "Hura! Alŝutitas!"
+
+#: 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 ""
+"Se vi estas certa, ke la adreso estas ĝusta, eble la serĉata de vi paĝo "
+"estis movita aŭ forigita."
+
+#: 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 "Emblemo de MediaGoblin"
+
+#: mediagoblin/templates/mediagoblin/base.html:52
+msgid "Submit media"
+msgstr "Alŝuti aŭd-vid-dosieron"
+
+#: mediagoblin/templates/mediagoblin/base.html:63
+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
+msgid "Log in"
+msgstr "Ensaluti"
+
+#: mediagoblin/templates/mediagoblin/base.html:89
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
+"href=\"http://gnu.org/\">GNU project</a>"
+msgstr ""
+"Funkcias per <a href=\"http://mediagoblin.org\">MediaGoblin</a>, unu el la "
+"<a href=\"http://gnu.org/\">projektoj de GNU</a>"
+
+#: mediagoblin/templates/mediagoblin/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 "La perfekta loko por viaj aŭd-vid-dosieroj!"
+
+#: 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/auth/login.html:29
+msgid "Logging in failed!"
+msgstr "Ensaluto malsukcesis!"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:42
+msgid "Don't have an account yet?"
+msgstr "Ĉu ankoraŭ sen konto?"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:45
+msgid "Create one here!"
+msgstr "Kreu ĝin ĉi tie!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:27
+msgid "Create an account!"
+msgstr "Kreu konton!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:30
+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 ""
+"Sal %(username)s,\n"
+"\n"
+"por aktivigi vian GNU MediaGoblin konton, malfermu la sekvantan URLon en via retumilo:\n"
+"\n"
+"%(verification_url)s"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:29
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "Priredaktado de %(media_title)s"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:36
+msgid "Cancel"
+msgstr "Nuligi"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:37
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
+msgid "Save changes"
+msgstr "Konservi ŝanĝojn"
+
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:29
+#, python-format
+msgid "Editing %(username)s's profile"
+msgstr "Redaktado de l’profilo de %(username)s'"
+
+#: mediagoblin/templates/mediagoblin/listings/tag.html:31
+msgid "Media tagged with:"
+msgstr "Dosieroj markitaj per:"
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:26
+msgid "Submit yer media"
+msgstr "Alŝutu vian aŭd-vid-dosieron"
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:29
+msgid "Submit"
+msgstr "Alŝuti"
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media"
+msgstr "Dosieroj 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 "Uzanto ne trovita."
+
+#: 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 ""
+"Post kelkaj momentoj devas veni retletero kun instrukcio pri kiel tion fari."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:51
+msgid "In case it doesn't:"
+msgstr "Se tio ne okazas:"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:54
+msgid "Resend verification email"
+msgstr "Resendi kontrolmesaĝon"
+
+#: 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 ""
+"Se vi estas tiu sed vi perdis vian kontrolmesaĝon, vi povas <a "
+"href=\"%(login_url)s\">ensaluti</a> kaj resendi ĝin."
+
+#: 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 "Redakti profilon"
+
+#: 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 "Rigardi ĉiujn dosierojn 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 ""
+
+#: 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/user_pages/forms.py:24
+msgid "Comment"
+msgstr "Komento"
+
+
diff --git a/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.mo
new file mode 100644
index 00000000..f107ac62
--- /dev/null
+++ 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
new file mode 100644
index 00000000..d8627710
--- /dev/null
+++ b/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.po
@@ -0,0 +1,416 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+#
+# <ekenbrand@hotmail.com>, 2011.
+# <juangsub@gmail.com>, 2011.
+# <jacobo@gnu.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-08-25 07:41-0500\n"
+"PO-Revision-Date: 2011-08-25 12:41+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"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 0.9.6\n"
+"Language: es\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+
+#: mediagoblin/auth/forms.py:24 mediagoblin/auth/forms.py:46
+msgid "Username"
+msgstr "Nombre de Usuario"
+
+#: mediagoblin/auth/forms.py:29 mediagoblin/auth/forms.py:50
+msgid "Password"
+msgstr "Contraseña"
+
+#: mediagoblin/auth/forms.py:34
+msgid "Passwords must match."
+msgstr "Las contraseñas deben coincidir."
+
+#: mediagoblin/auth/forms.py:36
+msgid "Confirm password"
+msgstr "Confirme su contraseña"
+
+#: mediagoblin/auth/forms.py:39
+msgid "Email address"
+msgstr "Dirección de correo electrónico"
+
+#: mediagoblin/auth/views.py:40
+msgid "Sorry, registration is disabled on this instance."
+msgstr "Lo sentimos, la registración está deshabilitado en este momento."
+
+#: mediagoblin/auth/views.py:57
+msgid "Sorry, a user with that name already exists."
+msgstr "Lo sentimos, ya existe un usuario con ese nombre."
+
+#: mediagoblin/auth/views.py:61
+msgid "Sorry, that email address has already been taken."
+msgstr "Lo sentimos, su dirección de correo electrónico ya ha sido tomada."
+
+#: mediagoblin/auth/views.py:159
+msgid ""
+"Your email address has been verified. You may now login, edit your profile, "
+"and submit images!"
+msgstr ""
+"Su dirección de correo electrónico ha sido verificada. ¡Ahora puede "
+"ingresar, editar su perfil, y enviar imágenes!"
+
+#: mediagoblin/auth/views.py:165
+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:186
+#: mediagoblin/templates/mediagoblin/auth/resent_verification_email.html:22
+msgid "Resent your verification email."
+msgstr "Reenvíe su correo electrónico de verificación."
+
+#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+msgid "Title"
+msgstr "Título"
+
+#: mediagoblin/edit/forms.py:29
+msgid "Slug"
+msgstr "Ficha"
+
+#: mediagoblin/edit/forms.py:30
+msgid "The slug can't be empty"
+msgstr "La ficha no puede estar vacía"
+
+#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:31
+msgid "Tags"
+msgstr "Etiquetas"
+
+#: mediagoblin/edit/forms.py:38
+msgid "Bio"
+msgstr "Bio"
+
+#: mediagoblin/edit/forms.py:41
+msgid "Website"
+msgstr "Sitio web"
+
+#: mediagoblin/edit/views.py:65
+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:94
+msgid "You are editing another user's media. Proceed with caution."
+msgstr ""
+"Usted está editando el contenido de otro usuario. Proceder con precaución."
+
+#: mediagoblin/edit/views.py:165
+msgid "You are editing a user's profile. Proceed with caution."
+msgstr "Usted está editando un perfil de usuario. Proceder con precaución."
+
+#: mediagoblin/process_media/errors.py:44
+msgid "Invalid file given for media type."
+msgstr "Archivo inálido para el formato seleccionado."
+
+#: mediagoblin/submit/forms.py:25
+msgid "File"
+msgstr "Archivo"
+
+#: mediagoblin/submit/views.py:47
+msgid "You must provide a file."
+msgstr "Usted debe proporcionar un archivo."
+
+#: mediagoblin/submit/views.py:50
+msgid "The file doesn't seem to be an image!"
+msgstr "¡El archivo no parece ser una imagen!"
+
+#: mediagoblin/submit/views.py:122
+msgid "Woohoo! Submitted!"
+msgstr "¡Woohoo! ¡Enviado!"
+
+#: 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 "Parece no haber una página en esta dirección. ¡Lo siento!"
+
+#: 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 estas seguro que la dirección es correcta, puede ser que la pagina halla "
+"sido movida o borrada."
+
+#: mediagoblin/templates/mediagoblin/404.html:32
+msgid "Image of 404 goblin stressing out"
+msgstr "404 el goblin esta estresado"
+
+#: 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 "Enviar contenido"
+
+#: mediagoblin/templates/mediagoblin/base.html:63
+msgid "verify your email!"
+msgstr "Verifique su correo electrónico"
+
+#: mediagoblin/templates/mediagoblin/base.html:73
+#: mediagoblin/templates/mediagoblin/auth/login.html:26
+#: mediagoblin/templates/mediagoblin/auth/login.html:34
+msgid "Log in"
+msgstr "Conectarse"
+
+#: mediagoblin/templates/mediagoblin/base.html:89
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
+"href=\"http://gnu.org/\">GNU project</a>"
+msgstr ""
+"Potenciado por <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
+"href=\"http://gnu.org/\">GNU project</a>"
+
+#: mediagoblin/templates/mediagoblin/root.html:27
+msgid "Hi there, media lover! MediaGoblin is..."
+msgstr "Hola, amante de los medios de comunicación! MediaGoblin es ..."
+
+#: mediagoblin/templates/mediagoblin/root.html:29
+msgid "The perfect place for your media!"
+msgstr "El lugar ideal para tus cosas!"
+
+#: 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"
+
+#: 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 ""
+"Queriendo hacer del mundo un mejor lugar a través de la descentralización y "
+"(eventualmente!) la federalización!"
+
+#: mediagoblin/templates/mediagoblin/root.html:33
+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!)"
+
+#: 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 ""
+"Impulsado por gente como vos. (<a "
+"href=\"http://mediagoblin.org/pages/join.html\"> Vos podés ayudarnos a "
+"mejorar este programa</a>)"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:29
+msgid "Logging in failed!"
+msgstr "Fallo el inicio de sesión!"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:42
+msgid "Don't have an account yet?"
+msgstr "¿No tienes una cuenta?"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:45
+msgid "Create one here!"
+msgstr "¡Crea una aquí!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:27
+msgid "Create an account!"
+msgstr "¡Crea una cuenta!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:30
+msgid "Create"
+msgstr "Crear"
+
+#: 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 ""
+"Hola %(username)s , para activar su cuenta GNU MediaGoblin, abra la "
+"siguiente URL en su navegador: %(verification_url)s "
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:29
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "Edición %(media_title)s "
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:36
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:37
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
+msgid "Save changes"
+msgstr "Salvar cambios"
+
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:29
+#, python-format
+msgid "Editing %(username)s's profile"
+msgstr "Editando el perfil de %(username)s"
+
+#: mediagoblin/templates/mediagoblin/listings/tag.html:31
+msgid "Media tagged with:"
+msgstr "Contenido etiquetado con:"
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:26
+msgid "Submit yer media"
+msgstr "Envíe su contenido"
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:29
+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 "Contenido de <a href=\"%(user_url)s\">%(username)s</a>'s"
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:32
+msgid "Sorry, no such user found."
+msgstr "Lo sentimos, no se ha encontrado ese usuario."
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:22
+msgid "Media processing panel"
+msgstr "Panel de procesamiento de contenido"
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:25
+msgid ""
+"You can track the state of media being processed for your gallery here."
+msgstr ""
+"Puedes hacer un seguimiento del estado de tu contenido siendo procesado "
+"aquí."
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:28
+msgid "Media in-processing"
+msgstr "Contenido siendo procesado"
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:46
+msgid "No media in-processing"
+msgstr "No hay contenido siendo procesado."
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:50
+msgid "These uploads failed to process:"
+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"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:42
+msgid "Almost done! Your account still needs to be activated."
+msgstr "Casi terminas! Solo falta activar la cuenta."
+
+#: 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 ""
+"Un e-mail debería llegar en unos momentos con las instrucciones para "
+"hacerlo."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:51
+msgid "In case it doesn't:"
+msgstr "En caso de que no:"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:54
+msgid "Resend verification email"
+msgstr "Reenviar correo electrónico de verificación"
+
+#: 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 ""
+"Alguien ya registró una cuenta con ese nombre de usuario, pero todavía no "
+"fué activada."
+
+#: 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 usted es esa persona, pero ha perdido su correo electrónico de "
+"verificación, puede <a href=\"%(login_url)s\">acceder</a> y reenviarlo."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:78
+#, python-format
+msgid "%(username)s's profile"
+msgstr "Perfil de %(username)s'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í"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:90
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:108
+msgid "Edit profile"
+msgstr "Editar perfil"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:96
+msgid "This user hasn't filled in their profile (yet)."
+msgstr "Este usuario (todavia) no ha completado su perfil."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:122
+#, python-format
+msgid "View all of %(username)s's media"
+msgstr "Ver todo el contenido de %(username)s'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 ""
+"Aquí es donde tú contenido estará, pero parece que no haz agregado contenido"
+" todavia."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:141
+msgid "Add media"
+msgstr "Añadir contenido"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:147
+msgid "There doesn't seem to be any media here yet..."
+msgstr "Parece que no hay ningún contenido aquí todavia..."
+
+#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
+msgid "feed icon"
+msgstr "ícono feed"
+
+#: mediagoblin/templates/mediagoblin/utils/feed_link.html:23
+msgid "Atom feed"
+msgstr "Atom feed"
+
+#: mediagoblin/user_pages/forms.py:24
+msgid "Comment"
+msgstr "Comentario"
+
+
diff --git a/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.mo
new file mode 100644
index 00000000..871d2a42
--- /dev/null
+++ 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
new file mode 100644
index 00000000..91da5fc7
--- /dev/null
+++ b/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.po
@@ -0,0 +1,407 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+#
+# <maxineb@members.fsf.org>, 2011.
+# <marktraceur@gmail.com>, 2011.
+# Valentin Villenave <valentin@villenave.net>, 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-08-25 07:41-0500\n"
+"PO-Revision-Date: 2011-08-25 12:41+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: fr\n"
+"Plural-Forms: nplurals=2; plural=(n > 1)\n"
+
+#: mediagoblin/auth/forms.py:24 mediagoblin/auth/forms.py:46
+msgid "Username"
+msgstr "Nom d'utilisateur"
+
+#: mediagoblin/auth/forms.py:29 mediagoblin/auth/forms.py:50
+msgid "Password"
+msgstr "Mot de passe"
+
+#: mediagoblin/auth/forms.py:34
+msgid "Passwords must match."
+msgstr "Les mots de passe doivent correspondre."
+
+#: mediagoblin/auth/forms.py:36
+msgid "Confirm password"
+msgstr "Confirmer le mot de passe"
+
+#: mediagoblin/auth/forms.py:39
+msgid "Email address"
+msgstr "Adresse e-mail"
+
+#: mediagoblin/auth/views.py:40
+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:57
+msgid "Sorry, a user with that name already exists."
+msgstr "Un utilisateur existe déjà avec ce nom, désolé."
+
+#: mediagoblin/auth/views.py:61
+msgid "Sorry, that email address has already been taken."
+msgstr "Désolé, cette adresse courriel a déjà été prise."
+
+#: mediagoblin/auth/views.py:159
+msgid ""
+"Your email address has been verified. You may now login, edit your profile, "
+"and submit images!"
+msgstr ""
+"Votre adresse e-mail a bien été vérifiée. Vous pouvez maintenant vous "
+"identifier, modifier votre profil, et soumettre des images !"
+
+#: mediagoblin/auth/views.py:165
+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:186
+#: mediagoblin/templates/mediagoblin/auth/resent_verification_email.html:22
+msgid "Resent your verification email."
+msgstr "E-mail de vérification renvoyé."
+
+#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+msgid "Title"
+msgstr "Titre"
+
+#: mediagoblin/edit/forms.py:29
+msgid "Slug"
+msgstr "Légende"
+
+#: mediagoblin/edit/forms.py:30
+msgid "The slug can't be empty"
+msgstr "La légende ne peut pas être laissée vide."
+
+#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:31
+msgid "Tags"
+msgstr "Tags"
+
+#: mediagoblin/edit/forms.py:38
+msgid "Bio"
+msgstr "Bio"
+
+#: mediagoblin/edit/forms.py:41
+msgid "Website"
+msgstr "Site web"
+
+#: mediagoblin/edit/views.py:65
+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:94
+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:165
+msgid "You are editing a user's profile. Proceed with caution."
+msgstr ""
+"Vous vous apprêtez à modifier le profil d'un utilisateur. Veuillez prendre "
+"garde."
+
+#: mediagoblin/process_media/errors.py:44
+msgid "Invalid file given for media type."
+msgstr ""
+
+#: mediagoblin/submit/forms.py:25
+msgid "File"
+msgstr "Fichier"
+
+#: mediagoblin/submit/views.py:47
+msgid "You must provide a file."
+msgstr "Il vous faut fournir un fichier."
+
+#: mediagoblin/submit/views.py:50
+msgid "The file doesn't seem to be an image!"
+msgstr "Ce fichier ne semble pas être une image !"
+
+#: mediagoblin/submit/views.py:122
+msgid "Woohoo! Submitted!"
+msgstr "Youhou, c'est envoyé !"
+
+#: 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 "GNU MediaGoblin"
+
+#: mediagoblin/templates/mediagoblin/base.html:47
+msgid "MediaGoblin logo"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/base.html:52
+msgid "Submit media"
+msgstr "Soumettre un média"
+
+#: mediagoblin/templates/mediagoblin/base.html:63
+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
+msgid "Log in"
+msgstr "S'identifier"
+
+#: mediagoblin/templates/mediagoblin/base.html:89
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
+"href=\"http://gnu.org/\">GNU project</a>"
+msgstr ""
+"Propulsé par <a href=\"http://mediagoblin.org\">MediaGoblin</a>, un projet "
+"de <a href=\"http://gnu.org/\">GNU</a>"
+
+#: 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/auth/login.html:29
+msgid "Logging in failed!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:42
+msgid "Don't have an account yet?"
+msgstr "Pas encore de compte ?"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:45
+msgid "Create one here!"
+msgstr "Créez-en un ici !"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:27
+msgid "Create an account!"
+msgstr "Créer un compte !"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:30
+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 ""
+"Bonjour %(username)s,\n"
+"\n"
+"pour activer votre compte sur GNU MediaGoblin, veuillez vous rendre à l'adresse suivante avec votre navigateur web:\n"
+"\n"
+"%(verification_url)s"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:29
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "Modification de %(media_title)s"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:36
+msgid "Cancel"
+msgstr "Annuler"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:37
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
+msgid "Save changes"
+msgstr "Enregistrer les modifications"
+
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:29
+#, python-format
+msgid "Editing %(username)s's profile"
+msgstr "Modification du profil de %(username)s"
+
+#: mediagoblin/templates/mediagoblin/listings/tag.html:31
+msgid "Media tagged with:"
+msgstr "Média comportant les tags suivants :"
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:26
+msgid "Submit yer media"
+msgstr "Soumettez ce média"
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:29
+msgid "Submit"
+msgstr "Soumettre"
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media"
+msgstr "Médias 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 "Impossible de trouver cet utilisateur, désolé."
+
+#: 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 ""
+"Un e-mail devrait vous parvenir dans quelques instants ; il vous indiquera "
+"comment procéder."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:51
+msgid "In case it doesn't:"
+msgstr "Si la vérification n'est pas arrivée à bon port :"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:54
+msgid "Resend verification email"
+msgstr "Renvoyer l'e-mail de vérification"
+
+#: 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 c'est de vous qu'il s'agit, mais que vous avez perdu l'e-mail de "
+"vérification, vous pouvez vous <a href=\"%(login_url)s\">identifier</a> et "
+"le renvoyer."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:78
+#, python-format
+msgid "%(username)s's profile"
+msgstr "profil 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 "Modifier le profil"
+
+#: 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 "Voir tous les 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 ""
+
+#: 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/user_pages/forms.py:24
+msgid "Comment"
+msgstr "Commentaire"
+
+
diff --git a/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.mo
new file mode 100644
index 00000000..0e0e240d
--- /dev/null
+++ 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
new file mode 100644
index 00000000..611bae32
--- /dev/null
+++ b/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.po
@@ -0,0 +1,393 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+#
+# <averym@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-08-25 07:41-0500\n"
+"PO-Revision-Date: 2011-08-25 12:41+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: ja\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+
+#: mediagoblin/auth/forms.py:24 mediagoblin/auth/forms.py:46
+msgid "Username"
+msgstr "ユーザネーム"
+
+#: mediagoblin/auth/forms.py:29 mediagoblin/auth/forms.py:50
+msgid "Password"
+msgstr "パスワード"
+
+#: mediagoblin/auth/forms.py:34
+msgid "Passwords must match."
+msgstr "パスワードが一致している必要があります。"
+
+#: mediagoblin/auth/forms.py:36
+msgid "Confirm password"
+msgstr "パスワードを確認"
+
+#: mediagoblin/auth/forms.py:39
+msgid "Email address"
+msgstr "メールアドレス"
+
+#: mediagoblin/auth/views.py:40
+msgid "Sorry, registration is disabled on this instance."
+msgstr "申し訳ありませんが、このインスタンスで登録は無効になっています。"
+
+#: mediagoblin/auth/views.py:57
+msgid "Sorry, a user with that name already exists."
+msgstr "申し訳ありませんが、その名前を持つユーザーがすでに存在しています。"
+
+#: mediagoblin/auth/views.py:61
+msgid "Sorry, that email address has already been taken."
+msgstr ""
+
+#: mediagoblin/auth/views.py:159
+msgid ""
+"Your email address has been verified. You may now login, edit your profile, "
+"and submit images!"
+msgstr "メアドが確認されています。これで、ログインしてプロファイルを編集し、画像を提出することができます!"
+
+#: mediagoblin/auth/views.py:165
+msgid "The verification key or user id is incorrect"
+msgstr "検証キーまたはユーザーIDが間違っています"
+
+#: mediagoblin/auth/views.py:186
+#: mediagoblin/templates/mediagoblin/auth/resent_verification_email.html:22
+msgid "Resent your verification email."
+msgstr "検証メールを再送しました。"
+
+#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+msgid "Title"
+msgstr "タイトル"
+
+#: mediagoblin/edit/forms.py:29
+msgid "Slug"
+msgstr "スラグ"
+
+#: mediagoblin/edit/forms.py:30
+msgid "The slug can't be empty"
+msgstr "スラグは必要です。"
+
+#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:31
+msgid "Tags"
+msgstr "タグ"
+
+#: mediagoblin/edit/forms.py:38
+msgid "Bio"
+msgstr "自己紹介"
+
+#: mediagoblin/edit/forms.py:41
+msgid "Website"
+msgstr "URL"
+
+#: mediagoblin/edit/views.py:65
+msgid "An entry with that slug already exists for this user."
+msgstr "そのスラグを持つエントリは、このユーザーは既に存在します。"
+
+#: mediagoblin/edit/views.py:94
+msgid "You are editing another user's media. Proceed with caution."
+msgstr "あなたは、他のユーザーのメディアを編集しています。ご注意ください。"
+
+#: mediagoblin/edit/views.py:165
+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/views.py:47
+msgid "You must provide a file."
+msgstr "ファイルを提供する必要があります。"
+
+#: mediagoblin/submit/views.py:50
+msgid "The file doesn't seem to be an image!"
+msgstr "ファイルが画像ではないようです!"
+
+#: mediagoblin/submit/views.py:122
+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 "GNU MediaGoblin"
+
+#: 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:26
+#: mediagoblin/templates/mediagoblin/auth/login.html:34
+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 project</a>"
+msgstr ""
+"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
+"href=\"http://gnu.org/\">GNU project</a>"
+
+#: 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/auth/login.html:29
+msgid "Logging in failed!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:42
+msgid "Don't have an account yet?"
+msgstr "まだアカウントを持っていませんか?"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:45
+msgid "Create one here!"
+msgstr "ここで作成!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:27
+msgid "Create an account!"
+msgstr "アカウントを作成!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:30
+msgid "Create"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19
+#, python-format
+msgid ""
+"Hi %(username)s,\n"
+"\n"
+"to activate your GNU MediaGoblin account, open the following URL in\n"
+"your web browser:\n"
+"\n"
+"%(verification_url)s"
+msgstr ""
+"%(username)s様へ\n"
+"\n"
+"GNU MediaGoblinアカウントを検証にするには、このURLを開いてください。\n"
+"\n"
+"%(verification_url)s"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:29
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "%(media_title)sを編集中"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:36
+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 "%(username)sさんのプロフィールを編集中"
+
+#: 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:29
+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 "<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 "申し訳ありませんが、そのユーザーは見つかりませんでした。"
+
+#: 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 "あなたの確認メールを紛失した場合、<a href=\"%(login_url)s\">ログイン</a>して再送できます。"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:78
+#, python-format
+msgid "%(username)s's profile"
+msgstr "%(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 "%(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 ""
+
+#: 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/user_pages/forms.py:24
+msgid "Comment"
+msgstr ""
+
+
diff --git a/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.mo
new file mode 100644
index 00000000..931d51b9
--- /dev/null
+++ 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
new file mode 100644
index 00000000..1a8fb631
--- /dev/null
+++ b/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.po
@@ -0,0 +1,399 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+#
+# <mail@jefvanschendel.nl>, 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-08-25 07:41-0500\n"
+"PO-Revision-Date: 2011-08-25 12:41+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: nl\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+
+#: mediagoblin/auth/forms.py:24 mediagoblin/auth/forms.py:46
+msgid "Username"
+msgstr "Gebruikersnaam"
+
+#: mediagoblin/auth/forms.py:29 mediagoblin/auth/forms.py:50
+msgid "Password"
+msgstr "Wachtwoord"
+
+#: mediagoblin/auth/forms.py:34
+msgid "Passwords must match."
+msgstr "Wachtwoorden moeten overeenkomen."
+
+#: mediagoblin/auth/forms.py:36
+msgid "Confirm password"
+msgstr "Bevestig wachtwoord"
+
+#: mediagoblin/auth/forms.py:39
+msgid "Email address"
+msgstr "E-mail adres"
+
+#: mediagoblin/auth/views.py:40
+msgid "Sorry, registration is disabled on this instance."
+msgstr "Sorry, registratie is uitgeschakeld op deze instantie."
+
+#: mediagoblin/auth/views.py:57
+msgid "Sorry, a user with that name already exists."
+msgstr "Sorry, er bestaat al een gebruiker met die naam."
+
+#: mediagoblin/auth/views.py:61
+msgid "Sorry, that email address has already been taken."
+msgstr "Sorry, dat e-mailadres is al ingenomen."
+
+#: mediagoblin/auth/views.py:159
+msgid ""
+"Your email address has been verified. You may now login, edit your profile, "
+"and submit images!"
+msgstr ""
+"Uw e-mailadres is geverifieerd. U kunt nu inloggen, uw profiel bewerken, en "
+"afbeeldingen toevoegen!"
+
+#: mediagoblin/auth/views.py:165
+msgid "The verification key or user id is incorrect"
+msgstr "De verificatie sleutel of gebruikers-ID is onjuist"
+
+#: mediagoblin/auth/views.py:186
+#: mediagoblin/templates/mediagoblin/auth/resent_verification_email.html:22
+msgid "Resent your verification email."
+msgstr "Verificatie e-mail opnieuw opgestuurd."
+
+#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+msgid "Title"
+msgstr "Titel"
+
+#: mediagoblin/edit/forms.py:29
+msgid "Slug"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:30
+msgid "The slug can't be empty"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:31
+msgid "Tags"
+msgstr "Etiket"
+
+#: mediagoblin/edit/forms.py:38
+msgid "Bio"
+msgstr "Bio"
+
+#: mediagoblin/edit/forms.py:41
+msgid "Website"
+msgstr "Website"
+
+#: mediagoblin/edit/views.py:65
+msgid "An entry with that slug already exists for this user."
+msgstr ""
+
+#: mediagoblin/edit/views.py:94
+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:165
+msgid "You are editing a user's profile. Proceed with caution."
+msgstr ""
+"U bent een gebruikersprofiel aan het aanpassen. Ga voorzichtig te werk."
+
+#: mediagoblin/process_media/errors.py:44
+msgid "Invalid file given for media type."
+msgstr ""
+
+#: mediagoblin/submit/forms.py:25
+msgid "File"
+msgstr "Bestand"
+
+#: mediagoblin/submit/views.py:47
+msgid "You must provide a file."
+msgstr "U moet een bestand aangeven."
+
+#: mediagoblin/submit/views.py:50
+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
+msgid "Woohoo! Submitted!"
+msgstr "Mooizo! Toegevoegd!"
+
+#: 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 "GNU MediaGoblin"
+
+#: mediagoblin/templates/mediagoblin/base.html:47
+msgid "MediaGoblin logo"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/base.html:52
+msgid "Submit media"
+msgstr "Voeg media toe"
+
+#: mediagoblin/templates/mediagoblin/base.html:63
+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
+msgid "Log in"
+msgstr "Inloggen"
+
+#: mediagoblin/templates/mediagoblin/base.html:89
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
+"href=\"http://gnu.org/\">GNU project</a>"
+msgstr ""
+"Aangedreven door <a href=\"http://mediagoblin.org\">MediaGoblin</a> , een <a"
+" href=\"http://gnu.org/\">GNU-project</a>"
+
+#: 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/auth/login.html:29
+msgid "Logging in failed!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:42
+msgid "Don't have an account yet?"
+msgstr "Heeft u nog geen account?"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:45
+msgid "Create one here!"
+msgstr "Maak er hier een!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:27
+msgid "Create an account!"
+msgstr "Maak een account aan!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:30
+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 ""
+"Hallo %(username)s , open de volgende URL in uw webbrowser om uw GNU "
+"MediaGoblin account te activeren: %(verification_url)s "
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:29
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "%(media_title)s aanpassen"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:36
+msgid "Cancel"
+msgstr "Annuleren"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:37
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
+msgid "Save changes"
+msgstr "Wijzigingen opslaan"
+
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:29
+#, python-format
+msgid "Editing %(username)s's profile"
+msgstr "Het profiel aanpassen van %(username)s"
+
+#: mediagoblin/templates/mediagoblin/listings/tag.html:31
+msgid "Media tagged with:"
+msgstr "Media met het etiket:"
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:26
+msgid "Submit yer media"
+msgstr "Voeg media toe"
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:29
+msgid "Submit"
+msgstr "Voeg toe"
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media"
+msgstr "Media van <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 "Sorry, die gebruiker kon niet worden gevonden."
+
+#: 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 ""
+"Een e-mail zou in een paar ogenblikken aan moeten komen met instructies "
+"hiertoe."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:51
+msgid "In case it doesn't:"
+msgstr "Zoniet:"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:54
+msgid "Resend verification email"
+msgstr "Stuur de verificatie e-mail opnieuw op."
+
+#: 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 ""
+"Als u die persoon bent, maar de verificatie e-mail verloren hebt, kunt u <a "
+"href=\"%(login_url)s\">inloggen</a> en hem nogmaals verzenden."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:78
+#, python-format
+msgid "%(username)s's profile"
+msgstr "Profiel van %(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 "Profiel aanpassen."
+
+#: 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 "Bekijk alle media van %(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 ""
+
+#: 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/user_pages/forms.py:24
+msgid "Comment"
+msgstr "Commentaar"
+
+
diff --git a/mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.mo
new file mode 100644
index 00000000..8bdb4a92
--- /dev/null
+++ 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
new file mode 100644
index 00000000..f4c97b12
--- /dev/null
+++ b/mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.po
@@ -0,0 +1,397 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+#
+# <odin.omdal@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-08-25 07:41-0500\n"
+"PO-Revision-Date: 2011-08-25 12:41+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: nn_NO\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+
+#: mediagoblin/auth/forms.py:24 mediagoblin/auth/forms.py:46
+msgid "Username"
+msgstr "Brukarnamn"
+
+#: mediagoblin/auth/forms.py:29 mediagoblin/auth/forms.py:50
+msgid "Password"
+msgstr "Passord"
+
+#: mediagoblin/auth/forms.py:34
+msgid "Passwords must match."
+msgstr "Passorda må vera like."
+
+#: mediagoblin/auth/forms.py:36
+msgid "Confirm password"
+msgstr "Gjenta passord"
+
+#: mediagoblin/auth/forms.py:39
+msgid "Email address"
+msgstr "E-postadresse"
+
+#: mediagoblin/auth/views.py:40
+msgid "Sorry, registration is disabled on this instance."
+msgstr "Registrering er slege av. Orsak."
+
+#: mediagoblin/auth/views.py:57
+msgid "Sorry, a user with that name already exists."
+msgstr "Ein konto med dette brukarnamnet finst allereide."
+
+#: mediagoblin/auth/views.py:61
+msgid "Sorry, that email address has already been taken."
+msgstr ""
+
+#: mediagoblin/auth/views.py:159
+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."
+
+#: mediagoblin/auth/views.py:165
+msgid "The verification key or user id is incorrect"
+msgstr "Stadfestingsnykelen eller brukar-ID-en din er feil."
+
+#: mediagoblin/auth/views.py:186
+#: mediagoblin/templates/mediagoblin/auth/resent_verification_email.html:22
+msgid "Resent your verification email."
+msgstr "Send ein ny stadfestingsepost."
+
+#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+msgid "Title"
+msgstr "Tittel"
+
+#: mediagoblin/edit/forms.py:29
+msgid "Slug"
+msgstr "Adressetittel"
+
+#: mediagoblin/edit/forms.py:30
+msgid "The slug can't be empty"
+msgstr "Adressetittelen kan ikkje vera tom"
+
+#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:31
+msgid "Tags"
+msgstr "Merkelappar"
+
+#: mediagoblin/edit/forms.py:38
+msgid "Bio"
+msgstr "Presentasjon"
+
+#: mediagoblin/edit/forms.py:41
+msgid "Website"
+msgstr "Heimeside"
+
+#: mediagoblin/edit/views.py:65
+msgid "An entry with that slug already exists for this user."
+msgstr "Eit innlegg med denne adressetittelen finst allereie."
+
+#: mediagoblin/edit/views.py:94
+msgid "You are editing another user's media. Proceed with caution."
+msgstr "Ver forsiktig, du redigerer ein annan konto sitt innlegg."
+
+#: mediagoblin/edit/views.py:165
+msgid "You are editing a user's profile. Proceed with caution."
+msgstr "Ver forsiktig, du redigerer ein annan konto sin profil."
+
+#: mediagoblin/process_media/errors.py:44
+msgid "Invalid file given for media type."
+msgstr ""
+
+#: mediagoblin/submit/forms.py:25
+msgid "File"
+msgstr "Fil"
+
+#: mediagoblin/submit/views.py:47
+msgid "You must provide a file."
+msgstr "Du må velja ei fil."
+
+#: mediagoblin/submit/views.py:50
+msgid "The file doesn't seem to be an image!"
+msgstr "Fila verkar ikkje å vera ei gyldig biletefil."
+
+#: mediagoblin/submit/views.py:122
+msgid "Woohoo! Submitted!"
+msgstr "Johoo! Opplasta!"
+
+#: 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 "GNU MediaGoblin"
+
+#: mediagoblin/templates/mediagoblin/base.html:47
+msgid "MediaGoblin logo"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/base.html:52
+msgid "Submit media"
+msgstr "Last opp"
+
+#: mediagoblin/templates/mediagoblin/base.html:63
+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
+msgid "Log in"
+msgstr "Logg inn"
+
+#: mediagoblin/templates/mediagoblin/base.html:89
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
+"href=\"http://gnu.org/\">GNU project</a>"
+msgstr ""
+"Driven av <a href=\"http://mediagoblin.org\">MediaGoblin</a>, eit <a "
+"href=\"http://gnu.org/\">GNU-prosjekt</a>"
+
+#: 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/auth/login.html:29
+msgid "Logging in failed!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:42
+msgid "Don't have an account yet?"
+msgstr "Har du ingen konto?"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:45
+msgid "Create one here!"
+msgstr "Lag ein!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:27
+msgid "Create an account!"
+msgstr "Lag ein konto."
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:30
+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 ""
+"Hei %(username)s,\n"
+"\n"
+"opna den følgjande adressa 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"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:36
+msgid "Cancel"
+msgstr "Avbryt"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:37
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
+msgid "Save changes"
+msgstr "Lagra"
+
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:29
+#, python-format
+msgid "Editing %(username)s's profile"
+msgstr "Redigerar profilen til %(username)s"
+
+#: mediagoblin/templates/mediagoblin/listings/tag.html:31
+msgid "Media tagged with:"
+msgstr "Merkelappar:"
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:26
+msgid "Submit yer media"
+msgstr "Last opp"
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:29
+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"
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:32
+msgid "Sorry, no such user found."
+msgstr "Fann ingen slik brukar"
+
+#: 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 "Ein epost med instruksjonar kjem straks."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:51
+msgid "In case it doesn't:"
+msgstr "I tilfelle det ikkje skjer:"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:54
+msgid "Resend verification email"
+msgstr "Send ein ny epost"
+
+#: 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 ""
+"Viss dette er deg, kan du <a href=\"%(login_url)s\">logga inn</a> for å få "
+"tilsendt ny epost med stadfestingslenkje."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:78
+#, python-format
+msgid "%(username)s's profile"
+msgstr "%(username)s sin profil"
+
+#: 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 "Endra profil"
+
+#: 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 "Sjå all media frå %(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 ""
+
+#: 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/user_pages/forms.py:24
+msgid "Comment"
+msgstr ""
+
+
diff --git a/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.mo
new file mode 100644
index 00000000..b2e1161e
--- /dev/null
+++ 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
new file mode 100644
index 00000000..438af907
--- /dev/null
+++ b/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.po
@@ -0,0 +1,397 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+#
+# <snd.noise@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-08-25 07:41-0500\n"
+"PO-Revision-Date: 2011-08-25 12:41+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"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 0.9.6\n"
+"Language: pt_BR\n"
+"Plural-Forms: nplurals=2; plural=(n > 1)\n"
+
+#: mediagoblin/auth/forms.py:24 mediagoblin/auth/forms.py:46
+msgid "Username"
+msgstr "Nome de Usuário"
+
+#: mediagoblin/auth/forms.py:29 mediagoblin/auth/forms.py:50
+msgid "Password"
+msgstr "Senha"
+
+#: mediagoblin/auth/forms.py:34
+msgid "Passwords must match."
+msgstr "Senhas devem ser iguais."
+
+#: mediagoblin/auth/forms.py:36
+msgid "Confirm password"
+msgstr "Confirmar senha"
+
+#: mediagoblin/auth/forms.py:39
+msgid "Email address"
+msgstr "Endereço de email"
+
+#: mediagoblin/auth/views.py:40
+msgid "Sorry, registration is disabled on this instance."
+msgstr "Desculpa, o registro está desativado neste momento."
+
+#: mediagoblin/auth/views.py:57
+msgid "Sorry, a user with that name already exists."
+msgstr "Desculpe, um usuário com este nome já existe."
+
+#: mediagoblin/auth/views.py:61
+msgid "Sorry, that email address has already been taken."
+msgstr ""
+
+#: mediagoblin/auth/views.py:159
+msgid ""
+"Your email address has been verified. You may now login, edit your profile, "
+"and submit images!"
+msgstr ""
+"O seu endereço de e-mail foi verificado. Você pode agora fazer login, editar"
+" seu perfil, e enviar imagens!"
+
+#: mediagoblin/auth/views.py:165
+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:186
+#: mediagoblin/templates/mediagoblin/auth/resent_verification_email.html:22
+msgid "Resent your verification email."
+msgstr "O email de verificação foi reenviado."
+
+#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+msgid "Title"
+msgstr "Título"
+
+#: mediagoblin/edit/forms.py:29
+msgid "Slug"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:30
+msgid "The slug can't be empty"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:31
+msgid "Tags"
+msgstr "Tags"
+
+#: mediagoblin/edit/forms.py:38
+msgid "Bio"
+msgstr "Biográfia"
+
+#: mediagoblin/edit/forms.py:41
+msgid "Website"
+msgstr "Website"
+
+#: mediagoblin/edit/views.py:65
+msgid "An entry with that slug already exists for this user."
+msgstr ""
+
+#: mediagoblin/edit/views.py:94
+msgid "You are editing another user's media. Proceed with caution."
+msgstr ""
+
+#: mediagoblin/edit/views.py:165
+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 "Arquivo"
+
+#: mediagoblin/submit/views.py:47
+msgid "You must provide a file."
+msgstr "Você deve fornecer um arquivo."
+
+#: mediagoblin/submit/views.py:50
+msgid "The file doesn't seem to be an image!"
+msgstr "O arquivo não parece ser uma imagem!"
+
+#: mediagoblin/submit/views.py:122
+msgid "Woohoo! Submitted!"
+msgstr "Eba! Enviado!"
+
+#: 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 "GNU MediaGoblin"
+
+#: mediagoblin/templates/mediagoblin/base.html:47
+msgid "MediaGoblin logo"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/base.html:52
+msgid "Submit media"
+msgstr "Enviar mídia"
+
+#: mediagoblin/templates/mediagoblin/base.html:63
+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
+msgid "Log in"
+msgstr "Entrar"
+
+#: mediagoblin/templates/mediagoblin/base.html:89
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
+"href=\"http://gnu.org/\">GNU project</a>"
+msgstr ""
+"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
+"href=\"http://gnu.org/\">GNU project</a>"
+
+#: 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/auth/login.html:29
+msgid "Logging in failed!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:42
+msgid "Don't have an account yet?"
+msgstr "Ainda não tem conta?"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:45
+msgid "Create one here!"
+msgstr "Crie uma aqui!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:27
+msgid "Create an account!"
+msgstr "Criar uma conta!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:30
+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 ""
+"Olá %(username)s,\n"
+"\n"
+"Para ativar sua conta GNU MediaGoblin, visite este endereço no seu navegador:\n"
+"\n"
+"%(verification_url)s"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:29
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "Editando %(media_title)s"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:36
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:37
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
+msgid "Save changes"
+msgstr "Salvar mudanças"
+
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:29
+#, python-format
+msgid "Editing %(username)s's profile"
+msgstr "Editando perfil de %(username)s"
+
+#: mediagoblin/templates/mediagoblin/listings/tag.html:31
+msgid "Media tagged with:"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:26
+msgid "Submit yer media"
+msgstr "Envie sua mídia"
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:29
+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 ""
+
+#: 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."
+
+#: 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 "Receberá um email com instruções de como fazer."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:51
+msgid "In case it doesn't:"
+msgstr "Caso contrário:"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:54
+msgid "Resend verification email"
+msgstr "Reenviar email de verificação"
+
+#: 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 ""
+"Se você é essa pessoa, mas você perdeu seu e-mail de verificação, você pode "
+"<a href=\"%(login_url)s\">efetuar login</a> e reenviá-la."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:78
+#, python-format
+msgid "%(username)s's profile"
+msgstr "Perfil 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 "Editar 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 ""
+
+#: 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/user_pages/forms.py:24
+msgid "Comment"
+msgstr ""
+
+
diff --git a/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.mo
new file mode 100644
index 00000000..23d205cf
--- /dev/null
+++ 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
new file mode 100644
index 00000000..e0727b69
--- /dev/null
+++ b/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.po
@@ -0,0 +1,414 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+#
+# <gapop@hotmail.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-08-25 07:41-0500\n"
+"PO-Revision-Date: 2011-08-25 12:41+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: ro\n"
+"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1))\n"
+
+#: mediagoblin/auth/forms.py:24 mediagoblin/auth/forms.py:46
+msgid "Username"
+msgstr "Nume de utilizator"
+
+#: mediagoblin/auth/forms.py:29 mediagoblin/auth/forms.py:50
+msgid "Password"
+msgstr "Parolă"
+
+#: mediagoblin/auth/forms.py:34
+msgid "Passwords must match."
+msgstr "Parolele trebuie să fie identice."
+
+#: mediagoblin/auth/forms.py:36
+msgid "Confirm password"
+msgstr "Reintroduceți parola"
+
+#: mediagoblin/auth/forms.py:39
+msgid "Email address"
+msgstr "Adresa de e-mail"
+
+#: mediagoblin/auth/views.py:40
+msgid "Sorry, registration is disabled on this instance."
+msgstr "Ne pare rău, dar înscrierile sunt dezactivate pe această instanță."
+
+#: mediagoblin/auth/views.py:57
+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:61
+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:159
+msgid ""
+"Your email address has been verified. You may now login, edit your profile, "
+"and submit images!"
+msgstr ""
+"Adresa dvs. de e-mail a fost confirmată. Puteți să vă autentificați, să vă "
+"modificați profilul și să trimiteți imagini!"
+
+#: mediagoblin/auth/views.py:165
+msgid "The verification key or user id is incorrect"
+msgstr "Cheie de verificare sau user ID incorect."
+
+#: mediagoblin/auth/views.py:186
+#: mediagoblin/templates/mediagoblin/auth/resent_verification_email.html:22
+msgid "Resent your verification email."
+msgstr "E-mail-ul de verificare a fost retrimis."
+
+#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+msgid "Title"
+msgstr "Titlu"
+
+#: mediagoblin/edit/forms.py:29
+msgid "Slug"
+msgstr "Identificator"
+
+#: mediagoblin/edit/forms.py:30
+msgid "The slug can't be empty"
+msgstr "Identificatorul nu poate să lipsească"
+
+#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:31
+msgid "Tags"
+msgstr "Etichete"
+
+#: mediagoblin/edit/forms.py:38
+msgid "Bio"
+msgstr "Biografie"
+
+#: mediagoblin/edit/forms.py:41
+msgid "Website"
+msgstr "Sit Web"
+
+#: mediagoblin/edit/views.py:65
+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:94
+msgid "You are editing another user's media. Proceed with caution."
+msgstr "Editați fișierul unui alt utilizator. Se recomandă prudență."
+
+#: mediagoblin/edit/views.py:165
+msgid "You are editing a user's profile. Proceed with caution."
+msgstr "Editați profilul unui utilizator. Se recomandă prudență."
+
+#: mediagoblin/process_media/errors.py:44
+msgid "Invalid file given for media type."
+msgstr "Formatul fișierului nu corespunde cu tipul selectat."
+
+#: mediagoblin/submit/forms.py:25
+msgid "File"
+msgstr "Fișier"
+
+#: mediagoblin/submit/views.py:47
+msgid "You must provide a file."
+msgstr "Trebuie să selectați un fișier."
+
+#: mediagoblin/submit/views.py:50
+msgid "The file doesn't seem to be an image!"
+msgstr "Fișierul nu pare a fi o imagine!"
+
+#: mediagoblin/submit/views.py:122
+msgid "Woohoo! Submitted!"
+msgstr "Gata, trimis!"
+
+#: 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 "Ne pare rău, nu există nicio pagină la această adresă."
+
+#: 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 ""
+"Dacă sunteți sigur că adresa este coresctă, poate că pagina pe care o "
+"căutați a fost mutată sau ștearsă."
+
+#: mediagoblin/templates/mediagoblin/404.html:32
+msgid "Image of 404 goblin stressing out"
+msgstr "Imagine cu elful 404 stresat."
+
+#: mediagoblin/templates/mediagoblin/base.html:22
+msgid "GNU MediaGoblin"
+msgstr "GNU MediaGoblin"
+
+#: mediagoblin/templates/mediagoblin/base.html:47
+msgid "MediaGoblin logo"
+msgstr "logo MediaGoblin"
+
+#: mediagoblin/templates/mediagoblin/base.html:52
+msgid "Submit media"
+msgstr "Transmiteți fișier"
+
+#: mediagoblin/templates/mediagoblin/base.html:63
+msgid "verify your email!"
+msgstr "verificați e-mail-ul!"
+
+#: mediagoblin/templates/mediagoblin/base.html:73
+#: mediagoblin/templates/mediagoblin/auth/login.html:26
+#: mediagoblin/templates/mediagoblin/auth/login.html:34
+msgid "Log in"
+msgstr "Autentificare"
+
+#: mediagoblin/templates/mediagoblin/base.html:89
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
+"href=\"http://gnu.org/\">GNU project</a>"
+msgstr ""
+"Construit cu <a href=\"http://mediagoblin.org\">MediaGoblin</a>, un <a "
+"href=\"http://gnu.org/\">proiect GNU</a>"
+
+#: mediagoblin/templates/mediagoblin/root.html:27
+msgid "Hi there, media lover! MediaGoblin is..."
+msgstr "Bună! MediaGoblin este..."
+
+#: mediagoblin/templates/mediagoblin/root.html:29
+msgid "The perfect place for your media!"
+msgstr "Locul perfect pentru fișierele tale media!"
+
+#: mediagoblin/templates/mediagoblin/root.html:30
+msgid ""
+"A place for people to collaborate and show off original and derived "
+"creations!"
+msgstr ""
+"Un loc unde oamenii colaborează și își expun creațiile originale și "
+"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 ""
+
+#: mediagoblin/templates/mediagoblin/root.html:32
+msgid ""
+"Aiming to make the world a better place through decentralization and "
+"(eventually, coming soon!) federation!"
+msgstr ""
+"Un pas spre o lume mai bună prin descentralizare și (în curând) "
+"federalizare!"
+
+#: mediagoblin/templates/mediagoblin/root.html:33
+msgid ""
+"Built for extensibility. (Multiple media types coming soon to the software,"
+" including video support!)"
+msgstr ""
+"Proiectat să fie extensibil. (Software-ul va avea în curând suport pentru "
+"multiple formate de media, inclusiv pentru 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 ""
+"Animat de oameni ca tine. (<a "
+"href=\"http://mediagoblin.org/pages/join.html\">Ne poți ajuta să îmbunătățim"
+" acest software!</a>)"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:29
+msgid "Logging in failed!"
+msgstr "Autentificare eșuată!"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:42
+msgid "Don't have an account yet?"
+msgstr "Nu aveți un cont?"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:45
+msgid "Create one here!"
+msgstr "Creați-l aici!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:27
+msgid "Create an account!"
+msgstr "Creați un cont!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:30
+msgid "Create"
+msgstr "Creează"
+
+#: 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 ""
+"Bună, %(username)s,\n"
+"\n"
+"pentru activarea contului tău GNU MediaGoblin, accesează adresa următoare:\n"
+"\n"
+"%(verification_url)s"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:29
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "Editare %(media_title)s"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:36
+msgid "Cancel"
+msgstr "Anulare"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:37
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
+msgid "Save changes"
+msgstr "Salvează modificările"
+
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:29
+#, python-format
+msgid "Editing %(username)s's profile"
+msgstr "Editare profil %(username)s"
+
+#: mediagoblin/templates/mediagoblin/listings/tag.html:31
+msgid "Media tagged with:"
+msgstr "Etichete:"
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:26
+msgid "Submit yer media"
+msgstr "Trimite fișierele tale media"
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:29
+msgid "Submit"
+msgstr "Trimite"
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media"
+msgstr "Fișierele media ale lui <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 "Ne pare rău, nu am găsit utilizatorul căutat."
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:22
+msgid "Media processing panel"
+msgstr "Panou de procesare 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 "Aici poți urmări stadiul procesării fișierelor media din galeria ta."
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:28
+msgid "Media in-processing"
+msgstr "Fișiere în curs de procesare"
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:46
+msgid "No media in-processing"
+msgstr "Niciun fișier în curs de procesare"
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:50
+msgid "These uploads failed to process:"
+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"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:42
+msgid "Almost done! Your account still needs to be activated."
+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 "Veți primi în scurt timp un mesaj prin e-mail cu instrucțiuni."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:51
+msgid "In case it doesn't:"
+msgstr "Dacă nu primiți mesajul:"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:54
+msgid "Resend verification email"
+msgstr "Retrimite mesajul de verificare"
+
+#: 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 ""
+"Cineva a înregistrat un cont cu acest nume de utilizator, dar contul nu a "
+"fost încă activat."
+
+#: 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 ""
+"Dacă dvs. sunteți persoana respectivă și nu mai aveți e-mail-ul de "
+"verificare, puteți să vă <a href=\"%(login_url)s\">autentificați</a> pentru "
+"a-l retrimite."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:78
+#, python-format
+msgid "%(username)s's profile"
+msgstr "Profil %(username)s"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:85
+msgid "Here's a spot to tell others about yourself."
+msgstr "Aici poți spune altora ceva despre tine."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:90
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:108
+msgid "Edit profile"
+msgstr "Editare profil"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:96
+msgid "This user hasn't filled in their profile (yet)."
+msgstr "Acest utilizator nu și-a completat (încă) profilul."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:122
+#, python-format
+msgid "View all of %(username)s's media"
+msgstr "Toate fișierele lui %(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 ""
+"Aici vor apărea fișierele tale media, dar se pare că încă nu ai trimis "
+"nimic."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:141
+msgid "Add media"
+msgstr "Trimite fișier"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:147
+msgid "There doesn't seem to be any media here yet..."
+msgstr "Nu pare să existe niciun fișier media deocamdată..."
+
+#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
+msgid "feed icon"
+msgstr "icon feed"
+
+#: mediagoblin/templates/mediagoblin/utils/feed_link.html:23
+msgid "Atom feed"
+msgstr "feed Atom"
+
+#: mediagoblin/user_pages/forms.py:24
+msgid "Comment"
+msgstr "Scrie un comentariu"
+
+
diff --git a/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.mo
new file mode 100644
index 00000000..55f611d5
--- /dev/null
+++ 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
new file mode 100644
index 00000000..53222a97
--- /dev/null
+++ b/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.po
@@ -0,0 +1,387 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+#
+# <deletesoftware@yandex.ru>, 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-08-25 07:41-0500\n"
+"PO-Revision-Date: 2011-08-25 12:41+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: ru\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
+
+#: mediagoblin/auth/forms.py:24 mediagoblin/auth/forms.py:46
+msgid "Username"
+msgstr "Логин"
+
+#: mediagoblin/auth/forms.py:29 mediagoblin/auth/forms.py:50
+msgid "Password"
+msgstr "Пароль"
+
+#: mediagoblin/auth/forms.py:34
+msgid "Passwords must match."
+msgstr "Пароли должны совпадать."
+
+#: mediagoblin/auth/forms.py:36
+msgid "Confirm password"
+msgstr "Подтвердите пароль"
+
+#: mediagoblin/auth/forms.py:39
+msgid "Email address"
+msgstr "Адрес электронной почты"
+
+#: mediagoblin/auth/views.py:40
+msgid "Sorry, registration is disabled on this instance."
+msgstr ""
+
+#: mediagoblin/auth/views.py:57
+msgid "Sorry, a user with that name already exists."
+msgstr ""
+
+#: mediagoblin/auth/views.py:61
+msgid "Sorry, that email address has already been taken."
+msgstr ""
+
+#: mediagoblin/auth/views.py:159
+msgid ""
+"Your email address has been verified. You may now login, edit your profile, "
+"and submit images!"
+msgstr ""
+
+#: mediagoblin/auth/views.py:165
+msgid "The verification key or user id is incorrect"
+msgstr ""
+
+#: mediagoblin/auth/views.py:186
+#: mediagoblin/templates/mediagoblin/auth/resent_verification_email.html:22
+msgid "Resent your verification email."
+msgstr ""
+
+#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+msgid "Title"
+msgstr "Название"
+
+#: mediagoblin/edit/forms.py:29
+msgid "Slug"
+msgstr "Отличительная часть адреса"
+
+#: mediagoblin/edit/forms.py:30
+msgid "The slug can't be empty"
+msgstr "Отличительная часть адреса необходима"
+
+#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:31
+msgid "Tags"
+msgstr "Метки"
+
+#: mediagoblin/edit/forms.py:38
+msgid "Bio"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:41
+msgid "Website"
+msgstr "Сайт"
+
+#: mediagoblin/edit/views.py:65
+msgid "An entry with that slug already exists for this user."
+msgstr ""
+"У этого пользователя уже есть файл с такой отличительной частью адреса."
+
+#: mediagoblin/edit/views.py:94
+msgid "You are editing another user's media. Proceed with caution."
+msgstr ""
+
+#: mediagoblin/edit/views.py:165
+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/views.py:47
+msgid "You must provide a file."
+msgstr ""
+
+#: mediagoblin/submit/views.py:50
+msgid "The file doesn't seem to be an image!"
+msgstr ""
+
+#: mediagoblin/submit/views.py:122
+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:26
+#: mediagoblin/templates/mediagoblin/auth/login.html:34
+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 project</a>"
+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/auth/login.html:29
+msgid "Logging in failed!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:42
+msgid "Don't have an account yet?"
+msgstr "Ещё нет учётной записи?"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:45
+msgid "Create one here!"
+msgstr "Создайте её здесь!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:27
+msgid "Create an account!"
+msgstr "Создаём учётную запись!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:30
+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 "Редактирование %(media_title)s"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:36
+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 "Редактирование профиля %(username)s"
+
+#: 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:29
+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/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 "Профиль пользователя %(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 "Смотреть все файлы %(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 ""
+
+#: 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/user_pages/forms.py:24
+msgid "Comment"
+msgstr ""
+
+
diff --git a/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.mo
new file mode 100644
index 00000000..aaeec466
--- /dev/null
+++ 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
new file mode 100644
index 00000000..3db6ed4a
--- /dev/null
+++ b/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.po
@@ -0,0 +1,411 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+#
+# Jure Repinc <jlp@holodeck1.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-08-25 07:41-0500\n"
+"PO-Revision-Date: 2011-08-25 12:41+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: sl\n"
+"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3)\n"
+
+#: mediagoblin/auth/forms.py:24 mediagoblin/auth/forms.py:46
+msgid "Username"
+msgstr "Uporabniško ime"
+
+#: mediagoblin/auth/forms.py:29 mediagoblin/auth/forms.py:50
+msgid "Password"
+msgstr "Geslo"
+
+#: mediagoblin/auth/forms.py:34
+msgid "Passwords must match."
+msgstr "Gesli morata biti enaki."
+
+#: mediagoblin/auth/forms.py:36
+msgid "Confirm password"
+msgstr "Potrdite geslo"
+
+#: mediagoblin/auth/forms.py:39
+msgid "Email address"
+msgstr "E-poštni naslov"
+
+#: mediagoblin/auth/views.py:40
+msgid "Sorry, registration is disabled on this instance."
+msgstr "Oprostite, prijava za ta izvod ni omogočena."
+
+#: mediagoblin/auth/views.py:57
+msgid "Sorry, a user with that name already exists."
+msgstr "Oprostite, uporabnik s tem imenom že obstaja."
+
+#: mediagoblin/auth/views.py:61
+msgid "Sorry, that email address has already been taken."
+msgstr "Oprostite, ta e-poštni naslov je že v uporabi."
+
+#: mediagoblin/auth/views.py:159
+msgid ""
+"Your email address has been verified. You may now login, edit your profile, "
+"and submit images!"
+msgstr ""
+"Vaš e-poštni naslov je bil potrjen. Sedaj se lahko prijavite, uredite svoj "
+"profil in pošljete slike."
+
+#: mediagoblin/auth/views.py:165
+msgid "The verification key or user id is incorrect"
+msgstr "Potrditveni ključ ali uporabniška identifikacija je napačna"
+
+#: mediagoblin/auth/views.py:186
+#: mediagoblin/templates/mediagoblin/auth/resent_verification_email.html:22
+msgid "Resent your verification email."
+msgstr "Ponovno pošiljanje potrditvene e-pošte."
+
+#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+msgid "Title"
+msgstr "Naslov"
+
+#: mediagoblin/edit/forms.py:29
+msgid "Slug"
+msgstr "Oznaka"
+
+#: mediagoblin/edit/forms.py:30
+msgid "The slug can't be empty"
+msgstr "Oznaka ne sme biti prazna"
+
+#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:31
+msgid "Tags"
+msgstr "Oznake"
+
+#: mediagoblin/edit/forms.py:38
+msgid "Bio"
+msgstr "Biografija"
+
+#: mediagoblin/edit/forms.py:41
+msgid "Website"
+msgstr "Spletna stran"
+
+#: mediagoblin/edit/views.py:65
+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:94
+msgid "You are editing another user's media. Proceed with caution."
+msgstr "Urejate vsebino drugega uporabnika. Nadaljujte pazljivo."
+
+#: mediagoblin/edit/views.py:165
+msgid "You are editing a user's profile. Proceed with caution."
+msgstr "Urejate uporabniški profil. Nadaljujte pazljivo."
+
+#: mediagoblin/process_media/errors.py:44
+msgid "Invalid file given for media type."
+msgstr "Za vrsto vsebine je bila podana napačna datoteka."
+
+#: mediagoblin/submit/forms.py:25
+msgid "File"
+msgstr "Datoteka"
+
+#: mediagoblin/submit/views.py:47
+msgid "You must provide a file."
+msgstr "Podati morate datoteko."
+
+#: mediagoblin/submit/views.py:50
+msgid "The file doesn't seem to be an image!"
+msgstr "Kot kaže datoteka ni slika."
+
+#: mediagoblin/submit/views.py:122
+msgid "Woohoo! Submitted!"
+msgstr "Juhej! Poslano."
+
+#: mediagoblin/templates/mediagoblin/404.html:21
+msgid "Oops!"
+msgstr "Opa!"
+
+#: mediagoblin/templates/mediagoblin/404.html:24
+msgid "There doesn't seem to be a page at this address. Sorry!"
+msgstr "Oprostite. Videti je, da na tem naslovu ni nobene strani."
+
+#: mediagoblin/templates/mediagoblin/404.html:26
+msgid ""
+"If you're sure the address is correct, maybe the page you're looking for has"
+" been moved or deleted."
+msgstr ""
+"Če ste v točnost naslova prepričani, je bila iskana stran morda premaknjena "
+"ali pa izbrisana."
+
+#: mediagoblin/templates/mediagoblin/404.html:32
+msgid "Image of 404 goblin stressing out"
+msgstr "Slika napake 404 s paničnim škratom"
+
+#: mediagoblin/templates/mediagoblin/base.html:22
+msgid "GNU MediaGoblin"
+msgstr "GNU MediaGoblin"
+
+#: mediagoblin/templates/mediagoblin/base.html:47
+msgid "MediaGoblin logo"
+msgstr "Logotip MediaGoblin"
+
+#: mediagoblin/templates/mediagoblin/base.html:52
+msgid "Submit media"
+msgstr "Pošlji vsebino"
+
+#: mediagoblin/templates/mediagoblin/base.html:63
+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
+msgid "Log in"
+msgstr "Prijava"
+
+#: mediagoblin/templates/mediagoblin/base.html:89
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
+"href=\"http://gnu.org/\">GNU project</a>"
+msgstr ""
+"Stran poganja <a href=\"http://mediagoblin.org\">MediaGoblin</a>, del <a "
+"href=\"http://gnu.org/\">projekta GNU</a>"
+
+#: mediagoblin/templates/mediagoblin/root.html:27
+msgid "Hi there, media lover! MediaGoblin is..."
+msgstr "Pozdravljen, ljubitelj večpredstavnostnih vsebin! MediaGoblin je ..."
+
+#: mediagoblin/templates/mediagoblin/root.html:29
+msgid "The perfect place for your media!"
+msgstr "Popolno mesto za vaše večpredstavnostne vsebine."
+
+#: mediagoblin/templates/mediagoblin/root.html:30
+msgid ""
+"A place for people to collaborate and show off original and derived "
+"creations!"
+msgstr ""
+"Mesto, kjer ljudje lahko sodelujejo in razkazujejo originalne in predelane "
+"stvaritve."
+
+#: 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 ""
+"Ustvarjen z namenom izboljšati svet, s pomočjo decentralizacije in (kmalu) "
+"federacije."
+
+#: mediagoblin/templates/mediagoblin/root.html:33
+msgid ""
+"Built for extensibility. (Multiple media types coming soon to the software,"
+" including video support!)"
+msgstr ""
+"Zgrajen za razširjanje. (Kmalu bodo na voljo dodatne vrste vsebin, vključno "
+"podpora za 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 ""
+"Sad dela ljudi, kot ste vi. (<a "
+"href=\"http://mediagoblin.org/pages/join.html\">Pri izboljševanju nam lahko "
+"pomagate tudi vi.</a>)"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:29
+msgid "Logging in failed!"
+msgstr "Prijava ni uspela."
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:42
+msgid "Don't have an account yet?"
+msgstr "Še nimate računa?"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:45
+msgid "Create one here!"
+msgstr "Ustvarite si ga."
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:27
+msgid "Create an account!"
+msgstr "Ustvarite račun."
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:30
+msgid "Create"
+msgstr "Ustvari"
+
+#: 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 ""
+"Pozdravljeni, %(username)s\n"
+"\n"
+"Za aktivacijo svojega računa GNU MediaGoblin odprite\n"
+"naslednji URL v svojem spletnem brskalniku:\n"
+"\n"
+"%(verification_url)s"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:29
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "Urejanje %(media_title)s"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:36
+msgid "Cancel"
+msgstr "Prekliči"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:37
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
+msgid "Save changes"
+msgstr "Shrani spremembe"
+
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:29
+#, python-format
+msgid "Editing %(username)s's profile"
+msgstr "Urejanje profila – %(username)s"
+
+#: mediagoblin/templates/mediagoblin/listings/tag.html:31
+msgid "Media tagged with:"
+msgstr "Vsebina označena z:"
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:26
+msgid "Submit yer media"
+msgstr "Pošljite svojo vsebino"
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:29
+msgid "Submit"
+msgstr "Pošlji"
+
+#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32
+#, python-format
+msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media"
+msgstr "Vsebina uporabnika <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 "Oprostite, tega uporabnika ni bilo moč najti."
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:22
+msgid "Media processing panel"
+msgstr "Podokno obdelovanja vsebine"
+
+#: 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 lahko spremljate stanje vsebin, ki so v obdelavi za vašo galerijo."
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:28
+msgid "Media in-processing"
+msgstr "Vsebina v obdelavi"
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:46
+msgid "No media in-processing"
+msgstr "V obdelavi ni nobene vsebine"
+
+#: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:50
+msgid "These uploads failed to process:"
+msgstr "Teh vsebin ni bilo moč obdelati:"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:39
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:59
+msgid "Email verification needed"
+msgstr "Potrebna je potrditev prek e-pošte"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:42
+msgid "Almost done! Your account still needs to be activated."
+msgstr "Skoraj ste zaključili. Svoj račun morate le še aktivirati."
+
+#: 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 "V kratkem bi morali prejeti e-pošto z navodili, kako to storiti."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:51
+msgid "In case it doesn't:"
+msgstr "Če je ne prejmete:"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:54
+msgid "Resend verification email"
+msgstr "Ponovno pošlji potrditveno e-pošto"
+
+#: 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 ""
+"Nekdo je s tem uporabniškim imenom že registriral račun, vendar mora biti še"
+" aktiviran."
+
+#: 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 ""
+"Če ste ta oseba vi, a ste izgubili potrditveno e-pošto, se lahko <a "
+"href=\"%(login_url)s\">prijavite</a> in jo ponovno pošljete."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:78
+#, python-format
+msgid "%(username)s's profile"
+msgstr "Profil – %(username)s"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:85
+msgid "Here's a spot to tell others about yourself."
+msgstr "Na tem mestu lahko drugim poveste nekaj o sebi."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:90
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:108
+msgid "Edit profile"
+msgstr "Uredi profil"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:96
+msgid "This user hasn't filled in their profile (yet)."
+msgstr "Ta uporabnik še ni izpolnil svojega profila."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:122
+#, python-format
+msgid "View all of %(username)s's media"
+msgstr "Prikaži vso vsebino uporabnika %(username)s"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:135
+msgid ""
+"This is where your media will appear, but you don't seem to have added "
+"anything yet."
+msgstr "Tu bo prikazana vaša vsebina, a trenutno še niste dodali nič."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:141
+msgid "Add media"
+msgstr "Dodaj vsebino"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:147
+msgid "There doesn't seem to be any media here yet..."
+msgstr "Videti je, da tu še ni nobene vsebine ..."
+
+#: mediagoblin/templates/mediagoblin/utils/feed_link.html:21
+msgid "feed icon"
+msgstr "Ikona vira"
+
+#: mediagoblin/templates/mediagoblin/utils/feed_link.html:23
+msgid "Atom feed"
+msgstr "Ikona Atom"
+
+#: mediagoblin/user_pages/forms.py:24
+msgid "Comment"
+msgstr "Komentar"
+
+
diff --git a/mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.mo
new file mode 100644
index 00000000..2f9de271
--- /dev/null
+++ 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
new file mode 100644
index 00000000..51c2e443
--- /dev/null
+++ b/mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.po
@@ -0,0 +1,385 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: GNU MediaGoblin\n"
+"Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n"
+"POT-Creation-Date: 2011-08-25 07:41-0500\n"
+"PO-Revision-Date: 2011-08-25 12:41+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"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 0.9.6\n"
+"Language: sr\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
+
+#: mediagoblin/auth/forms.py:24 mediagoblin/auth/forms.py:46
+msgid "Username"
+msgstr ""
+
+#: mediagoblin/auth/forms.py:29 mediagoblin/auth/forms.py:50
+msgid "Password"
+msgstr ""
+
+#: mediagoblin/auth/forms.py:34
+msgid "Passwords must match."
+msgstr ""
+
+#: mediagoblin/auth/forms.py:36
+msgid "Confirm password"
+msgstr ""
+
+#: mediagoblin/auth/forms.py:39
+msgid "Email address"
+msgstr ""
+
+#: mediagoblin/auth/views.py:40
+msgid "Sorry, registration is disabled on this instance."
+msgstr ""
+
+#: mediagoblin/auth/views.py:57
+msgid "Sorry, a user with that name already exists."
+msgstr ""
+
+#: mediagoblin/auth/views.py:61
+msgid "Sorry, that email address has already been taken."
+msgstr ""
+
+#: mediagoblin/auth/views.py:159
+msgid ""
+"Your email address has been verified. You may now login, edit your profile, "
+"and submit images!"
+msgstr ""
+
+#: mediagoblin/auth/views.py:165
+msgid "The verification key or user id is incorrect"
+msgstr ""
+
+#: mediagoblin/auth/views.py:186
+#: mediagoblin/templates/mediagoblin/auth/resent_verification_email.html:22
+msgid "Resent your verification email."
+msgstr ""
+
+#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+msgid "Title"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:29
+msgid "Slug"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:30
+msgid "The slug can't be empty"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:31
+msgid "Tags"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:38
+msgid "Bio"
+msgstr ""
+
+#: mediagoblin/edit/forms.py:41
+msgid "Website"
+msgstr ""
+
+#: mediagoblin/edit/views.py:65
+msgid "An entry with that slug already exists for this user."
+msgstr ""
+
+#: mediagoblin/edit/views.py:94
+msgid "You are editing another user's media. Proceed with caution."
+msgstr ""
+
+#: mediagoblin/edit/views.py:165
+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/views.py:47
+msgid "You must provide a file."
+msgstr ""
+
+#: mediagoblin/submit/views.py:50
+msgid "The file doesn't seem to be an image!"
+msgstr ""
+
+#: mediagoblin/submit/views.py:122
+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:26
+#: mediagoblin/templates/mediagoblin/auth/login.html:34
+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 project</a>"
+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/auth/login.html:29
+msgid "Logging in failed!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:42
+msgid "Don't have an account yet?"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:45
+msgid "Create one here!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:27
+msgid "Create an account!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:30
+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
+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:29
+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/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/user_pages/forms.py:24
+msgid "Comment"
+msgstr ""
+
+
diff --git a/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.mo
new file mode 100644
index 00000000..e209556f
--- /dev/null
+++ 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
new file mode 100644
index 00000000..e4183c18
--- /dev/null
+++ b/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.po
@@ -0,0 +1,408 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+#
+# <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-08-25 07:41-0500\n"
+"PO-Revision-Date: 2011-08-25 12:41+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"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 0.9.6\n"
+"Language: sv\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+
+#: mediagoblin/auth/forms.py:24 mediagoblin/auth/forms.py:46
+msgid "Username"
+msgstr "Användarnamn"
+
+#: mediagoblin/auth/forms.py:29 mediagoblin/auth/forms.py:50
+msgid "Password"
+msgstr "Lösenord"
+
+#: mediagoblin/auth/forms.py:34
+msgid "Passwords must match."
+msgstr "Lösenorden måste vara identiska."
+
+#: mediagoblin/auth/forms.py:36
+msgid "Confirm password"
+msgstr "Bekräfta lösenord"
+
+#: mediagoblin/auth/forms.py:39
+msgid "Email address"
+msgstr "E-postadress"
+
+#: mediagoblin/auth/views.py:40
+msgid "Sorry, registration is disabled on this instance."
+msgstr "Vi beklagar, registreringen är avtängd på den här instansen."
+
+#: mediagoblin/auth/views.py:57
+msgid "Sorry, a user with that name already exists."
+msgstr "En användare med det användarnamnet finns redan."
+
+#: mediagoblin/auth/views.py:61
+msgid "Sorry, that email address has already been taken."
+msgstr "Den e-postadressen är redan tagen."
+
+#: mediagoblin/auth/views.py:159
+msgid ""
+"Your email address has been verified. You may now login, edit your profile, "
+"and submit images!"
+msgstr ""
+"Din e-postadress är verifierad. Du kan nu logga in, redigera din profil och "
+"ladda upp filer!"
+
+#: mediagoblin/auth/views.py:165
+msgid "The verification key or user id is incorrect"
+msgstr "Verifieringsnyckeln eller användar-IDt är fel."
+
+#: mediagoblin/auth/views.py:186
+#: mediagoblin/templates/mediagoblin/auth/resent_verification_email.html:22
+msgid "Resent your verification email."
+msgstr "Skickade ett nytt verifierings-email."
+
+#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+msgid "Title"
+msgstr "Titel"
+
+#: mediagoblin/edit/forms.py:29
+msgid "Slug"
+msgstr "Sökvägsnamn"
+
+#: mediagoblin/edit/forms.py:30
+msgid "The slug can't be empty"
+msgstr "Sökvägsnamnet kan inte vara tomt"
+
+#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:31
+msgid "Tags"
+msgstr "Taggar"
+
+#: mediagoblin/edit/forms.py:38
+msgid "Bio"
+msgstr "Presentation"
+
+#: mediagoblin/edit/forms.py:41
+msgid "Website"
+msgstr "Hemsida"
+
+#: mediagoblin/edit/views.py:65
+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:94
+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:165
+msgid "You are editing a user's profile. Proceed with caution."
+msgstr "Var försiktig, du redigerar en annan användares profil."
+
+#: mediagoblin/process_media/errors.py:44
+msgid "Invalid file given for media type."
+msgstr "Ogiltig fil för mediatypen."
+
+#: mediagoblin/submit/forms.py:25
+msgid "File"
+msgstr "Fil"
+
+#: mediagoblin/submit/views.py:47
+msgid "You must provide a file."
+msgstr "Du måste ange en fil"
+
+#: mediagoblin/submit/views.py:50
+msgid "The file doesn't seem to be an image!"
+msgstr "Filen verkar inte vara en giltig bildfil!"
+
+#: mediagoblin/submit/views.py:122
+msgid "Woohoo! Submitted!"
+msgstr "Tjohoo! Upladdat!"
+
+#: mediagoblin/templates/mediagoblin/404.html:21
+msgid "Oops!"
+msgstr "Ojoj!"
+
+#: mediagoblin/templates/mediagoblin/404.html:24
+msgid "There doesn't seem to be a page at this address. Sorry!"
+msgstr "Ledsen, det verkar inte vara någonting här."
+
+#: mediagoblin/templates/mediagoblin/404.html:26
+msgid ""
+"If you're sure the address is correct, maybe the page you're looking for has"
+" been moved or deleted."
+msgstr ""
+"Om du är säker på att adressen stämmer så kanske sidan du letar efter har "
+"flyttats eller tagits bort."
+
+#: mediagoblin/templates/mediagoblin/404.html:32
+msgid "Image of 404 goblin stressing out"
+msgstr "Bild av stressat 404-troll."
+
+#: mediagoblin/templates/mediagoblin/base.html:22
+msgid "GNU MediaGoblin"
+msgstr "GNU MediaGoblin"
+
+#: mediagoblin/templates/mediagoblin/base.html:47
+msgid "MediaGoblin logo"
+msgstr "MediaGoblin-logotyp"
+
+#: mediagoblin/templates/mediagoblin/base.html:52
+msgid "Submit media"
+msgstr "Ladda upp"
+
+#: mediagoblin/templates/mediagoblin/base.html:63
+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
+msgid "Log in"
+msgstr "Logga in"
+
+#: mediagoblin/templates/mediagoblin/base.html:89
+msgid ""
+"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
+"href=\"http://gnu.org/\">GNU project</a>"
+msgstr ""
+"Drivs av <a href=\"http://mediagoblin.org\">MediaGoblin</a>, ett <a "
+"href=\"http://gnu.org/\">GNU</a>-projekt"
+
+#: mediagoblin/templates/mediagoblin/root.html:27
+msgid "Hi there, media lover! MediaGoblin is..."
+msgstr "Hej där mediaentusiast, MediaGoblin..."
+
+#: mediagoblin/templates/mediagoblin/root.html:29
+msgid "The perfect place for your media!"
+msgstr "Är ett perfekt ställe för din media!"
+
+#: mediagoblin/templates/mediagoblin/root.html:30
+msgid ""
+"A place for people to collaborate and show off original and derived "
+"creations!"
+msgstr ""
+"Är ett ställe för människor att samarbeta och visa upp originella och "
+"härrörande verk."
+
+#: 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 ""
+"Arbetar för att göra världen till ett bättre ställe genom decentralisering "
+"och (så småningom, kommer snart!) -- Google Translate säger "
+"\"sammanslutning\", <em>en: <a "
+"href=\"http://en.wikipedia.org/wiki/Federation_(information_technology)\">federation</a></em>"
+" "
+
+#: 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/auth/login.html:29
+msgid "Logging in failed!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:42
+msgid "Don't have an account yet?"
+msgstr "Har du inget konto?"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:45
+msgid "Create one here!"
+msgstr "Skapa ett!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:27
+msgid "Create an account!"
+msgstr "Skapa ett konto!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:30
+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 ""
+"Hej %(username)s,\n"
+"\n"
+"oppna den följande URLen i din webbläsare för att aktivera ditt konto på GNU MediaGoblin:\n"
+"\n"
+"%(verification_url)s"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:29
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "Redigerar %(media_title)s"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:36
+msgid "Cancel"
+msgstr "Avbryt"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:37
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
+msgid "Save changes"
+msgstr "Spara"
+
+#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:29
+#, python-format
+msgid "Editing %(username)s's profile"
+msgstr "Redigerar %(username)ss profil"
+
+#: mediagoblin/templates/mediagoblin/listings/tag.html:31
+msgid "Media tagged with:"
+msgstr "Taggat med:"
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:26
+msgid "Submit yer media"
+msgstr "Ladda upp"
+
+#: mediagoblin/templates/mediagoblin/submit/start.html:29
+msgid "Submit"
+msgstr "Skicka"
+
+#: 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 "Finns ingen sådan användare ännu."
+
+#: 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 ""
+"Ett e-postmeddelande med instruktioner kommer att hamna hos dig inom kort."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:51
+msgid "In case it doesn't:"
+msgstr "Om det inte skulle göra det:"
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:54
+msgid "Resend verification email"
+msgstr "Skicka ett nytt e-postmeddelande"
+
+#: 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 ""
+"Om det är du som är den personen och har förlorat ditt e-postmeddelande med "
+"detaljer om hur du verifierar ditt konto så kan du <a "
+"href=\"%(login_url)s\">logga in</a> och begära ett nytt."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:78
+#, python-format
+msgid "%(username)s's profile"
+msgstr "%(username)ss profil"
+
+#: 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 "Redigera profil"
+
+#: 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 "Se all media från %(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 ""
+
+#: 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/user_pages/forms.py:24
+msgid "Comment"
+msgstr "Kommentar"
+
+
diff --git a/mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.mo
new file mode 100644
index 00000000..ce7240fc
--- /dev/null
+++ 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
new file mode 100644
index 00000000..44670ab2
--- /dev/null
+++ b/mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.po
@@ -0,0 +1,393 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+#
+# <chc@citi.sinica.edu.tw>, 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-08-25 07:41-0500\n"
+"PO-Revision-Date: 2011-08-25 12:41+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: zh_TW\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+
+#: mediagoblin/auth/forms.py:24 mediagoblin/auth/forms.py:46
+msgid "Username"
+msgstr "使用者名稱"
+
+#: mediagoblin/auth/forms.py:29 mediagoblin/auth/forms.py:50
+msgid "Password"
+msgstr "密碼"
+
+#: mediagoblin/auth/forms.py:34
+msgid "Passwords must match."
+msgstr "密碼必須一至"
+
+#: mediagoblin/auth/forms.py:36
+msgid "Confirm password"
+msgstr "確認密碼"
+
+#: mediagoblin/auth/forms.py:39
+msgid "Email address"
+msgstr "電子郵件位置"
+
+#: mediagoblin/auth/views.py:40
+msgid "Sorry, registration is disabled on this instance."
+msgstr "抱歉, 這個項目已經被暫停註冊."
+
+#: mediagoblin/auth/views.py:57
+msgid "Sorry, a user with that name already exists."
+msgstr "抱歉, 這個使用者名稱已經存在."
+
+#: mediagoblin/auth/views.py:61
+msgid "Sorry, that email address has already been taken."
+msgstr ""
+
+#: mediagoblin/auth/views.py:159
+msgid ""
+"Your email address has been verified. You may now login, edit your profile, "
+"and submit images!"
+msgstr "你的電子郵件位址已被認證. 你現在就可以登入, 編輯你的個人檔案而且送出照片!"
+
+#: mediagoblin/auth/views.py:165
+msgid "The verification key or user id is incorrect"
+msgstr "認證碼或是使用者帳號錯誤"
+
+#: mediagoblin/auth/views.py:186
+#: mediagoblin/templates/mediagoblin/auth/resent_verification_email.html:22
+msgid "Resent your verification email."
+msgstr "重送認證郵件."
+
+#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:27
+msgid "Title"
+msgstr "稱謂"
+
+#: mediagoblin/edit/forms.py:29
+msgid "Slug"
+msgstr "自訂字串"
+
+#: mediagoblin/edit/forms.py:30
+msgid "The slug can't be empty"
+msgstr "自訂字串不能空白"
+
+#: mediagoblin/edit/forms.py:33 mediagoblin/submit/forms.py:31
+msgid "Tags"
+msgstr "標籤"
+
+#: mediagoblin/edit/forms.py:38
+msgid "Bio"
+msgstr "自傳"
+
+#: mediagoblin/edit/forms.py:41
+msgid "Website"
+msgstr "網站"
+
+#: mediagoblin/edit/views.py:65
+msgid "An entry with that slug already exists for this user."
+msgstr "這個自訂字串已經被其他人用了"
+
+#: mediagoblin/edit/views.py:94
+msgid "You are editing another user's media. Proceed with caution."
+msgstr "你正在編輯他人的媒體檔案. 請謹慎處理."
+
+#: mediagoblin/edit/views.py:165
+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/views.py:47
+msgid "You must provide a file."
+msgstr "你必須提供一個檔案"
+
+#: mediagoblin/submit/views.py:50
+msgid "The file doesn't seem to be an image!"
+msgstr "檔案看起來不像是一個圖片喔!"
+
+#: mediagoblin/submit/views.py:122
+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 "GNU MediaGoblin"
+
+#: 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:26
+#: mediagoblin/templates/mediagoblin/auth/login.html:34
+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 project</a>"
+msgstr ""
+"由 <a href=\"http://mediagoblin.org\">MediaGoblin</a> 製作, 她是一個 <a "
+"href=\"http://gnu.org/\">GNU project</a>"
+
+#: 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/auth/login.html:29
+msgid "Logging in failed!"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:42
+msgid "Don't have an account yet?"
+msgstr "還沒有帳號嗎?"
+
+#: mediagoblin/templates/mediagoblin/auth/login.html:45
+msgid "Create one here!"
+msgstr "在這裡建立一個吧!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:27
+msgid "Create an account!"
+msgstr "建立一個帳號!"
+
+#: mediagoblin/templates/mediagoblin/auth/register.html:30
+msgid "Create"
+msgstr ""
+
+#: mediagoblin/templates/mediagoblin/auth/verification_email.txt:19
+#, python-format
+msgid ""
+"Hi %(username)s,\n"
+"\n"
+"to activate your GNU MediaGoblin account, open the following URL in\n"
+"your web browser:\n"
+"\n"
+"%(verification_url)s"
+msgstr ""
+"嗨 %(username)s,\n"
+"\n"
+"啟動 GNU MediaGoblin 帳號, 在你的瀏覽器中打開下面的網址:\n"
+"\n"
+"%(verification_url)s"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:29
+#, python-format
+msgid "Editing %(media_title)s"
+msgstr "編輯 %(media_title)s 中"
+
+#: mediagoblin/templates/mediagoblin/edit/edit.html:36
+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 "編輯 %(username)s'的檔案中"
+
+#: 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:29
+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 "<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 "抱歉, 找不到這個使用者."
+
+#: 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 "如果你就是那個人, 但是遺失了認證信, 你可以<a href=\"%(login_url)s\">登入</a> 然後重送一次."
+
+#: mediagoblin/templates/mediagoblin/user_pages/user.html:78
+#, python-format
+msgid "%(username)s's profile"
+msgstr "%(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 "查看%(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 ""
+
+#: 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/user_pages/forms.py:24
+msgid "Comment"
+msgstr ""
+
+
diff --git a/mediagoblin/init/__init__.py b/mediagoblin/init/__init__.py
index ff005703..44f604b1 100644
--- a/mediagoblin/init/__init__.py
+++ b/mediagoblin/init/__init__.py
@@ -112,10 +112,15 @@ def get_staticdirector(app_config):
def setup_storage():
- app_config = mg_globals.app_config
+ global_config = mg_globals.global_config
+
+ key_short = 'publicstore'
+ key_long = "storage:" + key_short
+ public_store = storage_system_from_config(global_config[key_long])
- public_store = storage_system_from_config(app_config, 'publicstore')
- queue_store = storage_system_from_config(app_config, 'queuestore')
+ key_short = 'queuestore'
+ key_long = "storage:" + key_short
+ queue_store = storage_system_from_config(global_config[key_long])
setup_globals(
public_store = public_store,
diff --git a/mediagoblin/process_media/__init__.py b/mediagoblin/process_media/__init__.py
index 8e12ca4d..e1289a4c 100644
--- a/mediagoblin/process_media/__init__.py
+++ b/mediagoblin/process_media/__init__.py
@@ -15,11 +15,14 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import Image
-from mediagoblin.db.util import ObjectId
-from celery.task import task
-from mediagoblin import mg_globals as mgg
from contextlib import contextmanager
+from celery.task import Task
+from celery import registry
+
+from mediagoblin.db.util import ObjectId
+from mediagoblin import mg_globals as mgg
+from mediagoblin.process_media.errors import BaseProcessingFail, BadMediaFail
THUMB_SIZE = 180, 180
@@ -32,6 +35,7 @@ def create_pub_filepath(entry, filename):
unicode(entry['_id']),
filename])
+
@contextmanager
def closing(callback):
try:
@@ -39,19 +43,99 @@ def closing(callback):
finally:
pass
-@task
-def process_media_initial(media_id):
- workbench = mgg.workbench_manager.create_workbench()
- entry = mgg.database.MediaEntry.one(
- {'_id': ObjectId(media_id)})
+################################
+# Media processing initial steps
+################################
+
+class ProcessMedia(Task):
+ """
+ Pass this entry off for processing.
+ """
+ def run(self, media_id):
+ """
+ Pass the media entry off to the appropriate processing function
+ (for now just process_image...)
+ """
+ entry = mgg.database.MediaEntry.one(
+ {'_id': ObjectId(media_id)})
+
+ # Try to process, and handle expected errors.
+ try:
+ process_image(entry)
+ except BaseProcessingFail, exc:
+ mark_entry_failed(entry[u'_id'], exc)
+ return
+
+ entry['state'] = u'processed'
+ entry.save()
+
+ def on_failure(self, exc, task_id, args, kwargs, einfo):
+ """
+ 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.
+ """
+ entry_id = args[0]
+ mark_entry_failed(entry_id, exc)
+
+
+process_media = registry.tasks[ProcessMedia.name]
+
+
+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.
+
+ Args:
+ - entry_id: The id of the media entry
+
+ """
+ # Was this a BaseProcessingFail? In other words, was this a
+ # type of error that we know how to handle?
+ if isinstance(exc, BaseProcessingFail):
+ # Looks like yes, so record information about that failure and any
+ # metadata the user might have supplied.
+ mgg.database['media_entries'].update(
+ {'_id': entry_id},
+ {'$set': {u'state': u'failed',
+ u'fail_error': exc.exception_path,
+ u'fail_metadata': exc.metadata}})
+ else:
+ # Looks like no, so just mark it as failed and don't record a
+ # failure_error (we'll assume it wasn't handled) and don't record
+ # metadata (in fact overwrite it if somehow it had previous info
+ # here)
+ mgg.database['media_entries'].update(
+ {'_id': entry_id},
+ {'$set': {u'state': u'failed',
+ u'fail_error': None,
+ u'fail_metadata': {}}})
+
+
+def process_image(entry):
+ """
+ Code to process an image
+ """
+ workbench = mgg.workbench_manager.create_workbench()
queued_filepath = entry['queued_media_file']
queued_filename = workbench.localized_file(
mgg.queue_store, queued_filepath,
'source')
- thumb = Image.open(queued_filename)
+ 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":
@@ -63,11 +147,9 @@ def process_media_initial(media_id):
with closing(thumb_file):
thumb.save(thumb_file, "JPEG", quality=90)
- """
- 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
- entry.
- """
+ # 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
+ # entry.
medium = Image.open(queued_filename)
medium_processed = False
@@ -101,8 +183,6 @@ def process_media_initial(media_id):
media_files_dict['original'] = original_filepath
if medium_processed:
media_files_dict['medium'] = medium_filepath
- entry['state'] = u'processed'
- entry.save()
# clean up workbench
workbench.destroy_self()
diff --git a/mediagoblin/process_media/errors.py b/mediagoblin/process_media/errors.py
new file mode 100644
index 00000000..f8ae9ab2
--- /dev/null
+++ b/mediagoblin/process_media/errors.py
@@ -0,0 +1,44 @@
+# 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/>.
+
+from mediagoblin.util 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" % (
+ self.__class__.__module__, self.__class__.__name__)
+
+ def __init__(self, **metadata):
+ self.metadata = metadata or {}
+
+
+class BadMediaFail(BaseProcessingFail):
+ """
+ Error that should be raised when an inappropriate file was given
+ for the media type specified.
+ """
+ general_message = _(u'Invalid file given for media type.')
diff --git a/mediagoblin/static/css/base.css b/mediagoblin/static/css/base.css
index 59c2f49d..1852b70c 100644
--- a/mediagoblin/static/css/base.css
+++ b/mediagoblin/static/css/base.css
@@ -1,12 +1,40 @@
+/* @font-face */
+
+@font-face {
+ font-family: 'Lato';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Lato Bold'), local('Lato-Bold'), url('http://themes.googleusercontent.com/static/fonts/lato/v1/wkfQbvfT_02e2IWO3yYueQ.woff') format('woff');
+}
+@font-face {
+ font-family: 'Lato';
+ font-style: italic;
+ font-weight: 400;
+ src: local('Lato Italic'), local('Lato-Italic'), url('http://themes.googleusercontent.com/static/fonts/lato/v1/oUan5VrEkpzIazlUe5ieaA.woff') format('woff');
+}
+@font-face {
+ font-family: 'Lato';
+ font-style: italic;
+ font-weight: 700;
+ src: local('Lato Bold Italic'), local('Lato-BoldItalic'), url('http://themes.googleusercontent.com/static/fonts/lato/v1/HkF_qI1x_noxlxhrhMQYED8E0i7KZn-EPnyo3HZu7kw.woff') format('woff');
+}
+@font-face {
+ font-family: 'Lato';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Lato Regular'), local('Lato-Regular'), url('http://themes.googleusercontent.com/static/fonts/lato/v1/9k-RPmcnxYEPm8CNFsH2gg.woff') format('woff');
+}
+
body {
background-color: #111;
background-image: url("../images/background.png");
- color: #999;
+ color: #C3C3C3;
font-family: sans-serif;
padding: none;
margin: 0px;
height: 100%;
font: 16px "HelveticaNeue-Light","Helvetica Neue Light","Helvetica Neue",Helvetica,Arial,sans-serif;
+ font-family:'Lato', sans-serif;
}
form {
@@ -14,37 +42,28 @@ form {
padding: 0px;
}
-/* Carter One font */
-
-@font-face {
- font-family: 'Carter One';
- font-style: normal;
- font-weight: normal;
- src: local('CarterOne'), url('http://themes.googleusercontent.com/font?kit=VjW2qt1pkqVtO22ObxgEBRsxEYwM7FgeyaSgU71cLG0') format('woff');
-}
-
/* text styles */
h1{
- font-family: 'Carter One',arial,serif;
margin-bottom: 15px;
margin-top: 15px;
color: #fff;
- font-size: 30px;
+ font-size: 1.875em;
}
h2{
+ font-size: 1.375em;
margin-top: 20px;
color: #fff;
}
h3{
- border-bottom: 1px solid #222;
- font-size: 18px;
+ border-bottom: 1px solid #333;
+ font-size: 1.125em;
}
a {
- color: #999;
+ color: #86D4B1;
}
a.highlight {
@@ -55,6 +74,11 @@ label {
font-weight: normal;
}
+input, textarea {
+ font-size:1em;
+ font-family:'Lato', sans-serif;
+}
+
/* website structure */
.mediagoblin_body {
@@ -66,10 +90,15 @@ label {
height: 36px;
padding-top: 14px;
margin-bottom: 20px;
- border-bottom: 1px solid #222222;
+ border-bottom: 1px solid #333;
+}
+
+a.mediagoblin_logo{
+ color: #fff;
+ font-weight: bold;
}
-.header_submit{
+.header_submit, .header_submit_highlight{
color: #272727;
background-color: #aaa;
background-image: -webkit-gradient(linear, left top, left bottom, from(##D2D2D2), to(#aaa));
@@ -79,22 +108,25 @@ label {
background-image: -o-linear-gradient(top, #D2D2D2, #aaa);
background-image: linear-gradient(top, #D2D2D2, #aaa);
box-shadow: 0px 0px 4px #000;
- border-radius: 5px 5px 5px 5px;
+ border-radius: 3px;
margin: 8px;
padding: 3px 8px;
text-decoration: none;
border: medium none;
- font-family: 'Carter One',arial,serif;
+ font-style: normal;
+}
+
+.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 #222222;
+ border-top: 1px solid #333;
bottom: 0px;
padding-top: 8px;
text-align: center;
- font-size: 14px;
- color: #999;
+ font-size: 0.875em;
}
.mediagoblin_content {
@@ -108,7 +140,6 @@ label {
/* common website elements */
.button {
- font-family: 'Carter One', arial, serif;
height: 32px;
min-width: 99px;
background-color: #86d4b1;
@@ -119,15 +150,16 @@ label {
background-image: -o-linear-gradient(top, #86d4b1, #62caa2);
background-image: linear-gradient(top, #86d4b1, #62caa2);
box-shadow: 0px 0px 4px #000;
- border-radius: 5px;
+ border-radius: 3px;
border: none;
color: #272727;
margin: 10px 0px 10px 15px;
- font-size: 1em;
text-align: center;
padding-left: 11px;
padding-right: 11px;
text-decoration: none;
+ font-family:'Lato', sans-serif;
+ font-size:1em;
}
.pagination{
@@ -138,13 +170,20 @@ text-align: center;
margin: 5px;
}
+.empty_space{
+ background-color: #222;
+ font-style: italic;
+ text-align: center;
+ height: 160px;
+ padding-top: 70px;
+}
+
/* forms */
.form_box {
background-color: #222;
background-image: url("../images/background_lines.png");
background-repeat: repeat-x;
- font-size: 18px;
padding-bottom: 30px;
padding-top: 30px;
margin-left: auto;
@@ -157,13 +196,8 @@ text-align: center;
background-image: url("../images/background_edit.png");
}
-.form_box h1 {
- font-size: 28px;
-}
-
.form_field_input input, .form_field_input textarea {
width: 100%;
- font-size: 18px;
}
.form_field_box {
@@ -178,7 +212,6 @@ text-align: center;
background-color: #87453b;
color: #fff;
border: none;
- font-size: 16px;
padding: 9px;
margin-top: 8px;
margin-bottom: 8px;
@@ -193,7 +226,7 @@ text-align: center;
.comment_author {
margin-bottom: 40px;
padding-top: 4px;
- font-size: 14px;
+ font-size: 0.9em;
}
.comment_content p {
@@ -205,17 +238,26 @@ text-align: center;
.media_thumbnail {
padding: 0px;
width: 180px;
- height: 180px;
overflow: hidden;
float: left;
margin: 0px 4px 10px 4px;
text-align: center;
+ font-size: 0.875em;
+}
+
+.media_thumbnail a {
+ color: #eee;
+ text-decoration: none;
}
/* media detail */
-.media_image_container {
- text-align: center;
+h2.media_title{
+ margin-bottom: 0px;
+}
+
+p.media_uploader{
+ font-size: 0.9em;
}
/* icons */
@@ -232,10 +274,9 @@ img.media_icon{
display: block;
float: left;
text-align: center;
- background-color: #222;
+ background-color: #333;
text-decoration: none;
padding: 12px 0pt;
- font-family: 'Carter One', arial, serif;
font-size: 2em;
margin: 0 0 20px
}
@@ -291,3 +332,15 @@ ul.mediaentry_tags li {
margin: 0px 5px 0px 0px;
padding: 0px;
}
+
+
+/* media processing panel */
+
+table.media_panel {
+ width: 100%;
+}
+
+table.media_panel th {
+ font-weight: bold;
+ padding-bottom: 4px;
+}
diff --git a/mediagoblin/static/images/404.png b/mediagoblin/static/images/404.png
new file mode 100644
index 00000000..78d746ba
--- /dev/null
+++ b/mediagoblin/static/images/404.png
Binary files differ
diff --git a/mediagoblin/static/images/frontpage_image.png b/mediagoblin/static/images/frontpage_image.png
new file mode 100644
index 00000000..689eb2c2
--- /dev/null
+++ b/mediagoblin/static/images/frontpage_image.png
Binary files differ
diff --git a/mediagoblin/static/images/goblin.ico b/mediagoblin/static/images/goblin.ico
new file mode 100644
index 00000000..f2e7152f
--- /dev/null
+++ b/mediagoblin/static/images/goblin.ico
Binary files differ
diff --git a/mediagoblin/static/images/goblin.png b/mediagoblin/static/images/goblin.png
new file mode 100644
index 00000000..0a3ad22e
--- /dev/null
+++ b/mediagoblin/static/images/goblin.png
Binary files differ
diff --git a/mediagoblin/static/images/icon_feed.png b/mediagoblin/static/images/icon_feed.png
index 11e5b1e7..81889473 100644
--- a/mediagoblin/static/images/icon_feed.png
+++ b/mediagoblin/static/images/icon_feed.png
Binary files differ
diff --git a/mediagoblin/static/images/logo.png b/mediagoblin/static/images/logo.png
index cf28a6d4..019ec5ec 100644
--- a/mediagoblin/static/images/logo.png
+++ b/mediagoblin/static/images/logo.png
Binary files differ
diff --git a/mediagoblin/storage.py b/mediagoblin/storage.py
index e449eda3..d484be1f 100644
--- a/mediagoblin/storage.py
+++ b/mediagoblin/storage.py
@@ -15,7 +15,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
-import re
import shutil
import urlparse
import uuid
@@ -286,6 +285,145 @@ class CloudFilesStorage(StorageInterface):
return self.get_file(filepath).public_uri()
+class MountStorage(StorageInterface):
+ """
+ Experimental "Mount" virtual Storage Interface
+
+ This isn't an interface to some real storage, instead it's a
+ redirecting interface, that redirects requests to other
+ "StorageInterface"s.
+
+ For example, say you have the paths:
+
+ 1. ['user_data', 'cwebber', 'avatar.jpg']
+ 2. ['user_data', 'elrond', 'avatar.jpg']
+ 3. ['media_entries', '34352f304c3f4d0ad8ad0f043522b6f2', 'thumb.jpg']
+
+ You could mount media_entries under CloudFileStorage and user_data
+ under BasicFileStorage. Then 1 would be passed to
+ BasicFileStorage under the path ['cwebber', 'avatar.jpg'] and 3
+ would be passed to CloudFileStorage under
+ ['34352f304c3f4d0ad8ad0f043522b6f2', 'thumb.jpg'].
+
+ In other words, this is kind of like mounting /home/ and /etc/
+ under different filesystems on your operating system... but with
+ mediagoblin filestorages :)
+
+ To set this up, you currently need to call the mount() method with
+ the target path and a backend, that shall be available under that
+ target path. You have to mount things in a sensible order,
+ especially you can't mount ["a", "b"] before ["a"].
+ """
+ def __init__(self, **kwargs):
+ self.mounttab = {}
+
+ def mount(self, dirpath, backend):
+ """
+ Mount a new backend under dirpath
+ """
+ new_ent = clean_listy_filepath(dirpath)
+
+ print "Mounting:", repr(new_ent)
+ already, rem_1, table, rem_2 = self._resolve_to_backend(new_ent, True)
+ print "===", repr(already), repr(rem_1), repr(rem_2), len(table)
+
+ assert (len(rem_2) > 0) or (None not in table), \
+ "That path is already mounted"
+ assert (len(rem_2) > 0) or (len(table)==0), \
+ "A longer path is already mounted here"
+
+ for part in rem_2:
+ table[part] = {}
+ table = table[part]
+ table[None] = backend
+
+ def _resolve_to_backend(self, filepath, extra_info = False):
+ """
+ extra_info = True is for internal use!
+
+ Normally, returns the backend and the filepath inside that backend.
+
+ With extra_info = True it returns the last directory node and the
+ remaining filepath from there in addition.
+ """
+ table = self.mounttab
+ filepath = filepath[:]
+ res_fp = None
+ while True:
+ new_be = table.get(None)
+ if (new_be is not None) or res_fp is None:
+ res_be = new_be
+ res_fp = filepath[:]
+ res_extra = (table, filepath[:])
+ # print "... New res: %r, %r, %r" % (res_be, res_fp, res_extra)
+ if len(filepath) == 0:
+ break
+ query = filepath.pop(0)
+ entry = table.get(query)
+ if entry is not None:
+ table = entry
+ res_extra = (table, filepath[:])
+ else:
+ break
+ if extra_info:
+ return (res_be, res_fp) + res_extra
+ else:
+ return (res_be, res_fp)
+
+ def resolve_to_backend(self, filepath):
+ backend, filepath = self._resolve_to_backend(filepath)
+ if backend is None:
+ raise Error("Path not mounted")
+ return backend, filepath
+
+ def __repr__(self, table = None, indent = []):
+ res = []
+ if table is None:
+ res.append("MountStorage<")
+ table = self.mounttab
+ v = table.get(None)
+ if v:
+ res.append(" " * len(indent) + repr(indent) + ": " + repr(v))
+ for k, v in table.iteritems():
+ if k == None:
+ continue
+ res.append(" " * len(indent) + repr(k) + ":")
+ res += self.__repr__(v, indent + [k])
+ if table is self.mounttab:
+ res.append(">")
+ return "\n".join(res)
+ else:
+ return res
+
+ def file_exists(self, filepath):
+ backend, filepath = self.resolve_to_backend(filepath)
+ return backend.file_exists(filepath)
+
+ def get_file(self, filepath, mode='r'):
+ backend, filepath = self.resolve_to_backend(filepath)
+ return backend.get_file(filepath, mode)
+
+ def delete_file(self, filepath):
+ backend, filepath = self.resolve_to_backend(filepath)
+ return backend.delete_file(filepath)
+
+ def file_url(self, filepath):
+ backend, filepath = self.resolve_to_backend(filepath)
+ return backend.file_url(filepath)
+
+ def get_local_path(self, filepath):
+ backend, filepath = self.resolve_to_backend(filepath)
+ return backend.get_local_path(filepath)
+
+ def copy_locally(self, filepath, dest_path):
+ """
+ Need to override copy_locally, because the local_storage
+ attribute is not correct.
+ """
+ backend, filepath = self.resolve_to_backend(filepath)
+ backend.copy_locally(filepath, dest_path)
+
+
###########
# Utilities
###########
@@ -317,41 +455,34 @@ def clean_listy_filepath(listy_filepath):
return cleaned_filepath
-def storage_system_from_config(paste_config, storage_prefix):
+def storage_system_from_config(config_section):
"""
- Utility for setting up a storage system from the paste app config.
+ Utility for setting up a storage system from a config section.
- Note that a special argument may be passed in to the paste_config
- which is "${storage_prefix}_storage_class" which will provide an
+ Note that a special argument may be passed in to
+ the config_section which is "storage_class" which will provide an
import path to a storage system. This defaults to
"mediagoblin.storage:BasicFileStorage" if otherwise undefined.
Arguments:
- - paste_config: dictionary of config parameters
- - storage_prefix: the storage system we're setting up / will be
- getting keys/arguments from. For example 'publicstore' will
- grab all arguments that are like 'publicstore_FOO'.
+ - config_section: dictionary of config parameters
Returns:
An instantiated storage system.
Example:
storage_system_from_config(
- {'publicstore_base_url': '/media/',
- 'publicstore_base_dir': '/var/whatever/media/'},
- 'publicstore')
+ {'base_url': '/media/',
+ 'base_dir': '/var/whatever/media/'})
Will return:
BasicFileStorage(
base_url='/media/',
base_dir='/var/whatever/media')
"""
- prefix_re = re.compile('^%s_(.+)$' % re.escape(storage_prefix))
-
- config_params = dict(
- [(prefix_re.match(key).groups()[0], value)
- for key, value in paste_config.iteritems()
- if prefix_re.match(key)])
+ # This construct is needed, because dict(config) does
+ # not replace the variables in the config items.
+ config_params = dict(config_section.iteritems())
if 'storage_class' in config_params:
storage_class = config_params['storage_class']
diff --git a/mediagoblin/submit/forms.py b/mediagoblin/submit/forms.py
index f02c95a6..4519b057 100644
--- a/mediagoblin/submit/forms.py
+++ b/mediagoblin/submit/forms.py
@@ -16,15 +16,17 @@
import wtforms
+
from mediagoblin.util import tag_length_validator
+from mediagoblin.util import fake_ugettext_passthrough as _
class SubmitStartForm(wtforms.Form):
+ file = wtforms.FileField(_('File'))
title = wtforms.TextField(
- 'Title',
+ _('Title'),
[wtforms.validators.Length(min=0, max=500)])
description = wtforms.TextAreaField('Description of this work')
- file = wtforms.FileField('File')
tags = wtforms.TextField(
- 'Tags',
+ _('Tags'),
[tag_length_validator])
diff --git a/mediagoblin/submit/views.py b/mediagoblin/submit/views.py
index 87e57dda..4481adeb 100644
--- a/mediagoblin/submit/views.py
+++ b/mediagoblin/submit/views.py
@@ -14,18 +14,21 @@
# 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 mediagoblin.mg_globals as mg_globals
+import uuid
from os.path import splitext
from cgi import FieldStorage
-from string import split
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.decorators import require_active_login
from mediagoblin.submit import forms as submit_forms, security
-from mediagoblin.process_media import process_media_initial
+from mediagoblin.process_media import process_media, mark_entry_failed
from mediagoblin.messages import add_message, SUCCESS
@@ -41,15 +44,16 @@ def submit_start(request):
and isinstance(request.POST['file'], FieldStorage)
and request.POST['file'].file):
submit_form.file.errors.append(
- u'You must provide a file.')
+ _(u'You must provide a file.'))
elif not security.check_filetype(request.POST['file']):
submit_form.file.errors.append(
- u'The file doesn\'t seem to be an image!')
+ _(u"The file doesn't seem to be an image!"))
else:
filename = request.POST['file'].filename
# create entry and save in database
entry = request.db.MediaEntry()
+ entry['_id'] = ObjectId()
entry['title'] = (
request.POST['title']
or unicode(splitext(filename)[0]))
@@ -65,10 +69,6 @@ def submit_start(request):
entry['tags'] = convert_to_tag_list_of_dicts(
request.POST.get('tags'))
- # Save, just so we can get the entry id for the sake of using
- # it to generate the file path
- entry.save(validate=False)
-
# Generate a slug from the title
entry.generate_slug()
@@ -87,12 +87,39 @@ def submit_start(request):
# Add queued filename to the entry
entry['queued_media_file'] = queue_filepath
- entry.save(validate=True)
- # queue it for processing
- process_media_initial.delay(unicode(entry['_id']))
+ # We generate this ourselves so we know what the taks id is for
+ # retrieval later.
+ # (If we got it off the task's auto-generation, there'd be a risk of
+ # a race condition when we'd save after sending off the task)
+ task_id = unicode(uuid.uuid4())
+ entry['queued_task_id'] = task_id
+
+ # Save now so we have this data before kicking off processing
+ entry.save(validate=True)
- add_message(request, SUCCESS, 'Woohoo! Submitted!')
+ # Pass off to processing
+ #
+ # (... don't change entry after this point to avoid race
+ # conditions with changes to the document via processing code)
+ try:
+ process_media.apply_async(
+ [unicode(entry['_id'])], {},
+ task_id=task_id)
+ except BaseException as exc:
+ # The purpose of this section is because when running in "lazy"
+ # or always-eager-with-exceptions-propagated celery mode that
+ # the failure handling won't happen on Celery end. Since we
+ # expect a lot of users to run things in this way we have to
+ # capture stuff here.
+ #
+ # ... not completely the diaper pattern because the exception is
+ # re-raised :)
+ mark_entry_failed(entry[u'_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'])
@@ -100,4 +127,5 @@ def submit_start(request):
return render_to_response(
request,
'mediagoblin/submit/start.html',
- {'submit_form': submit_form})
+ {'submit_form': submit_form,
+ 'app_config': mg_globals.app_config})
diff --git a/mediagoblin/templates/mediagoblin/404.html b/mediagoblin/templates/mediagoblin/404.html
new file mode 100644
index 00000000..5af46a87
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/404.html
@@ -0,0 +1,34 @@
+{#
+# 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/>.
+#}
+{% extends "mediagoblin/base.html" %}
+
+{% block mediagoblin_content %}
+ <h1>{% trans %}Oops!{% endtrans %}</h1>
+
+ <div class="grid_8 alpha">
+ <p>{% trans %}There doesn't seem to be a page at this address. Sorry!{% endtrans %}</p>
+ <p>
+ {%- trans %}If you're sure the address is correct, maybe the page you're looking for has been moved or deleted.{% endtrans -%}
+ </p>
+ </div>
+
+ <div class="grid_8 omega">
+ <img src="{{ request.staticdirect('/images/404.png') }}"
+ alt="{% trans %}Image of 404 goblin stressing out{% endtrans %}" />
+ </div>
+{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/auth/login.html b/mediagoblin/templates/mediagoblin/auth/login.html
index e25783ea..afbecf20 100644
--- a/mediagoblin/templates/mediagoblin/auth/login.html
+++ b/mediagoblin/templates/mediagoblin/auth/login.html
@@ -23,20 +23,27 @@
<form action="{{ request.urlgen('mediagoblin.auth.login') }}"
method="POST" enctype="multipart/form-data">
<div class="grid_6 prefix_1 suffix_1 form_box">
- <h1>Log in</h1>
+ <h1>{% trans %}Log in{% endtrans %}</h1>
{% if login_failed %}
- <div class="form_field_error">Login failed!</div>
+ <div class="form_field_error">
+ {% trans %}Logging in failed!{% endtrans %}
+ </div>
{% endif %}
{{ wtforms_util.render_divs(login_form) }}
<div class="form_submit_buttons">
- <input type="submit" value="submit" class="button"/>
+ <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>Don't have an account yet?<br /><a href="{{ request.urlgen('mediagoblin.auth.register') }}">Create one here!</a></p>
+ <p>
+ {% trans %}Don't have an account yet?{% endtrans %}
+ <br />
+ <a href="{{ request.urlgen('mediagoblin.auth.register') }}">
+ {%- trans %}Create one here!{% endtrans %}</a>
+ </p>
{% endif %}
</div>
</form>
diff --git a/mediagoblin/templates/mediagoblin/auth/register.html b/mediagoblin/templates/mediagoblin/auth/register.html
index f77b3782..d9eedc4a 100644
--- a/mediagoblin/templates/mediagoblin/auth/register.html
+++ b/mediagoblin/templates/mediagoblin/auth/register.html
@@ -24,10 +24,11 @@
<form action="{{ request.urlgen('mediagoblin.auth.register') }}"
method="POST" enctype="multipart/form-data">
<div class="grid_6 prefix_1 suffix_1 form_box">
- <h1>Create an account!</h1>
+ <h1>{% trans %}Create an account!{% endtrans %}</h1>
{{ wtforms_util.render_divs(register_form) }}
<div class="form_submit_buttons">
- <input type="submit" value="submit" class="button" />
+ <input type="submit" value="{% trans %}Create{% endtrans %}"
+ class="button" />
</div>
</div>
</form>
diff --git a/mediagoblin/templates/mediagoblin/auth/resent_verification_email.html b/mediagoblin/templates/mediagoblin/auth/resent_verification_email.html
index da3a9e99..8fd80ee9 100644
--- a/mediagoblin/templates/mediagoblin/auth/resent_verification_email.html
+++ b/mediagoblin/templates/mediagoblin/auth/resent_verification_email.html
@@ -19,6 +19,6 @@
{% block mediagoblin_content %}
<p>
- Resent your verification email.
+ {% trans %}Resent your verification email.{% endtrans %}
</p>
{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/auth/verification_email.txt b/mediagoblin/templates/mediagoblin/auth/verification_email.txt
index 7863374d..32053101 100644
--- a/mediagoblin/templates/mediagoblin/auth/verification_email.txt
+++ b/mediagoblin/templates/mediagoblin/auth/verification_email.txt
@@ -14,9 +14,13 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#}
+-#}
+
+{% trans username=username, verification_url=verification_url|safe -%}
Hi {{ username }},
-to activate your GNU MediaGoblin account, open the following URL in your web browser
+to activate your GNU MediaGoblin account, open the following URL in
+your web browser:
-{{ verification_url|safe }}
+{{ verification_url }}
+{%- endtrans %}
diff --git a/mediagoblin/templates/mediagoblin/base.html b/mediagoblin/templates/mediagoblin/base.html
index 4da685f9..32d5a5d2 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 %}GNU MediaGoblin{% endblock title %}</title>
+ <title>{% block title %}{% trans %}GNU MediaGoblin{% endtrans %}{% endblock title %}</title>
<link rel="stylesheet" type="text/css"
href="{{ request.staticdirect('/css/extlib/reset.css') }}"/>
<link rel="stylesheet" type="text/css"
@@ -28,6 +28,8 @@
href="{{ request.staticdirect('/css/extlib/960_16_col.css') }}"/>
<link rel="stylesheet" type="text/css"
href="{{ request.staticdirect('/css/base.css') }}"/>
+ <link rel="shortcut icon"
+ href="{{ request.staticdirect('/images/goblin.ico') }}" />
{% block mediagoblin_head %}
{% endblock mediagoblin_head %}
</head>
@@ -40,15 +42,14 @@
<div class="grid_16 mediagoblin_header">
{% block mediagoblin_logo %}
<a class="mediagoblin_logo"
- href="{{ request.urlgen('index') }}">
- <img src="{{ request.staticdirect('/images/logo.png') }}"
- alt="Mediagoblin logo" />
- </a>
+ href="{{ request.urlgen('index') }}"
+ ><img src="{{ request.staticdirect('/images/logo.png') }}"
+ alt="{% trans %}MediaGoblin logo{% endtrans %}" /></a>
{% endblock %}
{% if request.user and request.user['status'] == 'active' %}
<a class="header_submit"
href="{{ request.urlgen('mediagoblin.submit.start') }}">
- Submit media
+ {% trans %}Submit media{% endtrans %}
</a>
{% endif %}
{% block mediagoblin_header_title %}{% endblock %}
@@ -59,17 +60,17 @@
<a href="{{ request.urlgen('mediagoblin.user_pages.user_home',
user=request.user['username']) }}"
class="header_submit">
- verify your email!</a>
+ {% 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') }}">logout</a>)
+ (<a href="{{ request.urlgen('mediagoblin.auth.logout') }}">log out</a>)
{% else %}
<a href="{{ request.urlgen('mediagoblin.auth.login') }}">
- Login</a>
+ {% trans %}Log in{% endtrans %}</a>
{% endif %}
</div>
</div>
@@ -85,7 +86,9 @@
{% block mediagoblin_footer %}
<div class="container_16">
<div class="grid_16 mediagoblin_footer">
- Powered by <a href="http://mediagoblin.org">MediaGoblin</a>, a <a href="http://gnu.org/">GNU project</a>
+ {% trans -%}
+ Powered by <a href="http://mediagoblin.org">MediaGoblin</a>, a <a href="http://gnu.org/">GNU project</a>
+ {%- endtrans %}
</div>
</div>
{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/edit/attachments.html b/mediagoblin/templates/mediagoblin/edit/attachments.html
new file mode 100644
index 00000000..2f319dbb
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/edit/attachments.html
@@ -0,0 +1,55 @@
+{#
+# 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/>.
+#}
+{% extends "mediagoblin/base.html" %}
+
+{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
+{% block mediagoblin_content %}
+ <form action="{{ request.urlgen('mediagoblin.edit.attachments',
+ user= media.uploader().username,
+ media= media._id) }}"
+ method="POST" enctype="multipart/form-data">
+ <div class="grid_8 prefix_1 suffix_1 edit_box form_box">
+ <h1>Editing attachments for {{ media.title }}</h1>
+ <div style="text-align: center;" >
+ <img src="{{ request.app.public_store.file_url(
+ media['media_files']['thumb']) }}" />
+ </div>
+
+ {% if media.attachment_files|count %}
+ <h2>Attachments</h2>
+ <ul>
+ {% for attachment in media.attachment_files %}
+ <li>
+ <a target="_blank" href="{{ request.app.public_store.file_url(
+ attachment['filepath']) }}">
+ {{ attachment.name -}}
+ </a><br />
+ </li>
+ {% endfor %}
+ </ul>
+ {% endif %}
+
+ <h2>Add attachment</h2>
+ {{ wtforms_util.render_divs(form) }}
+ <div class="form_submit_buttons">
+ <a href="{{ media.url_for_self(request.urlgen) }}">Cancel</a>
+ <input type="submit" value="Save changes" class="button" />
+ </div>
+ </div>
+ </form>
+{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/edit/edit.html b/mediagoblin/templates/mediagoblin/edit/edit.html
index d19034cb..3dc170c8 100644
--- a/mediagoblin/templates/mediagoblin/edit/edit.html
+++ b/mediagoblin/templates/mediagoblin/edit/edit.html
@@ -26,15 +26,15 @@
media= media._id) }}"
method="POST" enctype="multipart/form-data">
<div class="grid_8 prefix_1 suffix_1 edit_box form_box">
- <h1>Editing {{ media.title }}</h1>
+ <h1>{% trans media_title=media.title %}Editing {{ media_title }}{% endtrans %}</h1>
<div style="text-align: center;" >
<img src="{{ request.app.public_store.file_url(
media['media_files']['thumb']) }}" />
</div>
{{ 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" />
+ <a href="{{ media.url_for_self(request.urlgen) }}">{% trans %}Cancel{% endtrans %}</a>
+ <input type="submit" value="{% trans %}Save changes{% endtrans %}" class="button" />
</div>
</div>
</form>
diff --git a/mediagoblin/templates/mediagoblin/edit/edit_profile.html b/mediagoblin/templates/mediagoblin/edit/edit_profile.html
index a11b86d7..bed5e0ca 100644
--- a/mediagoblin/templates/mediagoblin/edit/edit_profile.html
+++ b/mediagoblin/templates/mediagoblin/edit/edit_profile.html
@@ -25,10 +25,14 @@
user['username'] }}"
method="POST" enctype="multipart/form-data">
<div class="grid_8 prefix_1 suffix_1 edit_box form_box">
- <h1>Editing {{ user['username'] }}'s profile</h1>
+ <h1>
+ {%- trans username=user['username'] -%}
+ Editing {{ username }}'s profile
+ {%- endtrans %}
+ </h1>
{{ wtforms_util.render_divs(form) }}
<div class="form_submit_buttons">
- <input type="submit" value="submit" class="button" />
+ <input type="submit" value="{% trans %}Save changes{% endtrans %}" class="button" />
</div>
</div>
</form>
diff --git a/mediagoblin/templates/mediagoblin/listings/tag.html b/mediagoblin/templates/mediagoblin/listings/tag.html
index 6f10ec8d..289f44b8 100644
--- a/mediagoblin/templates/mediagoblin/listings/tag.html
+++ b/mediagoblin/templates/mediagoblin/listings/tag.html
@@ -17,6 +17,8 @@
#}
{% extends "mediagoblin/base.html" %}
+{% from "mediagoblin/utils/object_gallery.html" import object_gallery %}
+
{% block mediagoblin_head %}
<link rel="alternate" type="application/atom+xml"
href="{{ request.urlgen(
@@ -26,16 +28,17 @@
{% block mediagoblin_content -%}
<h1>
- Media tagged with: {{ tag_name }}
+ {% trans %}Media tagged with:{% endtrans %} {{ tag_name }}
</h1>
<div class="container_16 media_gallery">
- {% include "mediagoblin/utils/object_gallery.html" %}
+ {{ object_gallery(request, media_entries, pagination) }}
</div>
<div class="grid_16">
- <a href="{{ request.urlgen(
- 'mediagoblin.listings.tag_atom_feed',
- tag=tag_slug) }}">atom feed</a>
+ {% set feed_url = request.urlgen(
+ 'mediagoblin.listings.tag_atom_feed',
+ tag=tag_slug) %}
+ {% include "mediagoblin/utils/feed_link.html" %}
</div>
{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/root.html b/mediagoblin/templates/mediagoblin/root.html
index ed7b931f..086c99c4 100644
--- a/mediagoblin/templates/mediagoblin/root.html
+++ b/mediagoblin/templates/mediagoblin/root.html
@@ -17,27 +17,36 @@
#}
{% extends "mediagoblin/base.html" %}
-{% block mediagoblin_content %}
- <h1>{% trans %}Welcome to GNU MediaGoblin!{% endtrans %}</h1>
+{% from "mediagoblin/utils/object_gallery.html" import object_gallery %}
+{% block mediagoblin_content %}
{% if request.user %}
- <p>
- <a href="{{ request.urlgen('mediagoblin.submit.start') }}">Submit an item</a>
- </p>
+ <h1>Explore</h1>
{% else %}
- <p>
- If you have an account, you can
- <a href="{{ request.urlgen('mediagoblin.auth.login') }}">Login</a>.
- </p>
- {% if allow_registration %}
- <p>
- If you don't have an account, please
- <a href="{{ request.urlgen('mediagoblin.auth.register') }}">Register</a>.
- </p>
- {% endif %}
- {% endif %}
+ <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>
- {# temporarily, an "image gallery" that isn't one really ;) #}
+ {% if allow_registration %}
+ <p>Excited to join us? To add your own media, make collections and save favorites...<p>
+ <a class="header_submit_highlight" href="{{ request.urlgen('mediagoblin.auth.register') }}">Create a free account</a> or
+ <a class="header_submit" href="http://wiki.mediagoblin.org/HackingHowto">Set up MediaGoblin on your own server</a>
+ {% endif %}
+ </div>
- {% include "mediagoblin/utils/object_gallery.html" %}
+ <div class="grid_5 omega">
+ <img src="{{ request.staticdirect('/images/frontpage_image.png') }}" />
+ </div>
+
+ <div class="clear"></div>
+ {% endif %}
+ <h2>Most recent media</h2>
+ {{ object_gallery(request, media_entries, pagination) }}
{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/submit/start.html b/mediagoblin/templates/mediagoblin/submit/start.html
index 6d00510c..3a40850d 100644
--- a/mediagoblin/templates/mediagoblin/submit/start.html
+++ b/mediagoblin/templates/mediagoblin/submit/start.html
@@ -23,13 +23,10 @@
<form action="{{ request.urlgen('mediagoblin.submit.start') }}"
method="POST" enctype="multipart/form-data">
<div class="grid_8 prefix_1 suffix_1 form_box">
- <h1>Submit yer media</h1>
- {{ wtforms_util.render_field_div(submit_form.file) }}
- {{ wtforms_util.render_field_div(submit_form.title) }}
- {{ wtforms_util.render_textarea_div(submit_form.description) }}
- {{ wtforms_util.render_field_div(submit_form.tags) }}
+ <h1>{% trans %}Submit yer media{% endtrans %}</h1>
+ {{ wtforms_util.render_divs(submit_form) }}
<div class="form_submit_buttons">
- <input type="submit" value="Submit" class="button" />
+ <input type="submit" value="{% trans %}Submit{% endtrans %}" class="button" />
</div>
</div>
</form>
diff --git a/mediagoblin/templates/mediagoblin/user_pages/gallery.html b/mediagoblin/templates/mediagoblin/user_pages/gallery.html
index 637c892d..3a3d2373 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/gallery.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/gallery.html
@@ -17,6 +17,8 @@
#}
{% extends "mediagoblin/base.html" %}
+{% from "mediagoblin/utils/object_gallery.html" import object_gallery %}
+
{% block mediagoblin_head %}
<link rel="alternate" type="application/atom+xml"
href="{{ request.urlgen(
@@ -27,21 +29,26 @@
{% block mediagoblin_content -%}
{% if user %}
<h1>
- <a href="{{ request.urlgen(
- 'mediagoblin.user_pages.user_home',
- user=user.username) }}">{{ user.username }}</a>'s media</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>
<div class="container_16 media_gallery">
- {% include "mediagoblin/utils/object_gallery.html" %}
+ {{ object_gallery(request, media_entries, pagination) }}
</div>
+
<div class="grid_16">
- <a href={{ request.urlgen(
- 'mediagoblin.user_pages.atom_feed',
- user=user.username) }}>atom feed</a>
+ {% 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>Sorry, no such user found.<p/>
+ <p>{% trans %}Sorry, no such user found.{% endtrans %}<p/>
{% endif %}
{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html
index a1382518..0425500e 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/media.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/media.html
@@ -24,38 +24,54 @@
{% if media %}
<div class="grid_11 alpha">
<div class="media_image_container">
- <img class="media_image"
- src="{{ request.app.public_store.file_url(
- media.get_display_media(media.media_files)) }}" />
+ {% set display_media = request.app.public_store.file_url(
+ media.get_display_media(media.media_files)) %}
+
+ {# if there's a medium file size, that means the medium size
+ # isn't the original... so link to the original!
+ #}
+ {% if media['media_files'].has_key('medium') %}
+ <a href="{{ request.app.public_store.file_url(
+ media['media_files']['original']) }}">
+ <img class="media_image"
+ src="{{ display_media }}"
+ alt="Image for {{ media.title }}" />
+ </a>
+ {% else %}
+ <img class="media_image"
+ src="{{ display_media }}"
+ alt="Image for {{ media.title }}" />
+ {% endif %}
</div>
- <h2>
- {{media.title}}
+ <h2 class="media_title">
+ {{ media.title }}
</h2>
+ <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>
+ {%- endtrans %}
+ </p>
+
{% autoescape False %}
<p>{{ media.description_html }}</p>
{% endautoescape %}
- <p>
- &mdash;&nbsp;uploaded on
- {{ "%4d-%02d-%02d"|format(media.created.year,
- media.created.month, media.created.day) }}
- by
- <a href="{{ request.urlgen('mediagoblin.user_pages.user_home',
- user= media.uploader().username) }}">
- {{- media.uploader().username }}</a>
- </p>
<br />
+ <h3>{% trans %}Comments{% endtrans %}</h3>
- <h3>Comments</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_field_div(comment_form.comment_content) }}
+ {{ wtforms_util.render_divs(comment_form) }}
<div class="form_submit_buttons">
- <input type="submit" value="Post comment!" class="button" />
+ <input type="submit" value="{% trans %}Post comment!{% endtrans %}" class="button" />
</div>
</form>
{% endif %}
@@ -69,26 +85,23 @@
{% else %}
<div class="comment_wrapper" id="comment-{{ comment['_id'] }}">
{% endif %}
+
<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',
- user = comment_author['username']) }}">
- {{ comment_author['username'] }}</a> at
- <!--</div>
- <div class="comment_datetime">-->
+ 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'],
user = media.uploader().username,
media = media._id) }}#comment">
- {{ "%4d-%02d-%02d %02d:%02d"|format(comment.created.year,
- comment.created.month,
- comment.created.day,
- comment.created.hour,
- comment.created.minute) }}
+ {{ comment.created.strftime("%Y-%m-%d %I:%M%p") }}
</a>
</div>
</div>
@@ -103,30 +116,51 @@
<div class="grid_5 omega">
{% include "mediagoblin/utils/prev_next.html" %}
- <h3>Sidebar content here!</h3>
-
- <p>
- {% if media['uploader'] == request.user['_id'] or
- request.user['is_admin'] %}
- <p>
- <a href="{{ request.urlgen('mediagoblin.edit.edit_media',
- user= media.uploader().username,
- media= media._id) }}"
- ><img src="{{ request.staticdirect('/images/icon_edit.png') }}"
- class="media_icon" />edit</a>
- </p>
- <p>
- <img src="{{ request.staticdirect('/images/icon_delete.png') }}"
- class="media_icon" />delete
- </p>
- {% endif %}
- </p>
+
+ {% if media['uploader'] == request.user['_id'] or
+ request.user['is_admin'] %}
+ <h3>Temporary button holder</h3>
+ <p>
+ <a href="{{ request.urlgen('mediagoblin.edit.edit_media',
+ user= media.uploader().username,
+ media= media._id) }}"
+ ><img src="{{ request.staticdirect('/images/icon_edit.png') }}"
+ class="media_icon" />edit</a>
+ </p>
+ <p>
+ <img src="{{ request.staticdirect('/images/icon_delete.png') }}"
+ class="media_icon" />{% trans %}delete{% endtrans %}
+ </p>
+ {% endif %}
+
+ {% if media.attachment_files|count %}
+ <h3>Attachments</h3>
+ <ul>
+ {% for attachment in media.attachment_files %}
+ <li>
+ <a href="{{ request.app.public_store.file_url(attachment.filepath) }}">
+ {{ attachment.name }}
+ </a>
+ </li>
+ {% endfor %}
+ </ul>
+ {% endif %}
+
+ {% if app_config['allow_attachments']
+ and (media['uploader'] == request.user['_id']
+ or request.user['is_admin']) %}
+ <p>
+ <a href="{{ request.urlgen('mediagoblin.edit.attachments',
+ user=media.uploader().username,
+ media=media._id) }}">Add attachment</a>
+ </p>
+ {% endif %}
{% if media.tags %}
{% include "mediagoblin/utils/tags.html" %}
{% endif %}
</div>
{% else %}
- <p>Sorry, no such media found.<p/>
+ <p>{% trans %}Sorry, no such media found.{% endtrans %}<p/>
{% endif %}
{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/user_pages/processing_panel.html b/mediagoblin/templates/mediagoblin/user_pages/processing_panel.html
new file mode 100644
index 00000000..abc7efd3
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/user_pages/processing_panel.html
@@ -0,0 +1,67 @@
+{#
+# 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/>.
+#}
+{% extends "mediagoblin/base.html" %}
+
+{% block mediagoblin_content %}
+
+<h1>{% trans %}Media processing panel{% endtrans %}</h1>
+
+<p>
+ {% trans %}You can track the state of media being processed for your gallery here.{% endtrans %}
+</p>
+
+<h2>{% trans %}Media in-processing{% endtrans %}</h2>
+
+{% if processing_entries.count() %}
+ <table class="media_panel processing">
+ <tr>
+ <th>Title</th>
+ <th>When submitted</th>
+ <th>Status</th>
+ </tr>
+ {% for media_entry in processing_entries %}
+ <tr>
+ <td>{{ media_entry['title'] }}</td>
+ <td>{{ media_entry['created'].strftime("%m-%d-%Y %I:%M %p") }}</td>
+ <td></td>
+ </tr>
+ {% endfor %}
+ </table>
+{% else %}
+ <p><i>{% trans %}No media in-processing{% endtrans %}</i></p>
+{% endif %}
+
+{% if failed_entries.count() %}
+ <h2>{% trans %}These uploads failed to process:{% endtrans %}</h2>
+
+ <table class="media_panel failed">
+ <tr>
+ <th>Title</th>
+ <th>When submitted</th>
+ <th>Reason for failure</th>
+ </tr>
+ {% for media_entry in failed_entries %}
+ <tr>
+ <td>{{ media_entry['title'] }}</td>
+ <td>{{ media_entry['created'].strftime("%m-%d-%Y %I:%M %p") }}</td>
+ <td>{{ media_entry.get_fail_exception().general_message }}</td>
+ </tr>
+ {% endfor %}
+ </table>
+{% endif %}
+{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/user_pages/user.html b/mediagoblin/templates/mediagoblin/user_pages/user.html
index 76cf36be..e7fd9692 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/user.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/user.html
@@ -17,6 +17,8 @@
#}
{% extends "mediagoblin/base.html" %}
+{% from "mediagoblin/utils/object_gallery.html" import object_gallery %}
+
{% block mediagoblin_head %}
<link rel="alternate" type="application/atom+xml"
href="{{ request.urlgen(
@@ -27,66 +29,128 @@
{% block mediagoblin_content -%}
{# If no user... #}
{% if not user %}
- <p>Sorry, no such user found.<p/>
+ <p>{% trans %}Sorry, no such user found.{% endtrans %}<p/>
{# User exists, but needs verification #}
{% elif user.status == "needs_email_verification" %}
{% if user == request.user %}
{# this should only be visible when you are this user #}
<div class="grid_6 prefix_1 suffix_1 form_box">
- <h1>Verification needed</h1>
+ <h1>{% trans %}Email verification needed{% endtrans %}</h1>
- <p>Almost done! Your account still needs to be verified.</p>
<p>
- An email should arrive in a few moments with instructions
- on how to do so.
+ {% trans -%}
+ Almost done! Your account still needs to be activated.
+ {%- endtrans %}
+ </p>
+ <p>
+ {% trans -%}
+ An email should arrive in a few moments with instructions on how to do so.
+ {%- endtrans %}
</p>
- <p>In case it doesn't:</p>
+ <p>{% trans %}In case it doesn't:{% endtrans %}</p>
<a href="{{ request.urlgen('mediagoblin.auth.resend_verification') }}"
- class="button">Resend verification email</a>
+ class="button">{% trans %}Resend verification email{% endtrans %}</a>
</div>
{% else %}
{# if the user is not you, but still needs to verify their email #}
<div class="grid_6 prefix_1 suffix_1 form_box">
- <h1>Verification needed</h1>
+ <h1>{% trans %}Email verification needed{% endtrans %}</h1>
<p>
- Someone has registered an account with this username, but it
- still has to be verified.
+ {% trans -%}
+ Someone has registered an account with this username, but it still has to be activated.
+ {%- endtrans %}
</p>
<p>
- If you are that person but you've lost your verification
- email, you can
- <a href="{{ request.urlgen('mediagoblin.auth.login') }}">log in</a>
- and resend it.
+ {% trans login_url=request.urlgen('mediagoblin.auth.login') -%}
+ If you are that person but you've lost your verification email, you can <a href="{{ login_url }}">log in</a> and resend it.
+ {%- endtrans %}
</p>
</div>
{% endif %}
{# Active(?) (or at least verified at some point) user, horray! #}
{% else %}
- <h1>{{ user.username }}'s profile</h1>
+ <h1>
+ {%- trans username=user.username %}{{ username }}'s profile{% endtrans -%}
+ </h1>
- <div class="grid_6 alpha">
- {% include "mediagoblin/utils/profile.html" %}
- {% if request.user['_id'] == user['_id'] or request.user['is_admin'] %}
- <a href="{{ request.urlgen('mediagoblin.edit.profile') }}?username={{
- user.username }}">Edit profile</a>
+ {% if not user['url'] and not user['profile'] %}
+ {% 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">
+ {%- trans %}Edit profile{% endtrans -%}
+ </a>
+ </div>
+ {% else %}
+ <div class="grid_6 alpha empty_space">
+ <p>
+ {% trans -%}
+ This user hasn't filled in their profile (yet).
+ {%- endtrans %}
+ </p>
+ </div>
{% endif %}
- </div>
-
- <div class="grid_10 omega">
- {% set pagination_base_url = user_gallery_url %}
- {% include "mediagoblin/utils/object_gallery.html" %}
- <div class="clear"></div>
- <p><a href="{{ user_gallery_url }}">View all of {{ user.username }}'s media</a></p>
- <a href={{ request.urlgen(
- 'mediagoblin.user_pages.atom_feed',
- user=user.username) }}>atom feed</a>
- </div>
+ {% else %}
+ <div class="grid_6 alpha">
+ {% include "mediagoblin/utils/profile.html" %}
+ {% 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 -%}
+ </a>
+ {% endif %}
+ </div>
+ {% endif %}
+ {% if media_entries.count() %}
+ <div class="grid_10 omega">
+ {{ object_gallery(request, media_entries, pagination,
+ pagination_base_url=user_gallery_url, col_number=3) }}
+ {% include "mediagoblin/utils/object_gallery.html" %}
+ <div class="clear"></div>
+ <p>
+ <a href="{{ user_gallery_url }}">
+ {% trans username=user.username -%}
+ View all of {{ username }}'s media{% endtrans -%}
+ </a>
+ </p>
+ {% set feed_url = request.urlgen(
+ 'mediagoblin.user_pages.atom_feed',
+ user=user.username) %}
+ {% include "mediagoblin/utils/feed_link.html" %}
+ </div>
+ {% else %}
+ {% 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"
+ href="{{ request.urlgen('mediagoblin.submit.start') }}">
+ {%- trans %}Add media{% endtrans -%}
+ </a>
+ </div>
+ {% else %}
+ <div class="grid_10 omega empty_space">
+ <p>
+ {% trans -%}
+ There doesn't seem to be any media here yet...
+ {%- endtrans %}
+ </p>
+ </div>
+ {% endif %}
+ {% endif %}
<div class="clear"></div>
{% endif %}
{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/utils/feed_link.html b/mediagoblin/templates/mediagoblin/utils/feed_link.html
new file mode 100644
index 00000000..c4036bf3
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/utils/feed_link.html
@@ -0,0 +1,23 @@
+{#
+# 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/>.
+#}
+
+<a href="{{ feed_url }}">
+ <img src="{{ request.staticdirect('/images/icon_feed.png') }}"
+ class="media_icon" alt="{% trans %}feed icon{% endtrans %}" />
+</a>
+<a href="{{ feed_url }}">{%- trans %}Atom feed{% endtrans -%}</a>
diff --git a/mediagoblin/templates/mediagoblin/utils/object_gallery.html b/mediagoblin/templates/mediagoblin/utils/object_gallery.html
index 03b85b17..34eb7dbc 100644
--- a/mediagoblin/templates/mediagoblin/utils/object_gallery.html
+++ b/mediagoblin/templates/mediagoblin/utils/object_gallery.html
@@ -18,15 +18,47 @@
{% from "mediagoblin/utils/pagination.html" import render_pagination %}
-{% block object_gallery_content -%}
- {% if media_entries and media_entries.count() %}
- {% for entry in media_entries %}
- <div class="media_thumbnail">
- <a href="{{ entry.url_for_self(request.urlgen) }}">
- <img src="{{ request.app.public_store.file_url(
- entry['media_files']['thumb']) }}" /></a>
- </div>
+{% macro media_grid(request, media_entries, col_number=5) %}
+ <table class="thumb_gallery">
+ {% for row in gridify_cursor(media_entries, col_number) %}
+ <tr class="thumb_row
+ {%- if loop.first %} thumb_row_first
+ {%- elif loop.last %} thumb_row_last{% endif %}">
+ {% for entry in row %}
+ {% set entry_url = entry.url_for_self(request.urlgen) %}
+ <td class="media_thumbnail thumb_entry
+ {%- if loop.first %} thumb_entry_first
+ {%- elif loop.last %} thumb_entry_last{% endif %}">
+ <a href="{{ entry_url }}">
+ <img src="{{ request.app.public_store.file_url(
+ entry['media_files']['thumb']) }}" />
+ </a>
+ {% if entry['title'] %}
+ <br />
+ <a href="{{ entry_url }}">{{ entry['title'] }}</a>
+ {% endif %}
+ </td>
+ {% endfor %}
+ </tr>
{% endfor %}
+ </table>
+{%- endmacro %}
+
+{#
+ Render a media gallery with pagination.
+
+ Args:
+ - request: Request
+ - media_entries: pymongo cursor of media entries
+ - pagination: Paginator object
+ - pagination_base_url: If you want the pagination to point to a
+ different URL, point it here
+ - col_number: How many columns per row (default 5)
+#}
+{% macro object_gallery(request, media_entries, pagination,
+ pagination_base_url=None, col_number=5) %}
+ {% if media_entries and media_entries.count() %}
+ {{ media_grid(request, media_entries, col_number=col_number) }}
<div class="clear"></div>
{% if pagination_base_url %}
{# different url, so set that and don't keep the get params #}
@@ -39,4 +71,4 @@
<i>There doesn't seem to be any media here yet...</i>
</p>
{% endif %}
-{% endblock %}
+{% endmacro %}
diff --git a/mediagoblin/templates/mediagoblin/utils/tags.html b/mediagoblin/templates/mediagoblin/utils/tags.html
index ade41944..32db6e31 100644
--- a/mediagoblin/templates/mediagoblin/utils/tags.html
+++ b/mediagoblin/templates/mediagoblin/utils/tags.html
@@ -17,7 +17,7 @@
#}
{% block tags_content -%}
- <h4>Tags</h4>
+ <h3>Tags</h3>
<ul class="mediaentry_tags">
{% for tag in media.tags %}
<li class="tag">
diff --git a/mediagoblin/templates/mediagoblin/utils/wtforms.html b/mediagoblin/templates/mediagoblin/utils/wtforms.html
index 1d2f8619..2639522a 100644
--- a/mediagoblin/templates/mediagoblin/utils/wtforms.html
+++ b/mediagoblin/templates/mediagoblin/utils/wtforms.html
@@ -19,9 +19,9 @@
{# Generically render a field #}
{% macro render_field_div(field) %}
<div class="form_field_box">
- <div class="form_field_label">{{ field.label }}</div>
+ <div class="form_field_label">{{ _(field.label.text) }}</div>
{% if field.description -%}
- <div class="form_field_description">{{ field.description }}</div>
+ <div class="form_field_description">{{ _(field.description) }}</div>
{%- endif %}
<div class="form_field_input">{{ field }}</div>
{%- if field.errors -%}
@@ -34,25 +34,6 @@
</div>
{%- endmacro %}
-{# Generically render a textarea
- # ... mostly the same thing except it includes rows and cols #}
-{% macro render_textarea_div(field, rows=8, cols=20) %}
- <div class="form_field_box">
- <div class="form_field_label">{{ field.label }}</div>
- {% if field.description -%}
- <div class="form_field_description">{{ field.description }}</div>
- {%- endif %}
- <div class="form_field_input">{{ field(rows=rows, cols=cols) }}</div>
- {%- if field.errors -%}
- {% for error in field.errors %}
- <div class="form_field_error">
- {{ error }}
- </div>
- {% endfor %}
- {%- endif %}
- </div>
-{%- endmacro %}
-
{# Auto-render a form as a series of divs #}
{% macro render_divs(form) -%}
{% for field in form %}
@@ -64,7 +45,7 @@
{% macro render_table(form) -%}
{% for field in form %}
<tr>
- <th>{{field.label}}</th>
+ <th>{{ _(field.label.text) }}</th>
<td>
{{field}}
{% if field.errors %}
diff --git a/mediagoblin/tests/test_mgoblin_app.ini b/mediagoblin/tests/test_mgoblin_app.ini
index 7716e9ca..9d938b4f 100644
--- a/mediagoblin/tests/test_mgoblin_app.ini
+++ b/mediagoblin/tests/test_mgoblin_app.ini
@@ -1,7 +1,4 @@
[mediagoblin]
-queuestore_base_dir = %(here)s/test_user_dev/media/queue
-publicstore_base_dir = %(here)s/test_user_dev/media/public
-publicstore_base_url = /mgoblin_media/
direct_remote_path = /mgoblin_static/
email_sender_address = "notice@mediagoblin.example.org"
email_debug_mode = true
@@ -15,5 +12,12 @@ tags_max_length = 50
# mediagoblin.init.celery.from_celery
celery_setup_elsewhere = true
+[storage:publicstore]
+base_dir = %(here)s/test_user_dev/media/public
+base_url = /mgoblin_media/
+
+[storage:queuestore]
+base_dir = %(here)s/test_user_dev/media/queue
+
[celery]
celery_always_eager = true
diff --git a/mediagoblin/tests/test_paste.ini b/mediagoblin/tests/test_paste.ini
index 929a1ccf..e7574b7a 100644
--- a/mediagoblin/tests/test_paste.ini
+++ b/mediagoblin/tests/test_paste.ini
@@ -14,7 +14,7 @@ config = %(here)s/test_mgoblin_app.ini
[app:publicstore_serve]
use = egg:Paste#static
-document_root = %(here)s/user_dev/media/public
+document_root = %(here)s/test_user_dev/media/public
[app:mediagoblin_static]
use = egg:Paste#static
diff --git a/mediagoblin/tests/test_storage.py b/mediagoblin/tests/test_storage.py
index 1800c29d..45cb35c1 100644
--- a/mediagoblin/tests/test_storage.py
+++ b/mediagoblin/tests/test_storage.py
@@ -60,23 +60,20 @@ class FakeRemoteStorage(storage.BasicFileStorage):
def test_storage_system_from_config():
this_storage = storage.storage_system_from_config(
- {'somestorage_base_url': 'http://example.org/moodia/',
- 'somestorage_base_dir': '/tmp/',
- 'somestorage_garbage_arg': 'garbage_arg',
- 'garbage_arg': 'trash'},
- 'somestorage')
+ {'base_url': 'http://example.org/moodia/',
+ 'base_dir': '/tmp/',
+ 'garbage_arg': 'garbage_arg',
+ 'garbage_arg': 'trash'})
assert this_storage.base_url == 'http://example.org/moodia/'
assert this_storage.base_dir == '/tmp/'
assert this_storage.__class__ is storage.BasicFileStorage
this_storage = storage.storage_system_from_config(
- {'somestorage_foobie': 'eiboof',
- 'somestorage_blech': 'hcelb',
- 'somestorage_garbage_arg': 'garbage_arg',
- 'garbage_arg': 'trash',
- 'somestorage_storage_class':
- 'mediagoblin.tests.test_storage:FakeStorageSystem'},
- 'somestorage')
+ {'foobie': 'eiboof',
+ 'blech': 'hcelb',
+ 'garbage_arg': 'garbage_arg',
+ 'storage_class':
+ 'mediagoblin.tests.test_storage:FakeStorageSystem'})
assert this_storage.foobie == 'eiboof'
assert this_storage.blech == 'hcelb'
assert this_storage.__class__ is FakeStorageSystem
diff --git a/mediagoblin/tests/test_submission.py b/mediagoblin/tests/test_submission.py
index a7248255..9ae129cd 100644
--- a/mediagoblin/tests/test_submission.py
+++ b/mediagoblin/tests/test_submission.py
@@ -156,7 +156,7 @@ class TestSubmission:
util.clear_test_template_context()
response = self.test_app.post(
'/submit/', {
- 'title': 'Malicious Upload 2'
+ 'title': 'Malicious Upload 1'
}, upload_files=[(
'file', EVIL_FILE)])
@@ -164,33 +164,46 @@ class TestSubmission:
form = context['submit_form']
assert form.file.errors == ['The file doesn\'t seem to be an image!']
- # NOTE: The following 2 tests will fail. These can be uncommented
- # after http://bugs.foocorp.net/issues/324 is resolved and
- # bad files are handled properly.
+ # NOTE: The following 2 tests will ultimately fail, but they
+ # *will* pass the initial form submission step. Instead,
+ # they'll be caught as failures during the processing step.
# Test non-supported file with .jpg extension
# -------------------------------------------
- #util.clear_test_template_context()
- #response = self.test_app.post(
- # '/submit/', {
- # 'title': 'Malicious Upload 2'
- # }, upload_files=[(
- # 'file', EVIL_JPG)])
+ util.clear_test_template_context()
+ response = self.test_app.post(
+ '/submit/', {
+ 'title': 'Malicious Upload 2'
+ }, upload_files=[(
+ 'file', EVIL_JPG)])
+ response.follow()
+ assert_equal(
+ urlparse.urlsplit(response.location)[2],
+ '/u/chris/')
- #context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html']
- #form = context['submit_form']
- #assert form.file.errors == ['The file doesn\'t seem to be an image!']
+ entry = mg_globals.database.MediaEntry.find_one(
+ {'title': 'Malicious Upload 2'})
+ assert_equal(entry['state'], 'failed')
+ assert_equal(
+ entry['fail_error'],
+ u'mediagoblin.process_media.errors:BadMediaFail')
# Test non-supported file with .png extension
# -------------------------------------------
- #util.clear_test_template_context()
- #response = self.test_app.post(
- # '/submit/', {
- # 'title': 'Malicious Upload 3'
- # }, upload_files=[(
- # 'file', EVIL_PNG)])
-
- #context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html']
- #form = context['submit_form']
- #assert form.file.errors == ['The file doesn\'t seem to be an image!']
+ util.clear_test_template_context()
+ response = self.test_app.post(
+ '/submit/', {
+ 'title': 'Malicious Upload 3'
+ }, upload_files=[(
+ 'file', EVIL_PNG)])
+ response.follow()
+ assert_equal(
+ urlparse.urlsplit(response.location)[2],
+ '/u/chris/')
+ entry = mg_globals.database.MediaEntry.find_one(
+ {'title': 'Malicious Upload 3'})
+ assert_equal(entry['state'], 'failed')
+ assert_equal(
+ entry['fail_error'],
+ u'mediagoblin.process_media.errors:BadMediaFail')
diff --git a/mediagoblin/translations/en/LC_MESSAGES/mediagoblin.mo b/mediagoblin/translations/en/LC_MESSAGES/mediagoblin.mo
deleted file mode 100644
index fb7046cd..00000000
--- a/mediagoblin/translations/en/LC_MESSAGES/mediagoblin.mo
+++ /dev/null
Binary files differ
diff --git a/mediagoblin/translations/en/LC_MESSAGES/mediagoblin.po b/mediagoblin/translations/en/LC_MESSAGES/mediagoblin.po
deleted file mode 100644
index 3bec204e..00000000
--- a/mediagoblin/translations/en/LC_MESSAGES/mediagoblin.po
+++ /dev/null
@@ -1,23 +0,0 @@
-# Translations template for PROJECT.
-# Copyright (C) 2011 ORGANIZATION
-# This file is distributed under the same license as the PROJECT project.
-# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
-#
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PROJECT VERSION\n"
-"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2011-05-12 22:28-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"
-"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"
-
-#: mediagoblin/templates/mediagoblin/root.html:22
-msgid "Welcome to GNU MediaGoblin!"
-msgstr ""
-
diff --git a/mediagoblin/user_pages/forms.py b/mediagoblin/user_pages/forms.py
index 8829b674..25001019 100644
--- a/mediagoblin/user_pages/forms.py
+++ b/mediagoblin/user_pages/forms.py
@@ -16,7 +16,10 @@
import wtforms
+from mediagoblin.util import fake_ugettext_passthrough as _
+
+
class MediaCommentForm(wtforms.Form):
- comment_content = wtforms.TextAreaField(
- 'Comment',
- [wtforms.validators.Required()])
+ comment_content = wtforms.TextAreaField(
+ _('Comment'),
+ [wtforms.validators.Required()])
diff --git a/mediagoblin/user_pages/routing.py b/mediagoblin/user_pages/routing.py
index 3be0617d..65c0fa64 100644
--- a/mediagoblin/user_pages/routing.py
+++ b/mediagoblin/user_pages/routing.py
@@ -28,9 +28,16 @@ user_routes = [
'/{user}/m/{media}/c/{comment}/',
controller="mediagoblin.user_pages.views:media_home"),
Route('mediagoblin.edit.edit_media', "/{user}/m/{media}/edit/",
- controller="mediagoblin.edit.views:edit_media"),
+ controller="mediagoblin.edit.views:edit_media"),
+ Route('mediagoblin.edit.attachments',
+ '/{user}/m/{media}/attachments/',
+ controller="mediagoblin.edit.views:edit_attachments"),
Route('mediagoblin.user_pages.atom_feed', '/{user}/atom/',
controller="mediagoblin.user_pages.views:atom_feed"),
Route('mediagoblin.user_pages.media_post_comment',
'/{user}/m/{media}/comment/add/',
- controller="mediagoblin.user_pages.views:media_post_comment")]
+ controller="mediagoblin.user_pages.views:media_post_comment"),
+ Route('mediagoblin.user_pages.processing_panel',
+ '/{user}/panel/',
+ controller="mediagoblin.user_pages.views:processing_panel"),
+ ]
diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py
index 85a84db6..2d9bcd21 100644
--- a/mediagoblin/user_pages/views.py
+++ b/mediagoblin/user_pages/views.py
@@ -1,4 +1,4 @@
-# GNU MediaGoblin -- federated, autonomous media hosting
+# MediaGoblin -- federated, autonomous media hosting
# Copyright (C) 2011 Free Software Foundation, Inc
#
# This program is free software: you can redistribute it and/or modify
@@ -16,10 +16,11 @@
from webob import exc
-from mediagoblin import messages
+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)
+ Pagination, render_to_response, redirect, cleaned_markdown_conversion,
+ render_404)
from mediagoblin.user_pages import forms as user_forms
from mediagoblin.decorators import (uses_pagination, get_user_media_entry,
@@ -34,7 +35,7 @@ def user_home(request, page):
user = request.db.User.find_one({
'username': request.matchdict['user']})
if not user:
- return exc.HTTPNotFound()
+ return render_404(request)
elif user['status'] != u'active':
return render_to_response(
request,
@@ -50,7 +51,7 @@ def user_home(request, page):
#if no data is available, return NotFound
if media_entries == None:
- return exc.HTTPNotFound()
+ return render_404(request)
user_gallery_url = request.urlgen(
'mediagoblin.user_pages.user_gallery',
@@ -71,7 +72,7 @@ def user_gallery(request, page):
'username': request.matchdict['user'],
'status': 'active'})
if not user:
- return exc.HTTPNotFound()
+ return render_404(request)
cursor = request.db.MediaEntry.find(
{'uploader': user['_id'],
@@ -82,7 +83,7 @@ def user_gallery(request, page):
#if no data is available, return NotFound
if media_entries == None:
- return exc.HTTPNotFound()
+ return render_404(request)
return render_to_response(
request,
@@ -117,7 +118,8 @@ def media_home(request, media, page, **kwargs):
{'media': media,
'comments': comments,
'pagination': pagination,
- 'comment_form': comment_form})
+ 'comment_form': comment_form,
+ 'app_config': mg_globals.app_config})
@require_active_login
@@ -154,7 +156,7 @@ def atom_feed(request):
'username': request.matchdict['user'],
'status': 'active'})
if not user:
- return exc.HTTPNotFound()
+ return render_404(request)
cursor = request.db.MediaEntry.find({
'uploader': user['_id'],
@@ -175,3 +177,53 @@ def atom_feed(request):
url=entry.url_for_self(request.urlgen))
return feed.get_response()
+
+
+@require_active_login
+def processing_panel(request):
+ """
+ Show to the user what media is still in conversion/processing...
+ and what failed, and why!
+ """
+ # Get the user
+ user = request.db.User.find_one(
+ {'username': request.matchdict['user'],
+ 'status': 'active'})
+
+ # Make sure the user exists and is active
+ if not user:
+ return render_404(request)
+ elif user['status'] != u'active':
+ return render_to_response(
+ request,
+ 'mediagoblin/user_pages/user.html',
+ {'user': user})
+
+ # XXX: Should this be a decorator?
+ #
+ # 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']
+ or request.user.is_admin):
+ # No? Let's simply redirect to this user's homepage then.
+ return redirect(
+ request, 'mediagoblin.user_pages.user_home',
+ user=request.matchdict['user'])
+
+ # Get media entries which are in-processing
+ processing_entries = request.db.MediaEntry.find(
+ {'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'],
+ 'state': 'failed'}).sort('created', DESCENDING)
+
+ # Render to response
+ return render_to_response(
+ request,
+ 'mediagoblin/user_pages/processing_panel.html',
+ {'user': user,
+ 'processing_entries': processing_entries,
+ 'failed_entries': failed_entries})
diff --git a/mediagoblin/util.py b/mediagoblin/util.py
index 60ba8800..ba4ac01e 100644
--- a/mediagoblin/util.py
+++ b/mediagoblin/util.py
@@ -28,11 +28,13 @@ 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
@@ -93,12 +95,15 @@ def get_jinja_env(template_loader, locale):
extensions=['jinja2.ext.i18n', 'jinja2.ext.autoescape'])
template_env.install_gettext_callables(
- mg_globals.translations.gettext,
- mg_globals.translations.ngettext)
+ 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
@@ -133,9 +138,11 @@ def clear_test_template_context():
TEMPLATE_TEST_CONTEXT = {}
-def render_to_response(request, template, context):
+def render_to_response(request, template, context, status=200):
"""Much like Django's shortcut.render()"""
- return Response(render_template(request, template, context))
+ return Response(
+ render_template(request, template, context),
+ status=status)
def redirect(request, *args, **kwargs):
@@ -309,7 +316,7 @@ def send_email(from_addr, to_addrs, subject, message_body):
TRANSLATIONS_PATH = pkg_resources.resource_filename(
- 'mediagoblin', 'translations')
+ 'mediagoblin', 'i18n')
def locale_to_lower_upper(locale):
@@ -350,8 +357,10 @@ def get_locale_from_request(request):
accept_lang_matches = request.accept_language.best_matches()
# Your routing can explicitly specify a target language
- if request.matchdict.has_key('locale'):
- target_lang = request.matchdict['locale']
+ 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
@@ -487,6 +496,66 @@ def setup_gettext(locale):
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):
@@ -575,3 +644,40 @@ class Pagination(object):
"""
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)
diff --git a/paste.ini b/paste.ini
index 73fbe8e8..fc459989 100644
--- a/paste.ini
+++ b/paste.ini
@@ -1,7 +1,11 @@
[DEFAULT]
-debug = true
+# Set to true to enable web-based debugging messages and etc.
+debug = false
-[composite:main]
+[pipeline:main]
+pipeline = errors routing
+
+[composite:routing]
use = egg:Paste#urlmap
/ = mediagoblin
/mgoblin_media/ = publicstore_serve
@@ -28,6 +32,10 @@ beaker.session.key = mediagoblin
beaker.session.data_dir = %(here)s/user_dev/beaker/sessions/data
beaker.session.lock_dir = %(here)s/user_dev/beaker/sessions/lock
+[filter:errors]
+use = egg:mediagoblin#errors
+debug = false
+
[server:main]
use = egg:Paste#http
host = 127.0.0.1
diff --git a/setup.py b/setup.py
index 6043ad41..d6ef584b 100644
--- a/setup.py
+++ b/setup.py
@@ -53,10 +53,14 @@ setup(
entry_points = """\
[console_scripts]
gmg = mediagoblin.gmg_commands:main_cli
+ pybabel = mediagoblin.babel.messages.frontend:main
[paste.app_factory]
app = mediagoblin.app:paste_app_factory
+ [paste.filter_app_factory]
+ errors = mediagoblin.errormiddleware:mgoblin_error_middleware
+
[zc.buildout]
make_user_dev_dirs = mediagoblin.buildout_recipes:MakeUserDevDirs