Merge branch 'master' into jwandborg-f482_media_attachments

Conflicts:
	mediagoblin/config_spec.ini
	mediagoblin/edit/forms.py
	mediagoblin/edit/views.py
	mediagoblin/submit/views.py
	mediagoblin/templates/mediagoblin/user_pages/media.html
This commit is contained in:
Christopher Allan Webber 2011-08-22 21:48:45 -05:00
commit 894fa564e7
88 changed files with 5742 additions and 692 deletions

3
.gitignore vendored
View File

@ -10,7 +10,8 @@ mediagoblin.egg-info
*.pyo
docs/_build/
user_dev/
mediagoblin_user.ini
paste_local.ini
mediagoblin_local.ini
server-log.txt
*~
*.swp

8
.tx/config Normal file
View File

@ -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

View File

@ -10,4 +10,4 @@ encoding = utf-8
# # Extraction from JavaScript files
# [javascript: mediagoblin/static/js/**.js]
# extract_messages = $._, jQuery._
# extract_messages = $._, jQuery._

View File

@ -8,34 +8,27 @@ 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
* people who want to try the software locally
* people who want to deploy and administrate the software
This manual is a living document and is in the ``mediagoblin``
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:
* http://mediagoblin.org/pages/join.html for general "join us" information
* http://wiki.mediagoblin.org/ for our contributor-focused wiki
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.
Who wrote this documentation?
=============================
In no particular order:
* Chris
* Will
* Deb
* Greg
* Karen
* Matt
* Asheesh
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``.

View File

@ -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/>`_.

View File

@ -12,11 +12,10 @@ Table of Contents:
:maxdepth: 2
foreword
mediagoblin
contributinghowto
about_mediagoblin
deploymenthowto
theminghowto
git
contributinghowto
codebase
vision

View File

@ -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

View File

@ -101,26 +101,6 @@ class MediaGoblinApp(object):
## Routing / controller loading stuff
route_match = self.routing.match(path_info)
# No matching page?
if route_match is None:
# Try to do see if we have a match with a trailing slash
# added and if so, redirect
if not path_info.endswith('/') \
and request.method == 'GET' \
and self.routing.match(path_info + '/'):
new_path_info = path_info + '/'
if request.GET:
new_path_info = '%s?%s' % (
new_path_info, urllib.urlencode(request.GET))
redirect = exc.HTTPFound(location=new_path_info)
return request.get_response(redirect)(environ, start_response)
# Okay, no matches. 404 time!
return exc.HTTPNotFound()(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)
@ -138,6 +118,27 @@ class MediaGoblinApp(object):
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
# added and if so, redirect
if not path_info.endswith('/') \
and request.method == 'GET' \
and self.routing.match(path_info + '/'):
new_path_info = path_info + '/'
if request.GET:
new_path_info = '%s?%s' % (
new_path_info, urllib.urlencode(request.GET))
redirect = exc.HTTPFound(location=new_path_info)
return request.get_response(redirect)(environ, start_response)
# Okay, no matches. 404 time!
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
return controller(request)(environ, start_response)

View File

@ -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()])

View File

@ -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.')
_(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
else:
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'])

View File

@ -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/")
@ -42,6 +37,15 @@ celery_setup_elsewhere = boolean(default=False)
# source files for a media file but can also be a HUGE security risk.
allow_attachments = boolean(default=False)
[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()

View File

@ -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)

View File

@ -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):
"""

View File

@ -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)

View File

@ -16,26 +16,29 @@
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')])

View File

@ -27,6 +27,7 @@ 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
@ -61,7 +62,7 @@ def edit_media(request, media):
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')
@ -90,7 +91,7 @@ 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,
@ -161,7 +162,7 @@ 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

View File

@ -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)

View File

@ -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'},
}

View File

@ -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)

Binary file not shown.

View File

@ -0,0 +1,317 @@
# 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.
# <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-08 22:53-0500\n"
"PO-Revision-Date: 2011-08-10 23:20+0000\n"
"Last-Translator: JanCBorchardt <JanCBorchardt@fsfe.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:55
msgid "Sorry, a user with that name already exists."
msgstr "Leider gibt es bereits einen Benutzer mit diesem Namen."
#: mediagoblin/auth/views.py:152
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:158
msgid "The verification key or user id is incorrect"
msgstr "Der Bestätigungssschlüssel oder die Nutzernummer ist falsch."
#: mediagoblin/auth/views.py:179
#: mediagoblin/templates/mediagoblin/auth/resent_verification_email.html:22
msgid "Resent your verification email."
msgstr "Bestätigungs-Email noch Mal senden."
#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:26
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/forms.py:43
msgid "Improperly formed URL"
msgstr "Adresse fehlerhaft"
#: mediagoblin/edit/views.py:54
msgid "An entry with that slug already exists for this user."
msgstr "Diesen Kurztitel hast du bereits vergeben."
#: mediagoblin/edit/views.py:75
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:96
msgid "You are editing a user's profile. Proceed with caution."
msgstr "Du bearbeitest das Profil eines Anderen. Bitte sei vorsichtig."
#: mediagoblin/submit/forms.py:29
msgid "File"
msgstr "Datei"
#: mediagoblin/submit/views.py:45
msgid "You must provide a file."
msgstr "Du musst eine Datei angeben."
#: mediagoblin/submit/views.py:48
msgid "The file doesn't seem to be an image!"
msgstr "Diese Datei scheint kein Bild zu sein!"
#: mediagoblin/submit/views.py:96
msgid "Woohoo! Submitted!"
msgstr "Yeeeaaah! Geschafft!"
#: mediagoblin/templates/mediagoblin/base.html:22
msgid "GNU MediaGoblin"
msgstr "GNU MediaGoblin"
#: mediagoblin/templates/mediagoblin/base.html:45
msgid "Mediagoblin logo"
msgstr "Mediagoblin-Logo"
#: mediagoblin/templates/mediagoblin/base.html:51
msgid "Submit media"
msgstr "Medien hochladen"
#: mediagoblin/templates/mediagoblin/base.html:62
msgid "verify your email!"
msgstr "Bitte bestätige deine Email-Adresse!"
#: mediagoblin/templates/mediagoblin/base.html:72
msgid "Login"
msgstr "Anmelden"
#: mediagoblin/templates/mediagoblin/base.html:88
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU project</a>"
msgstr ""
"Läüft mit <a href=\"http://mediagoblin.org\">MediaGoblin</a>, einem <a "
"href=\"http://gnu.org/\">GNU-Projekt</a>"
#: mediagoblin/templates/mediagoblin/root.html:21
msgid "Welcome to GNU MediaGoblin!"
msgstr "Willkommen bei GNU MediaGoblin!"
#: mediagoblin/templates/mediagoblin/root.html:26
msgid "Submit an item"
msgstr "Eintrag hochladen"
#: mediagoblin/templates/mediagoblin/root.html:31
#, python-format
msgid "If you have an account, you can <a href=\"%(login_url)s\">Login</a>."
msgstr ""
"Falls du ein Konto hast, kannst du dich <a "
"href=\"%(login_url)s\">anmelden</a>."
#: mediagoblin/templates/mediagoblin/root.html:37
#, python-format
msgid ""
"If you don't have an account, please <a "
"href=\"%(register_url)s\">Register</a>."
msgstr ""
"Wenn du noch kein Konto hast, <a href=\"%(register_url)s\">registriere "
"dich</a>."
#: mediagoblin/templates/mediagoblin/auth/login.html:26
msgid "Log in"
msgstr "Anmelden"
#: mediagoblin/templates/mediagoblin/auth/login.html:29
msgid "Login failed!"
msgstr "Anmeldung fehlgeschlagen!"
#: mediagoblin/templates/mediagoblin/auth/login.html:34
#: mediagoblin/templates/mediagoblin/auth/register.html:30
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
#: mediagoblin/templates/mediagoblin/submit/start.html:32
msgid "Submit"
msgstr "Bestätigen"
#: 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/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
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:29
msgid "Media tagged with:"
msgstr "Medien markiert mit:"
#: mediagoblin/templates/mediagoblin/listings/tag.html:40
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:46
#: mediagoblin/templates/mediagoblin/user_pages/user.html:101
msgid "atom feed"
msgstr "Atom-Feed"
#: mediagoblin/templates/mediagoblin/submit/start.html:26
msgid "Submit yer media"
msgstr "Medien hochladen"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30
#, 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:51
#: mediagoblin/templates/mediagoblin/user_pages/user.html:30
msgid "Sorry, no such user found."
msgstr "Dieser Benutzer wurde leider nicht gefunden."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:37
#: mediagoblin/templates/mediagoblin/user_pages/user.html:57
msgid "Verification needed"
msgstr "Überprüfung notwendig"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:40
msgid "Almost done! Your account still needs to be verified."
msgstr "Fast geschafft! Dein Konto muss nur noch bestätigt werden."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:45
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:49
msgid "In case it doesn't:"
msgstr "Wenn sie nicht ankommt:"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:52
msgid "Resend verification email"
msgstr "Bestätigung noch Mal senden"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:60
msgid ""
"Someone has registered an account with this username, but it still has to be"
" verified."
msgstr ""
"Jemand hat schon ein Konto mit diesem Nutzernamen registriert, aber es muss "
"noch bestätigt werden."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:66
#, 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 weg ist, kannst du "
"dich <a href=\"%(login_url)s\">anmelden</a> und sie erneut senden."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:76
#, python-format
msgid "%(username)s's profile"
msgstr "%(username)ss Profil"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:84
msgid "Edit profile"
msgstr "Profil bearbeiten"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:95
#, python-format
msgid "View all of %(username)s's media"
msgstr "Alle Medien von %(username)s anschauen"

View File

@ -0,0 +1,300 @@
# 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-13 19:47-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/forms.py:43
msgid "Improperly formed URL"
msgstr ""
#: mediagoblin/edit/views.py:54
msgid "An entry with that slug already exists for this user."
msgstr ""
#: mediagoblin/edit/views.py:75
msgid "You are editing another user's media. Proceed with caution."
msgstr ""
#: mediagoblin/edit/views.py:96
msgid "You are editing a user's profile. Proceed with caution."
msgstr ""
#: mediagoblin/submit/forms.py:25
msgid "File"
msgstr ""
#: mediagoblin/submit/views.py:46
msgid "You must provide a file."
msgstr ""
#: mediagoblin/submit/views.py:49
msgid "The file doesn't seem to be an image!"
msgstr ""
#: mediagoblin/submit/views.py:94
msgid "Woohoo! Submitted!"
msgstr ""
#: mediagoblin/templates/mediagoblin/base.html:22
msgid "GNU MediaGoblin"
msgstr ""
#: mediagoblin/templates/mediagoblin/base.html:45
msgid "Mediagoblin logo"
msgstr ""
#: mediagoblin/templates/mediagoblin/base.html:51
msgid "Submit media"
msgstr ""
#: mediagoblin/templates/mediagoblin/base.html:62
msgid "verify your email!"
msgstr ""
#: mediagoblin/templates/mediagoblin/base.html:72
msgid "Login"
msgstr ""
#: mediagoblin/templates/mediagoblin/base.html:88
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:23
msgid "Welcome to GNU MediaGoblin!"
msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:28
msgid "Submit an item"
msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:33
#, python-format
msgid "If you have an account, you can <a href=\"%(login_url)s\">Login</a>."
msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:39
#, python-format
msgid ""
"If you don't have an account, please <a "
"href=\"%(register_url)s\">Register</a>."
msgstr ""
#: mediagoblin/templates/mediagoblin/auth/login.html:26
msgid "Log in"
msgstr ""
#: mediagoblin/templates/mediagoblin/auth/login.html:29
msgid "Login failed!"
msgstr ""
#: mediagoblin/templates/mediagoblin/auth/login.html:34
#: mediagoblin/templates/mediagoblin/auth/register.html:30
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
#: mediagoblin/templates/mediagoblin/submit/start.html:29
msgid "Submit"
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/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
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/listings/tag.html:42
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48
#: mediagoblin/templates/mediagoblin/user_pages/user.html:104
msgid "atom feed"
msgstr ""
#: mediagoblin/templates/mediagoblin/submit/start.html:26
msgid "Submit yer media"
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:53
#: mediagoblin/templates/mediagoblin/user_pages/user.html:32
msgid "Sorry, no such user found."
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/user.html:39
#: mediagoblin/templates/mediagoblin/user_pages/user.html:59
msgid "Verification needed"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/user.html:42
msgid "Almost done! Your account still needs to be verified."
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 verified."
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:86
msgid "Edit profile"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/user.html:98
#, python-format
msgid "View all of %(username)s's media"
msgstr ""
#: mediagoblin/user_pages/forms.py:24
msgid "Comment"
msgstr ""

Binary file not shown.

View File

@ -0,0 +1,319 @@
# Translations template for PROJECT.
# Copyright (C) 2011 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
#
# <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-13 19:47-0500\n"
"PO-Revision-Date: 2011-08-15 20:33+0000\n"
"Last-Translator: fajro <faigos@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 0.9.6\n"
"Language: 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 "Pasvorton"
#: mediagoblin/auth/forms.py:34
msgid "Passwords must match."
msgstr "Pasvortoj devas koincidi. "
#: mediagoblin/auth/forms.py:36
msgid "Confirm password"
msgstr "Retajpu pasvorton"
#: mediagoblin/auth/forms.py:39
msgid "Email address"
msgstr "Retadreso"
#: mediagoblin/auth/views.py:40
msgid "Sorry, registration is disabled on this instance."
msgstr "Bedaŭrinde, registrado estas malaktivita en tiu ĉi instanco."
#: 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 ""
#: mediagoblin/auth/views.py:159
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr ""
"Vian retadreson estas kontrolita. 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 ""
#: 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 "Etikedoj"
#: mediagoblin/edit/forms.py:38
msgid "Bio"
msgstr "Bio"
#: mediagoblin/edit/forms.py:41
msgid "Website"
msgstr "Retejo"
#: mediagoblin/edit/forms.py:43
msgid "Improperly formed URL"
msgstr ""
#: mediagoblin/edit/views.py:54
msgid "An entry with that slug already exists for this user."
msgstr ""
#: mediagoblin/edit/views.py:75
msgid "You are editing another user's media. Proceed with caution."
msgstr ""
#: mediagoblin/edit/views.py:96
msgid "You are editing a user's profile. Proceed with caution."
msgstr ""
#: mediagoblin/submit/forms.py:25
msgid "File"
msgstr "Dosiero"
#: mediagoblin/submit/views.py:46
msgid "You must provide a file."
msgstr "Vi devas provizi dosieron."
#: mediagoblin/submit/views.py:49
msgid "The file doesn't seem to be an image!"
msgstr ""
#: mediagoblin/submit/views.py:94
msgid "Woohoo! Submitted!"
msgstr ""
#: mediagoblin/templates/mediagoblin/base.html:22
msgid "GNU MediaGoblin"
msgstr "GNU MediaGoblin"
#: mediagoblin/templates/mediagoblin/base.html:45
msgid "Mediagoblin logo"
msgstr " Logogramo de Mediagoblin"
#: mediagoblin/templates/mediagoblin/base.html:51
msgid "Submit media"
msgstr "Alŝuti aŭd-vid-dosieron"
#: mediagoblin/templates/mediagoblin/base.html:62
msgid "verify your email!"
msgstr "kontrolu vian retpoŝton! "
#: mediagoblin/templates/mediagoblin/base.html:72
msgid "Login"
msgstr "Ensaluti"
#: mediagoblin/templates/mediagoblin/base.html:88
msgid ""
"Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a "
"href=\"http://gnu.org/\">GNU project</a>"
msgstr ""
"Provizita de <a href=\"http://mediagoblin.org\">MediaGoblin</a>, unu el la "
"<a href=\"http://gnu.org/\">GNU projectoj</a>"
#: mediagoblin/templates/mediagoblin/root.html:23
msgid "Welcome to GNU MediaGoblin!"
msgstr "Bonvenon al GNU MediaGoblin!"
#: mediagoblin/templates/mediagoblin/root.html:28
msgid "Submit an item"
msgstr "Alŝuti dosieron"
#: mediagoblin/templates/mediagoblin/root.html:33
#, python-format
msgid "If you have an account, you can <a href=\"%(login_url)s\">Login</a>."
msgstr "Se vi havas konton, vi povas <a href=\"%(login_url)s\">Ensaluti</a>."
#: mediagoblin/templates/mediagoblin/root.html:39
#, python-format
msgid ""
"If you don't have an account, please <a "
"href=\"%(register_url)s\">Register</a>."
msgstr ""
"Se vi ne havas konton, bonvolu <a href=\"%(register_url)s\">Registriĝi</a>."
#: mediagoblin/templates/mediagoblin/auth/login.html:26
msgid "Log in"
msgstr "Ensaluti"
#: mediagoblin/templates/mediagoblin/auth/login.html:29
msgid "Login failed!"
msgstr "Ensalutado malsukcesis!"
#: mediagoblin/templates/mediagoblin/auth/login.html:34
#: mediagoblin/templates/mediagoblin/auth/register.html:30
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
#: mediagoblin/templates/mediagoblin/submit/start.html:29
msgid "Submit"
msgstr "Alŝuti"
#: 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 unu ĉi tie!"
#: mediagoblin/templates/mediagoblin/auth/register.html:27
msgid "Create an account!"
msgstr "Kreu konton!"
#: 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 "Editing %(media_title)s"
#: mediagoblin/templates/mediagoblin/edit/edit.html:36
msgid "Cancel"
msgstr "Nuligi"
#: mediagoblin/templates/mediagoblin/edit/edit.html:37
msgid "Save changes"
msgstr "Konservi ŝanĝojn"
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:29
#, python-format
msgid "Editing %(username)s's profile"
msgstr "Redaktanta profilon de %(username)s'"
#: mediagoblin/templates/mediagoblin/listings/tag.html:31
msgid "Media tagged with:"
msgstr "Dosiero markita kiel:"
#: mediagoblin/templates/mediagoblin/listings/tag.html:42
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48
#: mediagoblin/templates/mediagoblin/user_pages/user.html:104
msgid "atom feed"
msgstr "Atom-a informfluado"
#: mediagoblin/templates/mediagoblin/submit/start.html:26
msgid "Submit yer media"
msgstr "Alŝutu vian aŭd-vid-dosieron"
#: 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>-a aŭd-vid-dosiero"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:53
#: mediagoblin/templates/mediagoblin/user_pages/user.html:32
msgid "Sorry, no such user found."
msgstr "Uzanto ne trovita."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:39
#: mediagoblin/templates/mediagoblin/user_pages/user.html:59
msgid "Verification needed"
msgstr "Kontrolon bezonata"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:42
msgid "Almost done! Your account still needs to be verified."
msgstr "Preskaŭ farite! Via konto ankoraŭ devas esti kontrolita."
#: 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 ""
"Retmesaĝo alvenos post kelkaj momentoj kun instrukcioj 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 "Resendu 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"
" verified."
msgstr ""
"Iu registris konton kun tiu ĉi uzantonomo, sed ĝi devas ankoraŭ esti "
"kontrolita."
#: 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 "%(username)s'-a profilo"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:86
msgid "Edit profile"
msgstr "Redakti profilo"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:98
#, python-format
msgid "View all of %(username)s's media"
msgstr "Rigardu ĉiuj aŭd-vid-dosierojn de %(username)s'"
#: mediagoblin/user_pages/forms.py:24
msgid "Comment"
msgstr "Komento"

Binary file not shown.

View File

@ -0,0 +1,312 @@
# Translations template for PROJECT.
# Copyright (C) 2011 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
#
# <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-08 22:53-0500\n"
"PO-Revision-Date: 2011-08-10 20:30+0000\n"
"Last-Translator: nvjacobo <jacobo@gnu.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, el registro está deshabilitado en este momento."
#: mediagoblin/auth/views.py:55
msgid "Sorry, a user with that name already exists."
msgstr "Lo sentimos, un usuario con ese nombre ya existe."
#: mediagoblin/auth/views.py:152
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 las imágenes!"
#: mediagoblin/auth/views.py:158
msgid "The verification key or user id is incorrect"
msgstr ""
"La clave de la verificación o la identificación del usuario es incorrecta"
#: mediagoblin/auth/views.py:179
#: 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:26
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 vacia"
#: 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/forms.py:43
msgid "Improperly formed URL"
msgstr "URL de forma incorrecta"
#: mediagoblin/edit/views.py:54
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:75
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:96
msgid "You are editing a user's profile. Proceed with caution."
msgstr "Usted está editando un perfil de usuario. Proceder con precaucións."
#: mediagoblin/submit/forms.py:29
msgid "File"
msgstr "Archivo"
#: mediagoblin/submit/views.py:45
msgid "You must provide a file."
msgstr "Usted debe proporcionar un archivo."
#: mediagoblin/submit/views.py:48
msgid "The file doesn't seem to be an image!"
msgstr "El archivo no parece ser una imagen!"
#: mediagoblin/submit/views.py:96
msgid "Woohoo! Submitted!"
msgstr "Woohoo! Enviado!"
#: mediagoblin/templates/mediagoblin/base.html:22
msgid "GNU MediaGoblin"
msgstr "GNU MediaGoblin"
#: mediagoblin/templates/mediagoblin/base.html:45
msgid "Mediagoblin logo"
msgstr "Mediagoblin logo"
#: mediagoblin/templates/mediagoblin/base.html:51
msgid "Submit media"
msgstr "Enviar contenido"
#: mediagoblin/templates/mediagoblin/base.html:62
msgid "verify your email!"
msgstr "Verifique su correo electrónico"
#: mediagoblin/templates/mediagoblin/base.html:72
msgid "Login"
msgstr "Conectarse"
#: mediagoblin/templates/mediagoblin/base.html:88
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:21
msgid "Welcome to GNU MediaGoblin!"
msgstr "¡Bienvenido a GNU MediaGoblin!"
#: mediagoblin/templates/mediagoblin/root.html:26
msgid "Submit an item"
msgstr "Enviar un item"
#: mediagoblin/templates/mediagoblin/root.html:31
#, python-format
msgid "If you have an account, you can <a href=\"%(login_url)s\">Login</a>."
msgstr ""
"Si tiene una cuenta, puede iniciar sesión <a "
"href=\"%(login_url)s\">Login</a>."
#: mediagoblin/templates/mediagoblin/root.html:37
#, python-format
msgid ""
"If you don't have an account, please <a "
"href=\"%(register_url)s\">Register</a>."
msgstr ""
"Si no tienes una cuenta, por favor, <a "
"href=\"%(register_url)s\">Regístrese</a> ."
#: mediagoblin/templates/mediagoblin/auth/login.html:26
msgid "Log in"
msgstr "Conectarse"
#: mediagoblin/templates/mediagoblin/auth/login.html:29
msgid "Login failed!"
msgstr "El inicio de sesión fallo"
#: mediagoblin/templates/mediagoblin/auth/login.html:34
#: mediagoblin/templates/mediagoblin/auth/register.html:30
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
#: mediagoblin/templates/mediagoblin/submit/start.html:32
msgid "Submit"
msgstr "Enviar"
#: 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/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 MediaGoblin GNU, abra ls "
"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
msgid "Save changes"
msgstr "Salvar cambios"
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:29
#, python-format
msgid "Editing %(username)s's profile"
msgstr "Edición %(username)s de perfil"
#: mediagoblin/templates/mediagoblin/listings/tag.html:29
msgid "Media tagged with:"
msgstr "El contenido con la etiqueta:"
#: mediagoblin/templates/mediagoblin/listings/tag.html:40
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:46
#: mediagoblin/templates/mediagoblin/user_pages/user.html:101
msgid "atom feed"
msgstr "feed Atom"
#: mediagoblin/templates/mediagoblin/submit/start.html:26
msgid "Submit yer media"
msgstr "Envíe su contenido"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30
#, 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:51
#: mediagoblin/templates/mediagoblin/user_pages/user.html:30
msgid "Sorry, no such user found."
msgstr "Lo sentimos, no se ha encontrado el usuario."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:37
#: mediagoblin/templates/mediagoblin/user_pages/user.html:57
msgid "Verification needed"
msgstr "Verificación necesaria"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:40
msgid "Almost done! Your account still needs to be verified."
msgstr "Ya está casi hecho! Su cuenta tiene que ser verificada."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:45
msgid ""
"An email should arrive in a few moments with instructions on how to do so."
msgstr ""
"Un e-mail debe llegar en unos momentos con las instrucciones para hacerlo."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:49
msgid "In case it doesn't:"
msgstr "En caso de que no:"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:52
msgid "Resend verification email"
msgstr "Reenviar correo electrónico de verificación"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:60
msgid ""
"Someone has registered an account with this username, but it still has to be"
" verified."
msgstr ""
"Alguien ha registrado una cuenta con este nombre de usuario, pero todavía "
"tiene que ser verificado."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:66
#, 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 usted ha perdido su correo electrónico de "
"verificación, usted puede reenviarlo <a href=\"%(login_url)s\">acceder</a>."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:76
#, python-format
msgid "%(username)s's profile"
msgstr "Perfil de %(username)s's"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:84
msgid "Edit profile"
msgstr "Editar perfil"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:95
#, python-format
msgid "View all of %(username)s's media"
msgstr "Ver todo el contenido de %(username)s's "

Binary file not shown.

View File

@ -0,0 +1,329 @@
# Translations template for PROJECT.
# Copyright (C) 2011 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
#
# <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-13 19:47-0500\n"
"PO-Revision-Date: 2011-08-16 13:22+0000\n"
"Last-Translator: joar <transifex@wandborg.se>\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 ""
#: 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/forms.py:43
msgid "Improperly formed URL"
msgstr "Adresse web mal formée"
#: mediagoblin/edit/views.py:54
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:75
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:96
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/submit/forms.py:25
msgid "File"
msgstr "Fichier"
#: mediagoblin/submit/views.py:46
msgid "You must provide a file."
msgstr "Il vous faut fournir un fichier."
#: mediagoblin/submit/views.py:49
msgid "The file doesn't seem to be an image!"
msgstr "Ce fichier ne semble pas être une image !"
#: mediagoblin/submit/views.py:94
msgid "Woohoo! Submitted!"
msgstr "Youhou, c'est envoyé !"
#: mediagoblin/templates/mediagoblin/base.html:22
msgid "GNU MediaGoblin"
msgstr "GNU MediaGoblin"
#: mediagoblin/templates/mediagoblin/base.html:45
msgid "Mediagoblin logo"
msgstr "logo de MediaGoblin"
#: mediagoblin/templates/mediagoblin/base.html:51
msgid "Submit media"
msgstr "Soumettre un média"
#: mediagoblin/templates/mediagoblin/base.html:62
msgid "verify your email!"
msgstr "vérifier son adresse e-mail"
#: mediagoblin/templates/mediagoblin/base.html:72
msgid "Login"
msgstr "Identification"
#: mediagoblin/templates/mediagoblin/base.html:88
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:23
msgid "Welcome to GNU MediaGoblin!"
msgstr "Bienvenue sur GNU MediaGoblin !"
#: mediagoblin/templates/mediagoblin/root.html:28
msgid "Submit an item"
msgstr "Soumettre un fichier"
#: mediagoblin/templates/mediagoblin/root.html:33
#, python-format
msgid "If you have an account, you can <a href=\"%(login_url)s\">Login</a>."
msgstr ""
"Si vous avez un compte, vous pouvez vous <a "
"href=\"%(login_url)s\">identifier</a>."
#: mediagoblin/templates/mediagoblin/root.html:39
#, python-format
msgid ""
"If you don't have an account, please <a "
"href=\"%(register_url)s\">Register</a>."
msgstr ""
"Si vous n'avez pas de compte, veuillez vous <a "
"href=\"%(register_url)s\">inscrire</a>."
#: mediagoblin/templates/mediagoblin/auth/login.html:26
msgid "Log in"
msgstr "S'identifier"
#: mediagoblin/templates/mediagoblin/auth/login.html:29
msgid "Login failed!"
msgstr "L'identification a échoué !"
#: mediagoblin/templates/mediagoblin/auth/login.html:34
#: mediagoblin/templates/mediagoblin/auth/register.html:30
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
#: mediagoblin/templates/mediagoblin/submit/start.html:29
msgid "Submit"
msgstr "Soumettre"
#: 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/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
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/listings/tag.html:42
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48
#: mediagoblin/templates/mediagoblin/user_pages/user.html:104
msgid "atom feed"
msgstr "flux Atom"
#: mediagoblin/templates/mediagoblin/submit/start.html:26
msgid "Submit yer media"
msgstr "Soumettez ce média"
#: 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:53
#: 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/user.html:39
#: mediagoblin/templates/mediagoblin/user_pages/user.html:59
msgid "Verification needed"
msgstr "Vérification requise"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:42
msgid "Almost done! Your account still needs to be verified."
msgstr "C'est presque fini ! Il vous faut encore vérifier votre compte."
#: 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"
" verified."
msgstr ""
"Quelqu'un a créé un compte à ce nom, mais le compte n'a pas encore été "
"vérifié."
#: 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:86
msgid "Edit profile"
msgstr "Modifier le profil"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:98
#, python-format
msgid "View all of %(username)s's media"
msgstr "Voir tous les médias de %(username)s"
#: mediagoblin/user_pages/forms.py:24
msgid "Comment"
msgstr ""

Binary file not shown.

View File

@ -0,0 +1,310 @@
# 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-13 19:47-0500\n"
"PO-Revision-Date: 2011-08-14 00:47+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/forms.py:43
msgid "Improperly formed URL"
msgstr "不適切な形式のURL"
#: mediagoblin/edit/views.py:54
msgid "An entry with that slug already exists for this user."
msgstr "そのスラグを持つエントリは、このユーザーは既に存在します。"
#: mediagoblin/edit/views.py:75
msgid "You are editing another user's media. Proceed with caution."
msgstr "あなたは、他のユーザーのメディアを編集しています。ご注意ください。"
#: mediagoblin/edit/views.py:96
msgid "You are editing a user's profile. Proceed with caution."
msgstr "あなたは、他のユーザーのプロファイルを編集しています。ご注意ください。"
#: mediagoblin/submit/forms.py:25
msgid "File"
msgstr "ファイル"
#: mediagoblin/submit/views.py:46
msgid "You must provide a file."
msgstr "ファイルを提供する必要があります。"
#: mediagoblin/submit/views.py:49
msgid "The file doesn't seem to be an image!"
msgstr "ファイルが画像ではないようです!"
#: mediagoblin/submit/views.py:94
msgid "Woohoo! Submitted!"
msgstr "投稿終了!"
#: mediagoblin/templates/mediagoblin/base.html:22
msgid "GNU MediaGoblin"
msgstr "GNU MediaGoblin"
#: mediagoblin/templates/mediagoblin/base.html:45
msgid "Mediagoblin logo"
msgstr "MediaGoblinロゴ"
#: mediagoblin/templates/mediagoblin/base.html:51
msgid "Submit media"
msgstr "コンテンツを投稿"
#: mediagoblin/templates/mediagoblin/base.html:62
msgid "verify your email!"
msgstr "メアドを確認してください!"
#: mediagoblin/templates/mediagoblin/base.html:72
msgid "Login"
msgstr "ログイン"
#: mediagoblin/templates/mediagoblin/base.html:88
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:23
msgid "Welcome to GNU MediaGoblin!"
msgstr "GNU MediaGoblinへようこそ"
#: mediagoblin/templates/mediagoblin/root.html:28
msgid "Submit an item"
msgstr "アイテムを投稿"
#: mediagoblin/templates/mediagoblin/root.html:33
#, python-format
msgid "If you have an account, you can <a href=\"%(login_url)s\">Login</a>."
msgstr "もしアカウントが持ったら、<a href=\"%(login_url)s\">ログイン</a>できます。"
#: mediagoblin/templates/mediagoblin/root.html:39
#, python-format
msgid ""
"If you don't have an account, please <a "
"href=\"%(register_url)s\">Register</a>."
msgstr "アカウントが持っていなければ、<a href=\"%(register_url)s\">登録</a>してお願いします。"
#: mediagoblin/templates/mediagoblin/auth/login.html:26
msgid "Log in"
msgstr "ログイン"
#: mediagoblin/templates/mediagoblin/auth/login.html:29
msgid "Login failed!"
msgstr "ログイン失敗!"
#: mediagoblin/templates/mediagoblin/auth/login.html:34
#: mediagoblin/templates/mediagoblin/auth/register.html:30
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
#: mediagoblin/templates/mediagoblin/submit/start.html:29
msgid "Submit"
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/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
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/listings/tag.html:42
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48
#: mediagoblin/templates/mediagoblin/user_pages/user.html:104
msgid "atom feed"
msgstr "Atomフィード"
#: mediagoblin/templates/mediagoblin/submit/start.html:26
msgid "Submit yer media"
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:53
#: mediagoblin/templates/mediagoblin/user_pages/user.html:32
msgid "Sorry, no such user found."
msgstr "申し訳ありませんが、そのユーザーは見つかりませんでした。"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:39
#: mediagoblin/templates/mediagoblin/user_pages/user.html:59
msgid "Verification needed"
msgstr "確認必要"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:42
msgid "Almost done! Your account still needs to be verified."
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"
" verified."
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:86
msgid "Edit profile"
msgstr "プロフィールを編集"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:98
#, python-format
msgid "View all of %(username)s's media"
msgstr "%(username)sさんのコンテンツをすべて見る"
#: mediagoblin/user_pages/forms.py:24
msgid "Comment"
msgstr ""

Binary file not shown.

View File

@ -0,0 +1,308 @@
# 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-08 22:53-0500\n"
"PO-Revision-Date: 2011-08-10 21:23+0000\n"
"Last-Translator: velmont <odin.omdal@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 0.9.6\n"
"Language: 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:55
msgid "Sorry, a user with that name already exists."
msgstr "Ein konto med dette brukarnamnet finst allereide."
#: mediagoblin/auth/views.py:152
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:158
msgid "The verification key or user id is incorrect"
msgstr "Stadfestingsnykelen eller brukar-ID-en din er feil."
#: mediagoblin/auth/views.py:179
#: 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:26
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/forms.py:43
msgid "Improperly formed URL"
msgstr "Ugyldeg URL"
#: mediagoblin/edit/views.py:54
msgid "An entry with that slug already exists for this user."
msgstr "Eit innlegg med denne adressetittelen finst allereie."
#: mediagoblin/edit/views.py:75
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:96
msgid "You are editing a user's profile. Proceed with caution."
msgstr "Ver forsiktig, du redigerer ein annan konto sin profil."
#: mediagoblin/submit/forms.py:29
msgid "File"
msgstr "Fil"
#: mediagoblin/submit/views.py:45
msgid "You must provide a file."
msgstr "Du må velja ei fil."
#: mediagoblin/submit/views.py:48
msgid "The file doesn't seem to be an image!"
msgstr "Fila verkar ikkje å vera ei gyldig biletefil."
#: mediagoblin/submit/views.py:96
msgid "Woohoo! Submitted!"
msgstr "Johoo! Opplasta!"
#: mediagoblin/templates/mediagoblin/base.html:22
msgid "GNU MediaGoblin"
msgstr "GNU MediaGoblin"
#: mediagoblin/templates/mediagoblin/base.html:45
msgid "Mediagoblin logo"
msgstr "MediaGoblin-logo"
#: mediagoblin/templates/mediagoblin/base.html:51
msgid "Submit media"
msgstr "Last opp"
#: mediagoblin/templates/mediagoblin/base.html:62
msgid "verify your email!"
msgstr "Stadfest epostadressa di"
#: mediagoblin/templates/mediagoblin/base.html:72
msgid "Login"
msgstr "Logg inn"
#: mediagoblin/templates/mediagoblin/base.html:88
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:21
msgid "Welcome to GNU MediaGoblin!"
msgstr "Velkomen til GNU MediaGoblin!"
#: mediagoblin/templates/mediagoblin/root.html:26
msgid "Submit an item"
msgstr "Last opp"
#: mediagoblin/templates/mediagoblin/root.html:31
#, python-format
msgid "If you have an account, you can <a href=\"%(login_url)s\">Login</a>."
msgstr "Har du ein konto? <a href=\"%(login_url)s\">Logg inn</a>."
#: mediagoblin/templates/mediagoblin/root.html:37
#, python-format
msgid ""
"If you don't have an account, please <a "
"href=\"%(register_url)s\">Register</a>."
msgstr "Har du ingen konto? <a href=\"%(register_url)s\">Registrer deg</a>."
#: mediagoblin/templates/mediagoblin/auth/login.html:26
msgid "Log in"
msgstr "Logg inn"
#: mediagoblin/templates/mediagoblin/auth/login.html:29
msgid "Login failed!"
msgstr "Innlogging feila!"
#: mediagoblin/templates/mediagoblin/auth/login.html:34
#: mediagoblin/templates/mediagoblin/auth/register.html:30
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
#: mediagoblin/templates/mediagoblin/submit/start.html:32
msgid "Submit"
msgstr "Send"
#: 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/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
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:29
msgid "Media tagged with:"
msgstr "Merkelappar:"
#: mediagoblin/templates/mediagoblin/listings/tag.html:40
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:46
#: mediagoblin/templates/mediagoblin/user_pages/user.html:101
msgid "atom feed"
msgstr "atom-feed"
#: mediagoblin/templates/mediagoblin/submit/start.html:26
msgid "Submit yer media"
msgstr "Last opp"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30
#, 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:51
#: mediagoblin/templates/mediagoblin/user_pages/user.html:30
msgid "Sorry, no such user found."
msgstr "Fann ingen slik brukar"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:37
#: mediagoblin/templates/mediagoblin/user_pages/user.html:57
msgid "Verification needed"
msgstr "Treng stadfesting"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:40
msgid "Almost done! Your account still needs to be verified."
msgstr "Nesten klart. Du treng berre stadfesta kontoen din."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:45
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:49
msgid "In case it doesn't:"
msgstr "I tilfelle det ikkje skjer:"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:52
msgid "Resend verification email"
msgstr "Send ein ny epost"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:60
msgid ""
"Someone has registered an account with this username, but it still has to be"
" verified."
msgstr ""
"Det finst allereie ein konto med det brukarnamnet, men den kontoen treng "
"stadfesting."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:66
#, 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:76
#, python-format
msgid "%(username)s's profile"
msgstr "%(username)s sin profil"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:84
msgid "Edit profile"
msgstr "Endra profil"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:95
#, python-format
msgid "View all of %(username)s's media"
msgstr "Sjå all media frå %(username)s"

Binary file not shown.

View File

@ -0,0 +1,310 @@
# 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-08 22:53-0500\n"
"PO-Revision-Date: 2011-08-10 23:16+0000\n"
"Last-Translator: osc <snd.noise@gmail.com>\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:55
msgid "Sorry, a user with that name already exists."
msgstr "Desculpe, um usuário com este nome já existe."
#: mediagoblin/auth/views.py:152
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:158
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:179
#: 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:26
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/forms.py:43
msgid "Improperly formed URL"
msgstr ""
#: mediagoblin/edit/views.py:54
msgid "An entry with that slug already exists for this user."
msgstr ""
#: mediagoblin/edit/views.py:75
msgid "You are editing another user's media. Proceed with caution."
msgstr ""
#: mediagoblin/edit/views.py:96
msgid "You are editing a user's profile. Proceed with caution."
msgstr ""
#: mediagoblin/submit/forms.py:29
msgid "File"
msgstr "Arquivo"
#: mediagoblin/submit/views.py:45
msgid "You must provide a file."
msgstr "Você deve fornecer um arquivo."
#: mediagoblin/submit/views.py:48
msgid "The file doesn't seem to be an image!"
msgstr "O arquivo não parece ser uma imagem!"
#: mediagoblin/submit/views.py:96
msgid "Woohoo! Submitted!"
msgstr "Eba! Enviado!"
#: mediagoblin/templates/mediagoblin/base.html:22
msgid "GNU MediaGoblin"
msgstr "GNU MediaGoblin"
#: mediagoblin/templates/mediagoblin/base.html:45
msgid "Mediagoblin logo"
msgstr "Logo de Mediagoblin"
#: mediagoblin/templates/mediagoblin/base.html:51
msgid "Submit media"
msgstr "Enviar mídia"
#: mediagoblin/templates/mediagoblin/base.html:62
msgid "verify your email!"
msgstr "Verifique seu email!"
#: mediagoblin/templates/mediagoblin/base.html:72
msgid "Login"
msgstr "Login"
#: mediagoblin/templates/mediagoblin/base.html:88
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:21
msgid "Welcome to GNU MediaGoblin!"
msgstr "Bemvindo a GNU Mediagoblin!"
#: mediagoblin/templates/mediagoblin/root.html:26
msgid "Submit an item"
msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:31
#, python-format
msgid "If you have an account, you can <a href=\"%(login_url)s\">Login</a>."
msgstr "Se você tem conta, você pode <a href=\"%(login_url)s\">Entrar</a> ."
#: mediagoblin/templates/mediagoblin/root.html:37
#, python-format
msgid ""
"If you don't have an account, please <a "
"href=\"%(register_url)s\">Register</a>."
msgstr ""
"Se você não tem conta, por favor <a href=\"%(register_url)s\">Registrar</a> "
"."
#: mediagoblin/templates/mediagoblin/auth/login.html:26
msgid "Log in"
msgstr "Entrar"
#: mediagoblin/templates/mediagoblin/auth/login.html:29
msgid "Login failed!"
msgstr "Login falhou!"
#: mediagoblin/templates/mediagoblin/auth/login.html:34
#: mediagoblin/templates/mediagoblin/auth/register.html:30
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
#: mediagoblin/templates/mediagoblin/submit/start.html:32
msgid "Submit"
msgstr "Enviar"
#: 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/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
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:29
msgid "Media tagged with:"
msgstr ""
#: mediagoblin/templates/mediagoblin/listings/tag.html:40
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:46
#: mediagoblin/templates/mediagoblin/user_pages/user.html:101
msgid "atom feed"
msgstr "atom feed"
#: mediagoblin/templates/mediagoblin/submit/start.html:26
msgid "Submit yer media"
msgstr "Envie sua mídia"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30
#, python-format
msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:51
#: mediagoblin/templates/mediagoblin/user_pages/user.html:30
msgid "Sorry, no such user found."
msgstr "Desculpe, tal usuário não encontrado."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:37
#: mediagoblin/templates/mediagoblin/user_pages/user.html:57
msgid "Verification needed"
msgstr "Verificação necessária"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:40
msgid "Almost done! Your account still needs to be verified."
msgstr "Quase pronto! Sua conta precisa de verificação."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:45
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:49
msgid "In case it doesn't:"
msgstr "Caso contrário:"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:52
msgid "Resend verification email"
msgstr "Reenviar email de verificação"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:60
msgid ""
"Someone has registered an account with this username, but it still has to be"
" verified."
msgstr ""
"Alguém já registrou uma conta com este nome, mas ainda tem que ser "
"verificada."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:66
#, 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:76
#, python-format
msgid "%(username)s's profile"
msgstr "Perfil de %(username)s"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:84
msgid "Edit profile"
msgstr "Editar perfil"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:95
#, python-format
msgid "View all of %(username)s's media"
msgstr ""

Binary file not shown.

View File

@ -0,0 +1,314 @@
# 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-08 22:53-0500\n"
"PO-Revision-Date: 2011-08-10 21:52+0000\n"
"Last-Translator: gap <gapop@hotmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"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:55
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:152
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:158
msgid "The verification key or user id is incorrect"
msgstr "Cheie de verificare sau user ID incorect."
#: mediagoblin/auth/views.py:179
#: 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:26
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/forms.py:43
msgid "Improperly formed URL"
msgstr "Adresă URL incorectă"
#: mediagoblin/edit/views.py:54
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:75
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:96
msgid "You are editing a user's profile. Proceed with caution."
msgstr "Editați profilul unui utilizator. Se recomandă prudență."
#: mediagoblin/submit/forms.py:29
msgid "File"
msgstr "Fișier"
#: mediagoblin/submit/views.py:45
msgid "You must provide a file."
msgstr "Trebuie să selectați un fișier."
#: mediagoblin/submit/views.py:48
msgid "The file doesn't seem to be an image!"
msgstr "Fișierul nu pare a fi o imagine!"
#: mediagoblin/submit/views.py:96
msgid "Woohoo! Submitted!"
msgstr "Gata, trimis!"
#: mediagoblin/templates/mediagoblin/base.html:22
msgid "GNU MediaGoblin"
msgstr "GNU MediaGoblin"
#: mediagoblin/templates/mediagoblin/base.html:45
msgid "Mediagoblin logo"
msgstr "Logo MediaGoblin"
#: mediagoblin/templates/mediagoblin/base.html:51
msgid "Submit media"
msgstr "Transmiteți fișier"
#: mediagoblin/templates/mediagoblin/base.html:62
msgid "verify your email!"
msgstr "verificați e-mail-ul!"
#: mediagoblin/templates/mediagoblin/base.html:72
msgid "Login"
msgstr "Autentificare"
#: mediagoblin/templates/mediagoblin/base.html:88
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:21
msgid "Welcome to GNU MediaGoblin!"
msgstr "Bun venit la GNU MediaGoblin!"
#: mediagoblin/templates/mediagoblin/root.html:26
msgid "Submit an item"
msgstr "Trimite un fișier"
#: mediagoblin/templates/mediagoblin/root.html:31
#, python-format
msgid "If you have an account, you can <a href=\"%(login_url)s\">Login</a>."
msgstr ""
"Dacă aveți deja un cont, vă puteți <a "
"href=\"%(login_url)s\">autentifica</a>."
#: mediagoblin/templates/mediagoblin/root.html:37
#, python-format
msgid ""
"If you don't have an account, please <a "
"href=\"%(register_url)s\">Register</a>."
msgstr ""
"Dacă nu aveți cont, vă rugăm să vă <a "
"href=\"%(register_url)s\">înregistrați</a>."
#: mediagoblin/templates/mediagoblin/auth/login.html:26
msgid "Log in"
msgstr "Autentificare"
#: mediagoblin/templates/mediagoblin/auth/login.html:29
msgid "Login failed!"
msgstr "Autentificare nereușită!"
#: mediagoblin/templates/mediagoblin/auth/login.html:34
#: mediagoblin/templates/mediagoblin/auth/register.html:30
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
#: mediagoblin/templates/mediagoblin/submit/start.html:32
msgid "Submit"
msgstr "Trimite"
#: 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/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
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:29
msgid "Media tagged with:"
msgstr "Etichete:"
#: mediagoblin/templates/mediagoblin/listings/tag.html:40
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:46
#: mediagoblin/templates/mediagoblin/user_pages/user.html:101
msgid "atom feed"
msgstr "flux atom"
#: mediagoblin/templates/mediagoblin/submit/start.html:26
msgid "Submit yer media"
msgstr "Trimite fișierele tale"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30
#, python-format
msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media"
msgstr "Fișierele lui <a href=\"%(user_url)s\">%(username)s</a>"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:51
#: mediagoblin/templates/mediagoblin/user_pages/user.html:30
msgid "Sorry, no such user found."
msgstr "Ne pare rău, nu am găsit utilizatorul căutat."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:37
#: mediagoblin/templates/mediagoblin/user_pages/user.html:57
msgid "Verification needed"
msgstr "Confirmare necesară"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:40
msgid "Almost done! Your account still needs to be verified."
msgstr "Aproape gata! Este necesară confirmarea contului dvs."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:45
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:49
msgid "In case it doesn't:"
msgstr "Dacă nu primiți mesajul:"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:52
msgid "Resend verification email"
msgstr "Retrimite mesajul de verificare"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:60
msgid ""
"Someone has registered an account with this username, but it still has to be"
" verified."
msgstr ""
"Cineva s-a înscris pe site cu acest nume de utilizator, dar nu a fost "
"confirmat încă."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:66
#, 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:76
#, python-format
msgid "%(username)s's profile"
msgstr "Profil %(username)s"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:84
msgid "Edit profile"
msgstr "Editare profil"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:95
#, python-format
msgid "View all of %(username)s's media"
msgstr "Toate fișierele lui %(username)s"

Binary file not shown.

View File

@ -0,0 +1,309 @@
# 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-08 22:53-0500\n"
"PO-Revision-Date: 2011-08-10 21:28+0000\n"
"Last-Translator: JLP <jlp@holodeck1.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 0.9.6\n"
"Language: 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:55
msgid "Sorry, a user with that name already exists."
msgstr "Oprostite, uporabnik s tem imenom že obstaja."
#: mediagoblin/auth/views.py:152
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:158
msgid "The verification key or user id is incorrect"
msgstr "Potrditveni ključ ali uporabniška identifikacija je napačna"
#: mediagoblin/auth/views.py:179
#: 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:26
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/forms.py:43
msgid "Improperly formed URL"
msgstr "Napačno oblikovan URL"
#: mediagoblin/edit/views.py:54
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:75
msgid "You are editing another user's media. Proceed with caution."
msgstr "Urejate vsebino drugega uporabnika. Nadaljujte pazljivo."
#: mediagoblin/edit/views.py:96
msgid "You are editing a user's profile. Proceed with caution."
msgstr "Urejate uporabniški profil. Nadaljujte pazljivo."
#: mediagoblin/submit/forms.py:29
msgid "File"
msgstr "Datoteka"
#: mediagoblin/submit/views.py:45
msgid "You must provide a file."
msgstr "Podati morate datoteko."
#: mediagoblin/submit/views.py:48
msgid "The file doesn't seem to be an image!"
msgstr "Kot kaže datoteka ni slika."
#: mediagoblin/submit/views.py:96
msgid "Woohoo! Submitted!"
msgstr "Juhej! Poslano."
#: mediagoblin/templates/mediagoblin/base.html:22
msgid "GNU MediaGoblin"
msgstr "GNU MediaGoblin"
#: mediagoblin/templates/mediagoblin/base.html:45
msgid "Mediagoblin logo"
msgstr "Logotip MediaGoblin"
#: mediagoblin/templates/mediagoblin/base.html:51
msgid "Submit media"
msgstr "Pošlji vsebino"
#: mediagoblin/templates/mediagoblin/base.html:62
msgid "verify your email!"
msgstr "Preverite svojo e-pošto."
#: mediagoblin/templates/mediagoblin/base.html:72
msgid "Login"
msgstr "Prijava"
#: mediagoblin/templates/mediagoblin/base.html:88
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:21
msgid "Welcome to GNU MediaGoblin!"
msgstr "Dobrodošli v GNU MediaGoblin!"
#: mediagoblin/templates/mediagoblin/root.html:26
msgid "Submit an item"
msgstr "Pošljite datoteko"
#: mediagoblin/templates/mediagoblin/root.html:31
#, python-format
msgid "If you have an account, you can <a href=\"%(login_url)s\">Login</a>."
msgstr "Če imate račun, se lahko <a href=\"%(login_url)s\">Prijavite</a>."
#: mediagoblin/templates/mediagoblin/root.html:37
#, python-format
msgid ""
"If you don't have an account, please <a "
"href=\"%(register_url)s\">Register</a>."
msgstr "Če računa še nimate, se <a href=\"%(register_url)s\">Registrirajte</a>."
#: mediagoblin/templates/mediagoblin/auth/login.html:26
msgid "Log in"
msgstr "Prijava"
#: mediagoblin/templates/mediagoblin/auth/login.html:29
msgid "Login failed!"
msgstr "Neuspešna prijava."
#: mediagoblin/templates/mediagoblin/auth/login.html:34
#: mediagoblin/templates/mediagoblin/auth/register.html:30
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
#: mediagoblin/templates/mediagoblin/submit/start.html:32
msgid "Submit"
msgstr "Pošlji"
#: 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/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
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:29
msgid "Media tagged with:"
msgstr "Vsebina označena z:"
#: mediagoblin/templates/mediagoblin/listings/tag.html:40
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:46
#: mediagoblin/templates/mediagoblin/user_pages/user.html:101
msgid "atom feed"
msgstr "Vir Atom"
#: mediagoblin/templates/mediagoblin/submit/start.html:26
msgid "Submit yer media"
msgstr "Pošljite svojo vsebino"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30
#, 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:51
#: mediagoblin/templates/mediagoblin/user_pages/user.html:30
msgid "Sorry, no such user found."
msgstr "Oprostite, tega uporabnika ni bilo moč najti."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:37
#: mediagoblin/templates/mediagoblin/user_pages/user.html:57
msgid "Verification needed"
msgstr "Potrebna je potrditev"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:40
msgid "Almost done! Your account still needs to be verified."
msgstr "Skoraj ste zaključili. Račun je potrebno le še potrditi."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:45
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:49
msgid "In case it doesn't:"
msgstr "Če je ne prejmete:"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:52
msgid "Resend verification email"
msgstr "Ponovno pošlji potrditveno e-pošto"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:60
msgid ""
"Someone has registered an account with this username, but it still has to be"
" verified."
msgstr ""
"Nekdo je s tem uporabniškim imenom že registriral račun, vendar mora biti še"
" potrjen."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:66
#, 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:76
#, python-format
msgid "%(username)s's profile"
msgstr "Profil %(username)s"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:84
msgid "Edit profile"
msgstr "Uredi profil"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:95
#, python-format
msgid "View all of %(username)s's media"
msgstr "Prikaži vso vsebino uporabnika %(username)s"

Binary file not shown.

View File

@ -0,0 +1,294 @@
# 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-08 22:53-0500\n"
"PO-Revision-Date: 2011-08-09 03:57+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:55
msgid "Sorry, a user with that name already exists."
msgstr ""
#: mediagoblin/auth/views.py:152
msgid ""
"Your email address has been verified. You may now login, edit your profile, "
"and submit images!"
msgstr ""
#: mediagoblin/auth/views.py:158
msgid "The verification key or user id is incorrect"
msgstr ""
#: mediagoblin/auth/views.py:179
#: mediagoblin/templates/mediagoblin/auth/resent_verification_email.html:22
msgid "Resent your verification email."
msgstr ""
#: mediagoblin/edit/forms.py:26 mediagoblin/submit/forms.py:26
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/forms.py:43
msgid "Improperly formed URL"
msgstr ""
#: mediagoblin/edit/views.py:54
msgid "An entry with that slug already exists for this user."
msgstr ""
#: mediagoblin/edit/views.py:75
msgid "You are editing another user's media. Proceed with caution."
msgstr ""
#: mediagoblin/edit/views.py:96
msgid "You are editing a user's profile. Proceed with caution."
msgstr ""
#: mediagoblin/submit/forms.py:29
msgid "File"
msgstr ""
#: mediagoblin/submit/views.py:45
msgid "You must provide a file."
msgstr ""
#: mediagoblin/submit/views.py:48
msgid "The file doesn't seem to be an image!"
msgstr ""
#: mediagoblin/submit/views.py:96
msgid "Woohoo! Submitted!"
msgstr ""
#: mediagoblin/templates/mediagoblin/base.html:22
msgid "GNU MediaGoblin"
msgstr ""
#: mediagoblin/templates/mediagoblin/base.html:45
msgid "Mediagoblin logo"
msgstr ""
#: mediagoblin/templates/mediagoblin/base.html:51
msgid "Submit media"
msgstr ""
#: mediagoblin/templates/mediagoblin/base.html:62
msgid "verify your email!"
msgstr ""
#: mediagoblin/templates/mediagoblin/base.html:72
msgid "Login"
msgstr ""
#: mediagoblin/templates/mediagoblin/base.html:88
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:21
msgid "Welcome to GNU MediaGoblin!"
msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:26
msgid "Submit an item"
msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:31
#, python-format
msgid "If you have an account, you can <a href=\"%(login_url)s\">Login</a>."
msgstr ""
#: mediagoblin/templates/mediagoblin/root.html:37
#, python-format
msgid ""
"If you don't have an account, please <a "
"href=\"%(register_url)s\">Register</a>."
msgstr ""
#: mediagoblin/templates/mediagoblin/auth/login.html:26
msgid "Log in"
msgstr ""
#: mediagoblin/templates/mediagoblin/auth/login.html:29
msgid "Login failed!"
msgstr ""
#: mediagoblin/templates/mediagoblin/auth/login.html:34
#: mediagoblin/templates/mediagoblin/auth/register.html:30
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
#: mediagoblin/templates/mediagoblin/submit/start.html:32
msgid "Submit"
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/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
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:29
msgid "Media tagged with:"
msgstr ""
#: mediagoblin/templates/mediagoblin/listings/tag.html:40
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:46
#: mediagoblin/templates/mediagoblin/user_pages/user.html:101
msgid "atom feed"
msgstr ""
#: mediagoblin/templates/mediagoblin/submit/start.html:26
msgid "Submit yer media"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30
#, python-format
msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:51
#: mediagoblin/templates/mediagoblin/user_pages/user.html:30
msgid "Sorry, no such user found."
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/user.html:37
#: mediagoblin/templates/mediagoblin/user_pages/user.html:57
msgid "Verification needed"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/user.html:40
msgid "Almost done! Your account still needs to be verified."
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/user.html:45
msgid ""
"An email should arrive in a few moments with instructions on how to do so."
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/user.html:49
msgid "In case it doesn't:"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/user.html:52
msgid "Resend verification email"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/user.html:60
msgid ""
"Someone has registered an account with this username, but it still has to be"
" verified."
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/user.html:66
#, 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:76
#, python-format
msgid "%(username)s's profile"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/user.html:84
msgid "Edit profile"
msgstr ""
#: mediagoblin/templates/mediagoblin/user_pages/user.html:95
#, python-format
msgid "View all of %(username)s's media"
msgstr ""

Binary file not shown.

View File

@ -0,0 +1,319 @@
# 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-13 19:47-0500\n"
"PO-Revision-Date: 2011-08-16 13:22+0000\n"
"Last-Translator: joar <transifex@wandborg.se>\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/forms.py:43
msgid "Improperly formed URL"
msgstr "Ogiltig URL"
#: mediagoblin/edit/views.py:54
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:75
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:96
msgid "You are editing a user's profile. Proceed with caution."
msgstr "Var försiktig, du redigerar en annan användares profil."
#: mediagoblin/submit/forms.py:25
msgid "File"
msgstr "Fil"
#: mediagoblin/submit/views.py:46
msgid "You must provide a file."
msgstr "Du måste ange en fil"
#: mediagoblin/submit/views.py:49
msgid "The file doesn't seem to be an image!"
msgstr "Filen verkar inte vara en giltig bildfil!"
#: mediagoblin/submit/views.py:94
msgid "Woohoo! Submitted!"
msgstr "Tjohoo! Upladdat!"
#: mediagoblin/templates/mediagoblin/base.html:22
msgid "GNU MediaGoblin"
msgstr "GNU MediaGoblin"
#: mediagoblin/templates/mediagoblin/base.html:45
msgid "Mediagoblin logo"
msgstr "MediaGoblin logo"
#: mediagoblin/templates/mediagoblin/base.html:51
msgid "Submit media"
msgstr "Ladda upp"
#: mediagoblin/templates/mediagoblin/base.html:62
msgid "verify your email!"
msgstr "Verifiera din e-postadress!"
#: mediagoblin/templates/mediagoblin/base.html:72
msgid "Login"
msgstr "Logga in"
#: mediagoblin/templates/mediagoblin/base.html:88
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:23
msgid "Welcome to GNU MediaGoblin!"
msgstr "Välkommen till GNU MediaGoblin!"
#: mediagoblin/templates/mediagoblin/root.html:28
msgid "Submit an item"
msgstr "Ladda upp"
#: mediagoblin/templates/mediagoblin/root.html:33
#, python-format
msgid "If you have an account, you can <a href=\"%(login_url)s\">Login</a>."
msgstr "Har du ett konto? <a href=\"%(login_url)s\">Logga in</a>."
#: mediagoblin/templates/mediagoblin/root.html:39
#, python-format
msgid ""
"If you don't have an account, please <a "
"href=\"%(register_url)s\">Register</a>."
msgstr ""
"Har du inget konto? <a href=\"%(register_url)s\">Registrera ett konto</a>."
#: mediagoblin/templates/mediagoblin/auth/login.html:26
msgid "Log in"
msgstr "Logga in"
#: mediagoblin/templates/mediagoblin/auth/login.html:29
msgid "Login failed!"
msgstr "Inloggning misslyckades!"
#: mediagoblin/templates/mediagoblin/auth/login.html:34
#: mediagoblin/templates/mediagoblin/auth/register.html:30
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
#: mediagoblin/templates/mediagoblin/submit/start.html:29
msgid "Submit"
msgstr "Skicka"
#: 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/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
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/listings/tag.html:42
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48
#: mediagoblin/templates/mediagoblin/user_pages/user.html:104
msgid "atom feed"
msgstr "atom-feed"
#: mediagoblin/templates/mediagoblin/submit/start.html:26
msgid "Submit yer media"
msgstr "Ladda upp"
#: 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:53
#: 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/user.html:39
#: mediagoblin/templates/mediagoblin/user_pages/user.html:59
msgid "Verification needed"
msgstr "Verifiering krävs"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:42
msgid "Almost done! Your account still needs to be verified."
msgstr "Nästan klart! Nu behöver du bara verifiera ditt konto."
#: 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"
" verified."
msgstr ""
"Det finns redan ett konto med det här användarnamnet, men det behöver "
"verifieras."
#: 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:86
msgid "Edit profile"
msgstr "Redigera profil"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:98
#, python-format
msgid "View all of %(username)s's media"
msgstr "Se all media från %(username)s"
#: mediagoblin/user_pages/forms.py:24
msgid "Comment"
msgstr "Kommentar"

Binary file not shown.

View File

@ -0,0 +1,310 @@
# 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-13 19:47-0500\n"
"PO-Revision-Date: 2011-08-14 00:47+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/forms.py:43
msgid "Improperly formed URL"
msgstr "部正確的網址"
#: mediagoblin/edit/views.py:54
msgid "An entry with that slug already exists for this user."
msgstr "這個自訂字串已經被其他人用了"
#: mediagoblin/edit/views.py:75
msgid "You are editing another user's media. Proceed with caution."
msgstr "你正在編輯他人的媒體檔案. 請謹慎處理."
#: mediagoblin/edit/views.py:96
msgid "You are editing a user's profile. Proceed with caution."
msgstr "你正在編輯他人的檔案. 請謹慎處理."
#: mediagoblin/submit/forms.py:25
msgid "File"
msgstr "檔案"
#: mediagoblin/submit/views.py:46
msgid "You must provide a file."
msgstr "你必須提供一個檔案"
#: mediagoblin/submit/views.py:49
msgid "The file doesn't seem to be an image!"
msgstr "檔案看起來不像是一個圖片喔!"
#: mediagoblin/submit/views.py:94
msgid "Woohoo! Submitted!"
msgstr "喔耶! 送出去了!"
#: mediagoblin/templates/mediagoblin/base.html:22
msgid "GNU MediaGoblin"
msgstr "GNU MediaGoblin"
#: mediagoblin/templates/mediagoblin/base.html:45
msgid "Mediagoblin logo"
msgstr "Mediagoblin 標誌"
#: mediagoblin/templates/mediagoblin/base.html:51
msgid "Submit media"
msgstr "送出媒體"
#: mediagoblin/templates/mediagoblin/base.html:62
msgid "verify your email!"
msgstr "確認您的電子郵件!"
#: mediagoblin/templates/mediagoblin/base.html:72
msgid "Login"
msgstr "登入"
#: mediagoblin/templates/mediagoblin/base.html:88
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:23
msgid "Welcome to GNU MediaGoblin!"
msgstr "GNU MediaGoblin 歡迎您!"
#: mediagoblin/templates/mediagoblin/root.html:28
msgid "Submit an item"
msgstr "送出一個項目"
#: mediagoblin/templates/mediagoblin/root.html:33
#, python-format
msgid "If you have an account, you can <a href=\"%(login_url)s\">Login</a>."
msgstr "如果您有帳號了, 你可以直接 <a href=\"%(login_url)s\">登入</a>."
#: mediagoblin/templates/mediagoblin/root.html:39
#, python-format
msgid ""
"If you don't have an account, please <a "
"href=\"%(register_url)s\">Register</a>."
msgstr "如果您尚未取得帳號, 請 <a href=\"%(register_url)s\">註冊</a>."
#: mediagoblin/templates/mediagoblin/auth/login.html:26
msgid "Log in"
msgstr "登入"
#: mediagoblin/templates/mediagoblin/auth/login.html:29
msgid "Login failed!"
msgstr "登入錯誤"
#: mediagoblin/templates/mediagoblin/auth/login.html:34
#: mediagoblin/templates/mediagoblin/auth/register.html:30
#: mediagoblin/templates/mediagoblin/edit/edit_profile.html:35
#: mediagoblin/templates/mediagoblin/submit/start.html:29
msgid "Submit"
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/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
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/listings/tag.html:42
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:48
#: mediagoblin/templates/mediagoblin/user_pages/user.html:104
msgid "atom feed"
msgstr "atom feed"
#: mediagoblin/templates/mediagoblin/submit/start.html:26
msgid "Submit yer media"
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:53
#: mediagoblin/templates/mediagoblin/user_pages/user.html:32
msgid "Sorry, no such user found."
msgstr "抱歉, 找不到這個使用者."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:39
#: mediagoblin/templates/mediagoblin/user_pages/user.html:59
msgid "Verification needed"
msgstr "需要驗證"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:42
msgid "Almost done! Your account still needs to be verified."
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"
" verified."
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:86
msgid "Edit profile"
msgstr "編輯個人檔案"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:98
#, python-format
msgid "View all of %(username)s's media"
msgstr "查看%(username)s的全部媒體檔案"
#: mediagoblin/user_pages/forms.py:24
msgid "Comment"
msgstr ""

View File

@ -112,10 +112,15 @@ def get_staticdirector(app_config):
def setup_storage():
app_config = mg_globals.app_config
global_config = mg_globals.global_config
public_store = storage_system_from_config(app_config, 'publicstore')
queue_store = storage_system_from_config(app_config, 'queuestore')
key_short = 'publicstore'
key_long = "storage:" + key_short
public_store = storage_system_from_config(global_config[key_long])
key_short = 'queuestore'
key_long = "storage:" + key_short
queue_store = storage_system_from_config(global_config[key_long])
setup_globals(
public_store = public_store,

View File

@ -15,10 +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 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,19 +36,106 @@ def create_pub_filepath(entry, filename):
filename])
@task
def process_media_initial(media_id):
workbench = mgg.workbench_manager.create_workbench()
@contextmanager
def closing(callback):
try:
yield callback
finally:
pass
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":
@ -53,14 +144,12 @@ def process_media_initial(media_id):
thumb_filepath = create_pub_filepath(entry, 'thumbnail.jpg')
thumb_file = mgg.public_store.get_file(thumb_filepath, 'w')
with thumb_file:
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
@ -73,7 +162,7 @@ def process_media_initial(media_id):
medium_filepath = create_pub_filepath(entry, 'medium.jpg')
medium_file = mgg.public_store.get_file(medium_filepath, 'w')
with medium_file:
with closing(medium_file):
medium.save(medium_file, "JPEG", quality=90)
medium_processed = True
@ -84,7 +173,7 @@ def process_media_initial(media_id):
with queued_file:
original_filepath = create_pub_filepath(entry, queued_filepath[-1])
with mgg.public_store.get_file(original_filepath, 'wb') as original_file:
with closing(mgg.public_store.get_file(original_filepath, 'wb')) as original_file:
original_file.write(queued_file.read())
mgg.queue_store.delete_file(queued_filepath)
@ -94,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()

View File

@ -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.')

View File

@ -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;
}
.header_submit{
a.mediagoblin_logo{
color: #fff;
font-weight: bold;
}
.header_submit, .header_submit_highlight{
color: #272727;
background-color: #aaa;
background-image: -webkit-gradient(linear, left top, left bottom, from(##D2D2D2), to(#aaa));
@ -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;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 413 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 522 B

After

Width:  |  Height:  |  Size: 378 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 839 B

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -15,10 +15,10 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import re
import shutil
import urlparse
import uuid
import cloudfiles
from werkzeug.utils import secure_filename
@ -28,11 +28,21 @@ from mediagoblin import util
# Errors
########
class Error(Exception): pass
class InvalidFilepath(Error): pass
class NoWebServing(Error): pass
class NotImplementedError(Error): pass
class Error(Exception):
pass
class InvalidFilepath(Error):
pass
class NoWebServing(Error):
pass
class NotImplementedError(Error):
pass
###############################################
@ -117,7 +127,7 @@ class StorageInterface(object):
Eg, if the filename doesn't exist:
>>> storage_handler.get_unique_filename(['dir1', 'dir2', 'fname.jpg'])
[u'dir1', u'dir2', u'fname.jpg']
But if a file does exist, let's get one back with at uuid tacked on:
>>> storage_handler.get_unique_filename(['dir1', 'dir2', 'fname.jpg'])
[u'dir1', u'dir2', u'd02c3571-dd62-4479-9d62-9e3012dada29-fname.jpg']
@ -184,7 +194,7 @@ class BasicFileStorage(StorageInterface):
"""
return os.path.join(
self.base_dir, *clean_listy_filepath(filepath))
def file_exists(self, filepath):
return os.path.exists(self._resolve_filepath(filepath))
@ -216,6 +226,204 @@ class BasicFileStorage(StorageInterface):
return self._resolve_filepath(filepath)
class CloudFilesStorage(StorageInterface):
def __init__(self, **kwargs):
self.param_container = kwargs.get('cloudfiles_container')
self.param_user = kwargs.get('cloudfiles_user')
self.param_api_key = kwargs.get('cloudfiles_api_key')
self.param_host = kwargs.get('cloudfiles_host')
self.param_use_servicenet = kwargs.get('cloudfiles_use_servicenet')
if not self.param_host:
print('No CloudFiles host URL specified, '
'defaulting to Rackspace US')
self.connection = cloudfiles.get_connection(
username=self.param_user,
api_key=self.param_api_key,
servicenet=True if self.param_use_servicenet == 'true' or \
self.param_use_servicenet == True else False)
if not self.param_container == \
self.connection.get_container(self.param_container):
self.container = self.connection.create_container(
self.param_container)
self.container.make_public(
ttl=60 * 60 * 2)
else:
self.container = self.connection.get_container(
self.param_container)
def _resolve_filepath(self, filepath):
return '/'.join(
clean_listy_filepath(filepath))
def file_exists(self, filepath):
try:
object = self.container.get_object(
self._resolve_filepath(filepath))
return True
except cloudfiles.errors.NoSuchObject:
return False
def get_file(self, filepath, mode='r'):
try:
obj = self.container.get_object(
self._resolve_filepath(filepath))
except cloudfiles.errors.NoSuchObject:
obj = self.container.create_object(
self._resolve_filepath(filepath))
return obj
def delete_file(self, filepath):
# TODO: Also delete unused directories if empty (safely, with
# checks to avoid race conditions).
self.container.delete_object(filepath)
def file_url(self, filepath):
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
###########
@ -247,43 +455,36 @@ 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))
# This construct is needed, because dict(config) does
# not replace the variables in the config items.
config_params = dict(config_section.iteritems())
config_params = dict(
[(prefix_re.match(key).groups()[0], value)
for key, value in paste_config.iteritems()
if prefix_re.match(key)])
if config_params.has_key('storage_class'):
if 'storage_class' in config_params:
storage_class = config_params['storage_class']
config_params.pop('storage_class')
else:
@ -291,5 +492,3 @@ def storage_system_from_config(paste_config, storage_prefix):
storage_class = util.import_component(storage_class)
return storage_class(**config_params)

View File

@ -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])

View File

@ -14,22 +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
from datetime import datetime
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
@ -45,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]))
@ -69,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()
@ -91,12 +87,39 @@ def submit_start(request):
# Add queued filename to the entry
entry['queued_media_file'] = queue_filepath
# 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)
# queue it for processing
process_media_initial.delay(unicode(entry['_id']))
# 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!')
add_message(request, SUCCESS, _('Woohoo! Submitted!'))
return redirect(request, "mediagoblin.user_pages.user_home",
user = request.user['username'])

View File

@ -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 %}

View File

@ -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>

View File

@ -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>

View File

@ -19,6 +19,6 @@
{% block mediagoblin_content %}
<p>
Resent your verification email.
{% trans %}Resent your verification email.{% endtrans %}
</p>
{% endblock %}

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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>

View File

@ -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>

View File

@ -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 %}

View File

@ -17,27 +17,36 @@
#}
{% extends "mediagoblin/base.html" %}
{% from "mediagoblin/utils/object_gallery.html" import object_gallery %}
{% block mediagoblin_content %}
<h1>{% trans %}Welcome to GNU MediaGoblin!{% endtrans %}</h1>
{% 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 %}
<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. (Were a <a href="http://gnu.org">GNU project</a> in the making, 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>
{% 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>
<div class="grid_5 omega">
<img src="{{ request.staticdirect('/images/frontpage_image.png') }}" />
</div>
<div class="clear"></div>
{% endif %}
{# temporarily, an "image gallery" that isn't one really ;) #}
{% include "mediagoblin/utils/object_gallery.html" %}
<h2>Most recent media</h2>
{{ object_gallery(request, media_entries, pagination) }}
{% endblock %}

View File

@ -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>

View File

@ -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 %}

View File

@ -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,45 +116,42 @@
<div class="grid_5 omega">
{% include "mediagoblin/utils/prev_next.html" %}
<h3>Sidebar content here!</h3>
{% if media.attachment_files or media['uploader'] == request.user['_id'] or
request.user['is_admin'] %}
<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 %}
{% endif %}
</ul>
<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'] %}
{% if app_config['allow_attachments']
and (media['uploader'] == request.user['_id']
or request.user['is_admin']) %}
<a href="{{ request.urlgen('mediagoblin.edit.attachments',
user= media.uploader().username,
media= media._id) }}">Add attachment</a>
user=media.uploader().username,
media=media._id) }}">Add attachment</a>
{% endif %}
{% if media.tags %}
@ -149,6 +159,6 @@
{% endif %}
</div>
{% else %}
<p>Sorry, no such media found.<p/>
<p>{% trans %}Sorry, no such media found.{% endtrans %}<p/>
{% endif %}
{% endblock %}

View File

@ -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 %}

View File

@ -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 %}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 verified.
{%- endtrans %}
</p>
<p>In case it doesn't:</p>
<p>
{% trans -%}
An email should arrive in a few moments with instructions on how to do so.
{%- endtrans %}
</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 %}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 verified.
{%- 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 %}

View File

@ -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>

View File

@ -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 %}

View File

@ -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">

View File

@ -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 %}

View File

@ -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]
queuestore_base_dir = %(here)s/test_user_dev/media/queue
[celery]
celery_always_eager = true

View File

@ -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

View File

@ -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')

View File

@ -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 ""

View File

@ -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()])

View File

@ -36,4 +36,8 @@ user_routes = [
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"),
]

View File

@ -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
@ -19,7 +19,8 @@ from webob import exc
from mediagoblin import messages, mg_globals
from mediagoblin.db.util import DESCENDING, ObjectId
from mediagoblin.util import (
Pagination, render_to_response, redirect, cleaned_markdown_conversion)
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,
@ -155,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'],
@ -176,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})

View File

@ -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):
@ -300,7 +307,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):
@ -341,8 +348,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
@ -478,6 +487,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):
@ -566,3 +635,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)

View File

@ -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

View File

@ -44,6 +44,7 @@ setup(
'webtest',
'ConfigObj',
'Markdown',
'python-cloudfiles',
## For now we're expecting that users will install this from
## their package managers.
# 'lxml',
@ -52,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