Merge branch 'master' into processing

This commit is contained in:
Christopher Allan Webber 2011-08-10 19:53:37 -05:00
commit 852d5bb238
119 changed files with 5327 additions and 1171 deletions

3
.gitignore vendored
View File

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

60
COPYING
View File

@ -2,30 +2,56 @@
COPYING COPYING
========= =========
GNU MediaGoblin is composed of the following kinds of files: 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.
* software files: Python, JavaScript and HTML templates This program is distributed in the hope that it will be useful, but
* non-software data: CSS, images, and video WITHOUT ANY WARRANTY; without even the implied warranty of
* documentation 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, in the file ``licenses/AGPLv3.txt``.
If not, see <http://www.gnu.org/licenses/>.
Software files JavaScript files located in the ``mediagoblin/`` directory tree of
============== are free software: you can redistribute and/or modify them under the
terms of the GNU Lesser General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
Python, JavaScript, and template files files are released under the You should have received a copy of the GNU Lesser General Public
AGPL v3. The text of this license is located in ``AGPLv3.txt``. License along with this program, in the file ``licenses/LGPLv3.txt``.
If not, see <http://www.gnu.org/licenses/>.
Non-software data Documentation files located in the ``docs/`` directory tree are released
================= under a CC0 license. To the extent possible under law, the author(s)
have dedicated all copyright and related and neighboring rights to these
files to the public domain worldwide. These files are distributed
without any warranty.
CSS, images and video are all released under a CC0 license. The text You should have received a copy of the CC0 license in the file
of this license is located in ``CC0_1.0.txt``. ``licenses/CC0_1.0.txt``. If not, see
<http://creativecommons.org/publicdomain/zero/1.0/>.
Documentation CSS, images and video located in the ``mediagoblin/`` directory tree are
============= released under a CC0 license. To the extent possible under law, the author(s)
have dedicated all copyright and related and neighboring rights to these
files to the public domain worldwide. These files are distributed without
any warranty.
All documentation is under the ``docs/`` directory. These materials You should have received a copy of the CC0 license in the file
are all released under a CC0 license. The text of this license is ``licenses/CC0_1.0.txt``. If not, see
located in ``CC0_1.0.txt``. <http://creativecommons.org/publicdomain/zero/1.0/>.
Additional library software has been made available in the ``extlib/``
directory. All of it is Free Software and can be distributed under
liberal terms, but those terms may differ in detail from the AGPL's
particulars. See each package's license file in the extlib directory
for additional terms.

12
README
View File

@ -12,7 +12,7 @@ What is GNU MediaGoblin?
* Federated with OStatus! * Federated with OStatus!
* Customizable! * Customizable!
* A place for people to collaborate and show off original and derived * A place for people to collaborate and show off original and derived
creations. Free, as in freedom. Were a GNU project in the making, creations. Free, as in freedom. Were a GNU project in the making,
afterall. afterall.
@ -33,6 +33,10 @@ hang out, see `our Join page <http://mediagoblin.org/join/>`_
Where is the documentation? Where is the documentation?
=========================== ===========================
Documentation is located in the ``docs/`` directory in a "raw" The beginnings of a user manual is located in the ``docs/`` directory
restructured-text form. It is also mirrored at in HTML, Texinfo, and source (Restructured Text) forms. It's also
http://docs.mediagoblin.org/ in HTML form. available online at http://docs.mediagoblin.org/ in HTML form.
Contributor/developer documentation as well as documentation on the
project processes and infrastructure is located on
`the wiki <http://wiki.mediagoblin.org/>`_.

View File

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

View File

@ -1,22 +0,0 @@
#!./bin/python
import pymongo
import sys, os
print "*** WARNING! ***"
print " Running this will destroy your mediagoblin database,"
print " remove all your media files in user_dev/, etc."
drop_it = raw_input(
'Are you SURE you want to destroy your environment? (if so, type "yes")> ')
if not drop_it == 'yes':
sys.exit(1)
conn = pymongo.Connection()
conn.drop_database('mediagoblin')
os.popen('rm -rf user_dev/media')
os.popen('rm -rf user_dev/beaker')
print "removed all your stuff! okay, now re-run ./bin/buildout"

View File

@ -5,14 +5,16 @@
SPHINXOPTS = SPHINXOPTS =
SPHINXBUILD = sphinx-build SPHINXBUILD = sphinx-build
PAPER = PAPER =
BUILDDIR = _build BUILDDIR = build
# Internal variables. # Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
help: help:
@echo "Please use \`make <target>' where <target> is one of" @echo "Please use \`make <target>' where <target> is one of"
@ -32,6 +34,9 @@ help:
@echo " changes to make an overview of all changed/added/deprecated items" @echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity" @echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)" @echo " doctest to run all doctests embedded in the documentation (if enabled)"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
clean: clean:
-rm -rf $(BUILDDIR)/* -rm -rf $(BUILDDIR)/*
@ -113,6 +118,24 @@ man:
@echo @echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man." @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes: changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo @echo

View File

@ -1,329 +0,0 @@
.. _design-decisions-chapter:
==================
Design Decisions
==================
.. contents:: Sections
:local:
This chapter talks a bit about design decisions.
Why GNU MediaGoblin?
====================
Chris and Will on "Why GNU MediaGoblin":
Chris came up with the name MediaGoblin. The name is pretty fun.
It merges the idea that this is a Media hosting project with
Goblin which sort of sounds like gobbling. Here's a piece of
software that gobbles up your media for all to see.
`According to Wikipedia <http://en.wikipedia.org/wiki/Goblin>`_, a
goblin is:
a legendary evil or mischievous illiterate creature, described
as grotesquely evil or evil-like phantom
So are we evil? No. Are we mischievous or illiterate? Not
really. So what kind of goblin are we thinking about? We're
thinking about these goblins:
.. figure:: goblin.png
:alt: Cute goblin with a beret.
*Figure 1: Cute goblin with a beret. llustrated by Chris
Webber*
.. figure:: snugglygoblin.png
:scale: 50%
:alt: Snuggly goblin with a beret.
*Figure 2: Snuggly goblin. Illustrated by Karen Rustad*
Those are pretty cute goblins. Those are the kinds of goblins
we're thinking about.
Chris started doing work on the project after thinking about it
for a year. Then, after talking with Matt and Rob, it became an
official GNU project. Thus we now call it GNU MediaGoblin.
That's a lot of letters, though, so in the interest of brevity and
facilitating easier casual conversation and balancing that with
what's important to us, we have the following rules:
1. "GNU MediaGoblin" is the name we're going to use in all official
capacities: web site, documentation, press releases, ...
2. In casual conversation, it's ok to use more casual names.
3. If you're writing about the project, we ask that you call it GNU
MediaGoblin.
4. If you don't like the name, we kindly ask you to take a deep
breath, think a happy thought about cute little goblins playing
on a playground and taking cute pictures of themselves, and let
it go. (Will added this one.)
Why Python
==========
Chris Webber on "Why Python":
Because I know Python, love Python, am capable of actually making
this thing happen in Python (I've worked on a lot of large free
software web applications before in Python, including `Miro
Community`_, the `Miro Guide`_, a large portion of `Creative
Commons`_, and a whole bunch of things while working at `Imaginary
Landscape`_). Me starting a project like this makes sense if it's
done in Python.
You might say that PHP is way more deployable, that Rails has way
more cool developers riding around on fixie bikes---and all of
those things are true. But I know Python, like Python, and think
that Python is pretty great. I do think that deployment in Python
is not as good as with PHP, but I think the days of shared hosting
are (thankfully) coming to an end, and will probably be replaced
by cheap virtual machines spun up on the fly for people who want
that sort of stuff, and Python will be a huge part of that future,
maybe even more than PHP will. The deployment tools are getting
better. Maybe we can use something like Silver Lining. Maybe we
can just distribute as ``.debs`` or ``.rpms``. We'll figure it
out when we get there.
Regardless, if I'm starting this project, which I am, it's gonna
be in Python.
.. _Miro Community: http://mirocommunity.org/
.. _Miro Guide: http://miroguide.org/
.. _Creative Commons: http://creativecommons.org/
.. _Imaginary Landscape: http://www.imagescape.com/
Why WSGI Minimalism
===================
Chris Webber on "Why WSGI Minimalism":
If you notice in the technology list I list a lot of components
that are very "django-like", but not actually `Django`_
components. What can I say, I really like a lot of the ideas in
Django! Which leads to the question: why not just use Django?
While I really like Django's ideas and a lot of its components, I
also feel that most of the best ideas in Django I want have been
implemented as good or even better outside of Django. I could
just use Django and replace the templating system with Jinja2, and
the form system with wtforms, and the database with MongoDB and
MongoKit, but at that point, how much of Django is really left?
I also am sometimes saddened and irritated by how coupled all of
Django's components are. Loosely coupled yes, but still coupled.
WSGI has done a good job of providing a base layer for running
applications on and if you know how to do it yourself [1]_, it's
not hard or many lines of code at all to bind them together
without any framework at all (not even say `Pylons`_, `Pyramid`_
or `Flask`_ which I think are still great projects, especially for
people who want this sort of thing but have no idea how to get
started). And even at this already really early stage of writing
MediaGoblin, that glue work is mostly done.
Not to say I don't think Django isn't great for a lot of things.
For a lot of stuff, it's still the best, but not for MediaGoblin,
I think.
One thing that Django does super well though is documentation. It
still has some faults, but even with those considered I can hardly
think of any other project in Python that has as nice of
documentation as Django. It may be worth learning some lessons on
documentation from Django [2]_, on that note.
I'd really like to have a good, thorough hacking-howto and
deployment-howto, especially in the former making some notes on
how to make it easier for Django hackers to get started.
.. _Django: http://www.djangoproject.com/
.. _Pylons: http://pylonshq.com/
.. _Pyramid: http://docs.pylonsproject.org/projects/pyramid/dev/
.. _Flask: http://flask.pocoo.org/
.. [1] http://pythonpaste.org/webob/do-it-yourself.html
.. [2] http://pycon.blip.tv/file/4881071/
Why MongoDB
===========
Chris Webber on "Why MongoDB":
In case you were wondering, I am not a NOSQL fanboy, I do not go
around telling people that MongoDB is web scale. Actually my
choice for MongoDB isn't scalability, though scaling up really
nicely is a pretty good feature and sets us up well in case large
volume sites eventually do use MediaGoblin. But there's another
side of scalability, and that's scaling down, which is important
for federation, maybe even more important than scaling up in an
ideal universe where everyone ran servers out of their own
housing. As a memory-mapped database, MongoDB is pretty hungry,
so actually I spent a lot of time debating whether the inability
to scale down as nicely as something like SQL has with sqlite
meant that it was out.
But I decided in the end that I really want MongoDB, not for
scalability, but for flexibility. Schema evolution pains in SQL
are almost enough reason for me to want MongoDB, but not quite.
The real reason is because I want the ability to eventually handle
multiple media types through MediaGoblin, and also allow for
plugins, without the rigidity of tables making that difficult. In
other words, something like::
{"title": "Me talking until you are bored",
"description": "blah blah blah",
"media_type": "audio",
"media_data": {
"length": "2:30",
"codec": "OGG Vorbis"},
"plugin_data": {
"licensing": {
"license": "http://creativecommons.org/licenses/by-sa/3.0/"}}}
Being able to just dump media-specific information in a media_data
hashtable is pretty great, and even better is having a plugin
system where you can just let plugins have their own entire
key-value space cleanly inside the document that doesn't interfere
with anyone else's stuff. If we were to let plugins to deposit
their own information inside the database, either we'd let plugins
create their own tables which makes SQL migrations even harder
than they already are, or we'd probably end up creating a table
with a column for key, a column for value, and a column for type
in one huge table called "plugin_data" or something similar. (Yo
dawg, I heard you liked plugins, so I put a database in your
database so you can query while you query.) Gross.
I also don't want things to be too loose so that we forget or lose
the structure of things, and that's one reason why I want to use
MongoKit, because we can cleanly define a much structure as we
want and verify that documents match that structure generally
without adding too much bloat or overhead (MongoKit is a pretty
lightweight wrapper and doesn't inject extra MongoKit-specific
stuff into the database, which is nice and nicer than many other
ORMs in that way).
Why Sphinx for documentation
============================
Will Kahn-Greene on "Why Sphinx":
`Sphinx`_ is a fantastic tool for organizing documentation for a
Python-based project that makes it pretty easy to write docs that
are readable in source form and can be "compiled" into HTML, LaTeX
and other formats.
There are other doc systems out there, but given that GNU
MediaGoblin is being written in Python and I've done a ton of
documentation using Sphinx, it makes sense to use Sphinx for now.
.. _Sphinx: http://sphinx.pocoo.org/
Why AGPLv3 and CC0?
===================
Chris, Brett, Will, Rob, Matt, et al curated into a story where
everyone is the hero by Will on "Why AGPLv3 and CC0":
The `AGPL v3`_ preserves the freedoms guaranteed by the GPL v3 in
the context of software as a service. Using this license ensures
that users of the service have the ability to examine the source,
deploy their own instance, and implement their own version. This
is really important to us and a core mission component of this
project. Thus we decided that the software parts should be under
this license.
However, the project is made up of more than just software:
there's CSS, images, and other output-related things. We wanted
the templates/images/css side of the project all permissive and
permissive in the same absolutely permissive way. We're waiving
our copyrights to non-software things under the CC0 waiver.
That brings us to the templates where there's some code and some
output. The template engine we're using is called Jinja2. It
mixes HTML markup with Python code to render the output of the
software. We decided the templates are part of the output of the
software and not the software itself. We wanted the output of the
software to be licensed in a hassle-free way so that when someone
deploys their own GNU MediaGoblin instance with their own
templates, they don't have to deal with the copyleft aspects of
the AGPLv3 and we'd be fine with that because the changes they're
making are identity-related. So at first we decided to waive our
copyrights to the templates with a CC0 waiver and then add an
exception to the AGPLv3 for the software such that the templates
can make calls into the software and yet be a separately licensed
work. However, Brett brought up the question of whether this
allows some unscrupulous person to make changes to the software
through the templates in such a way that they're not bound by the
AGPLv3: i.e. a loophole. We thought about this loophole and
between this and the extra legalese involved in the exception to
the AGPLv3, we decided that it's just way simpler if the templates
were also licensed under the AGPLv3.
Then we have the licensing for the documentation. Given that the
documentation is tied to the software content-wise, we don't feel
like we have to worry about ensuring freedom of the documentation
or worry about attribution concerns. Thus we're waiving our
copyrights to the documentation under CC0 as well.
Lastly, we have branding. This covers logos and other things that
are distinctive to GNU MediaGoblin that we feel represents this
project. Since we don't currently have any branding, this is an
open issue, but we're thinking we'll go with a CC BY-SA license.
By licensing in this way, we make sure that users of the software
receive the freedoms that the AGPLv3 ensures regardless of what
fate befalls this project.
So to summarize:
* software (Python, JavaScript, HTML templates): licensed
under AGPLv3
* non-software things (CSS, images, video): copyrights waived
under CC0 because this is output of the software
* documentation: copyrights waived under CC0 because it's not part
of the software
* branding assets: we're kicking this can down the road, but
probably CC BY-SA
This is all codified in the ``COPYING`` file.
.. _AGPL v3: http://www.gnu.org/licenses/agpl.html
.. _CC0 v1: http://creativecommons.org/publicdomain/zero/1.0/
Why (non-mandatory) copyright assignment?
=========================================
Chris Webber on "Why copyright assignment?":
GNU MediaGoblin is a GNU project with non-mandatory but heavily
encouraged copyright assignment to the FSF. Most, if not all, of
the core contributors to GNU MediaGoblin will have done a
copyright assignment, but unlike some other GNU projects, it isn't
required here. We think this is the best choice for GNU
MediaGoblin: it ensures that the Free Software Foundation may
protect the software by enforcing the AGPL if the FSF sees fit,
but it also means that we can immediately merge in changes from a
new contributor. It also means that some significant non-FSF
contributors might also be able to enforce the AGPL if seen fit.
Again, assignment is not mandatory, but it is heavily encouraged,
even incentivized: significant contributors who do a copyright
assignment to the FSF are eligible to have a unique goblin drawing
produced for them by the project's main founder, Christopher Allan
Webber. See :ref:`contributing-howto-chapter` for details.

View File

@ -1,345 +0,0 @@
.. _hacking-howto:
===============
Hacking HOWTO
===============
.. contents:: Sections
:local:
So you want to hack on GNU MediaGoblin?
=======================================
First thing to do is check out the `Web site
<http://mediagoblin.org/join/>`_ where we list all the project
infrastructure including:
* the IRC channel
* the mailing list
* the issue tracker
Additionally, we have information on how to get involved, who to talk
to, what needs to be worked on, and other things besides!
Second thing to do is take a look at :ref:`codebase-chapter` where
we've started documenting how GNU MediaGoblin is built and how to add
new things.
Third you'll need to :ref:`get the requirements
<get-requirements-section>`.
Fourth, you'll need to build a development environment. We use buildout,
but if you want to use virtualenv, there's a set of mediocre not-very-supported
steps in the `wiki <https://gitorious.org/mediagoblin/pages/Home>`_.
.. _get-requirements-section:
Getting requirements
====================
First, you need to have the following installed before you can build
an environment for hacking on GNU MediaGoblin:
* Python 2.6 or 2.7 - http://www.python.org/
You'll need Python as well as the dev files for building modules.
* python-lxml - http://lxml.de/
* git - http://git-scm.com/
* MongoDB - http://www.mongodb.org/
If you're running Debian GNU/Linux or a Debian-derived distribution
such as Mint or Ubuntu, running the following should install these
requirements::
sudo apt-get install mongodb git-core python python-dev \
python-lxml
On Fedora::
yum install mongodb-server python-paste-deploy python-paste-script \
git-core python python-devel python-lxml
.. YouCanHelp::
If you have instructions for other GNU/Linux distributions to set
up requirements, let us know!
.. _hacking-with-buildout:
How to set up and maintain an environment for hacking with buildout
===================================================================
**Requirements**
No additional requirements.
**Create a development environment**
After installing the requirements, follow these steps:
1. Clone the repository::
git clone git://gitorious.org/mediagoblin/mediagoblin.git
2. Bootstrap and run buildout::
cd mediagoblin
python bootstrap.py && ./bin/buildout
That's it! Using this method, buildout should create a ``user_dev``
directory, in which certain things will be stored (media, beaker
session stuff, etc). You can change this, but for development
purposes this default should be fine.
**Updating for dependency changes**
While hacking on GNU MediaGoblin over time, you'll eventually have to
update your development environment because the dependencies have
changed. To do that, run::
./bin/buildout && ./bin/gmg migrate
**Updating for code changes**
You don't need to do anything---code changes are automatically
available.
**Deleting your buildout**
At some point, you may want to delete your buildout. Perhaps it's to
start over. Perhaps it's to test building development environments
with buildout.
To do this, do::
rm -rf bin develop-eggs eggs mediagoblin.egg-info parts user_dev
Running the server
==================
If you want to get things running quickly and without hassle, just
run::
./lazyserver.sh
This will start up a python server where you can begin playing with
mediagoblin. It will also run celery in "always eager" mode so you
don't have to start a separate process for it.
This is fine in development, but if you want to actually run celery
separately for testing (or deployment purposes), you'll want to run
the server independently::
./bin/paster serve paste.ini --reload
Running celeryd
===============
If you aren't using ./lazyserver.sh or otherwise aren't running celery
in always eager mode, you'll need to do this if you want your media to
process and actually show up. It's probably a good idea in
development to have the web server (above) running in one terminal and
celeryd in another window.
Run::
CELERY_CONFIG_MODULE=mediagoblin.init.celery.from_celery ./bin/celeryd
Running the test suite
======================
Run::
./runtests.sh
Running a shell
===============
If you want a shell with your database pre-setup and an instantiated
application ready and at your fingertips....
Run::
./bin/gmg shell
Troubleshooting
===============
pymongo.errors.AutoReconnect: could not find master/primary
-----------------------------------------------------------
If you see this::
pymongo.errors.AutoReconnect: could not find master/primary
then make sure mongodb is installed and running.
If it's installed, check the mongodb log. On my machine, that's
``/var/log/mongodb/mongodb.log``. If you see something like::
old lock file: /var/lib/mongodb/mongod.lock. probably means...
in that case you might have had an unclean shutdown. Try::
sudo mongod --repair
If that didn't work, just delete the lock file and relaunch mongodb.
Anyway, then start the mongodb server in whatever way is appropriate
for your distro / OS.
pkg_resources.DistributionNotFound: distribute
----------------------------------------------
If you get this while running buildout::
pkg_resources.DistributionNotFound: distribute
Try this commmand instead::
python bootstrap.py --distribute && ./bin/buildout
Wiping your user data
=====================
.. Note::
Unless you're doing development and working on and testing creating
a new instance, you will probably never have to do this. Will
plans to do this work and thus he documented it.
.. YouCanHelp::
If you're familiar with MongoDB, we'd love to get a `script that
removes all the GNU MediaGoblin data from an existing instance
<http://bugs.foocorp.net/issues/296>`_. Let us know!
Quickstart for Django programmers
=================================
We're not using Django, but the codebase is very Django-like in its
structure.
* ``routing.py`` is like ``urls.py`` in Django
* ``models.py`` has mongokit ORM definitions
* ``views.py`` is where the views go
We're using MongoDB. Basically, instead of a relational database with
tables, you have a big JSON structure which acts a lot like a Python
dict.
.. YouCanHelp::
If there are other things that you think would help orient someone
new to GNU MediaGoblin but coming from Django, let us know!
Bite-sized bugs to start with
=============================
**May 3rd, 2011**: We don't have a list of bite-sized bugs, yet, but
this is important to us. If you're interested in things to work on,
let us know on `the mailing list <http://mediagoblin.org/join/>`_ or
on the `IRC channel <http://mediagoblin.org/join/>`_.
Tips for people new to coding
=============================
Learning Python
---------------
GNU MediaGoblin is written using a programming language called `Python
<http://python.org/>`_.
There are two different incompatible iterations of Python which I'll
refer to as Python 2 and Python 3. GNU MediaGoblin is written in
Python 2 and requires Python 2.6 or 2.7. At some point, we might
switch to Python 3, but that's a future thing.
You can learn how to code in Python 2 from several excellent books
that are freely available on the Internet:
* `Learn Python the Hard Way <http://learnpythonthehardway.org/>`_
* `Dive Into Pyton <http://diveintopython.org/>`_
* `Python for Software Design <http://www.greenteapress.com/thinkpython/>`_
* `A Byte of Python <http://www.swaroopch.com/notes/Python>`_
These are all excellent texts.
.. YouCanHelp::
If you know of other good quality Python tutorials and Python
tutorial videos, let us know!
Learning Libraries GNU MediaGoblin uses
---------------------------------------
GNU MediaGoblin uses a variety of libraries in order to do what it
does. These libraries are listed in the :ref:`codebase-chapter`
along with links to the project Web sites and documentation for the
libraries.
There are a variety of Python-related conferences every year that have
sessions covering many aspects of these libraries. You can find them
at `Python Miro Community <http://python.mirocommunity.org>`_ [0]_.
.. [0] This is a shameless plug. Will Kahn-Greene runs Python Miro
Community.
If you have questions or need help, find us on the mailing list and on
IRC.
.. _hacking-howto-git:
Learning git
------------
git is an interesting and very powerful tool. Like all powerful
tools, it has a learning curve.
If you're new to git, we highly recommend the following resources for
getting the hang of it:
* `Learn Git <http://learn.github.com/p/intro.html>`_ --- the GitHub
intro to git
* `Pro Git <http://progit.org/book/>`_ --- fantastic book
* `Git casts <http://gitcasts.com/>`_ --- screencast covering git
usage
* `Git Reference <http://gitref.org/>`_ --- Git reference that makes
it easier to get the hang of git if you're coming from other version
control systems
There's also a git mission at `OpenHatch <http://openhatch.org/>`_.
Learning other utilities
------------------------
The `OpenHatch <http://openhatch.org/>`_ site has a series of
`training missions <http://openhatch.org/missions/>`_ which are
designed to help you learn how to use these tools.
If you're new to tar, diff, patch and git, we highly recommend you sign
up with OpenHatch and do the missions.

View File

@ -0,0 +1,39 @@
{#
default/layout.html
~~~~~~~~~~~~~~~~~~~
Sphinx layout template for the default theme.
:copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
#}
{% extends "basic/layout.html" %}
{% if theme_collapsiblesidebar|tobool %}
{% set script_files = script_files + ['_static/sidebar.js'] %}
{% endif %}
{%- block footer %}
<div class="footer">
<div>
{% trans path=pathto('copyright'), copyright=copyright|e %}&copy; <a href="{{ path }}">Copyright</a> {{ copyright }}.{% endtrans %}
{%- if last_updated %}
{% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %}
{%- endif %}
{% trans sphinx_version=sphinx_version|e %}Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> {{ sphinx_version }}.{% endtrans %}
</div>
<a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/3.0/88x31.png" /></a><br /><span xmlns:dc="http://purl.org/dc/elements/1.1/" href="http://purl.org/dc/dcmitype/Text" property="dc:title" rel="dc:type">{{ shorttitle|e }}</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="http://bluesock.org/~willg/" property="cc:attributionName" rel="cc:attributionURL">Will Kahn-Greene</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.<br />
</div>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-163840-8']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
{%- endblock %}

View File

@ -0,0 +1,299 @@
/*
* default.css_t
* ~~~~~~~~~~~~~
*
* Sphinx stylesheet -- default theme.
*
* :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
@import url("basic.css");
/* -- page layout ----------------------------------------------------------- */
body {
font-family: {{ theme_bodyfont }};
font-size: 100%;
background-color: {{ theme_footerbgcolor }};
color: #000;
margin: 0;
padding: 0;
}
div.document {
background-color: {{ theme_sidebarbgcolor }};
}
div.documentwrapper {
float: left;
width: 100%;
}
div.bodywrapper {
margin: 0 0 0 230px;
}
div.body {
background-color: {{ theme_bgcolor }};
color: {{ theme_textcolor }};
padding: 0 20px 30px 20px;
}
{%- if theme_rightsidebar|tobool %}
div.bodywrapper {
margin: 0 230px 0 0;
}
{%- endif %}
div.footer {
color: {{ theme_footertextcolor }};
width: 100%;
padding: 9px 0 9px 0;
text-align: center;
font-size: 75%;
}
div.footer a {
color: {{ theme_footertextcolor }};
text-decoration: underline;
}
div.related {
background-color: {{ theme_relbarbgcolor }};
line-height: 30px;
color: {{ theme_relbartextcolor }};
}
div.related a {
color: {{ theme_relbarlinkcolor }};
}
div.sphinxsidebar {
{%- if theme_stickysidebar|tobool %}
top: 30px;
bottom: 0;
margin: 0;
position: fixed;
overflow: auto;
height: auto;
{%- endif %}
{%- if theme_rightsidebar|tobool %}
float: right;
{%- if theme_stickysidebar|tobool %}
right: 0;
{%- endif %}
{%- endif %}
}
{%- if theme_stickysidebar|tobool %}
/* this is nice, but it it leads to hidden headings when jumping
to an anchor */
/*
div.related {
position: fixed;
}
div.documentwrapper {
margin-top: 30px;
}
*/
{%- endif %}
div.sphinxsidebar h3 {
font-family: {{ theme_headfont }};
color: {{ theme_sidebartextcolor }};
font-size: 1.4em;
font-weight: normal;
margin: 0;
padding: 0;
}
div.sphinxsidebar h3 a {
color: {{ theme_sidebartextcolor }};
}
div.sphinxsidebar h4 {
font-family: {{ theme_headfont }};
color: {{ theme_sidebartextcolor }};
font-size: 1.3em;
font-weight: normal;
margin: 5px 0 0 0;
padding: 0;
}
div.sphinxsidebar p {
color: {{ theme_sidebartextcolor }};
}
div.sphinxsidebar p.topless {
margin: 5px 10px 10px 10px;
}
div.sphinxsidebar ul {
margin: 10px;
padding: 0;
color: {{ theme_sidebartextcolor }};
}
div.sphinxsidebar a {
color: {{ theme_sidebarlinkcolor }};
}
div.sphinxsidebar input {
border: 1px solid {{ theme_sidebarlinkcolor }};
font-family: sans-serif;
font-size: 1em;
}
/* -- hyperlink styles ------------------------------------------------------ */
a {
color: {{ theme_linkcolor }};
text-decoration: none;
}
a:visited {
color: {{ theme_visitedlinkcolor }};
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
{% if theme_externalrefs|tobool %}
a.external {
text-decoration: none;
border-bottom: 1px dashed {{ theme_linkcolor }};
}
a.external:hover {
text-decoration: none;
border-bottom: none;
}
{% endif %}
/* -- body styles ----------------------------------------------------------- */
div.body h1,
div.body h2,
div.body h3,
div.body h4,
div.body h5,
div.body h6 {
font-family: {{ theme_headfont }};
background-color: {{ theme_headbgcolor }};
font-weight: normal;
color: {{ theme_headtextcolor }};
border-bottom: 1px solid #ccc;
margin: 20px -20px 10px -20px;
padding: 3px 0 3px 10px;
}
div.body h1 { margin-top: 0; font-size: 200%; }
div.body h2 { font-size: 160%; }
div.body h3 { font-size: 140%; }
div.body h4 { font-size: 120%; }
div.body h5 { font-size: 110%; }
div.body h6 { font-size: 100%; }
a.headerlink {
color: {{ theme_headlinkcolor }};
font-size: 0.8em;
padding: 0 4px 0 4px;
text-decoration: none;
}
a.headerlink:hover {
background-color: {{ theme_headlinkcolor }};
color: white;
}
div.body p, div.body dd, div.body li {
text-align: justify;
line-height: 130%;
}
div.admonition p.admonition-title + p {
display: inline;
}
div.admonition p {
margin-bottom: 5px;
}
div.admonition pre {
margin-bottom: 5px;
}
div.admonition ul, div.admonition ol {
margin-bottom: 5px;
}
div.note {
background-color: #eee;
border: 1px solid #ccc;
}
div.seealso {
background-color: #ffc;
border: 1px solid #ff6;
}
div.topic {
background-color: #eee;
}
div.warning {
background-color: #ffe4e4;
border: 1px solid #f66;
}
p.admonition-title {
display: inline;
}
p.admonition-title:after {
content: ":";
}
pre {
padding: 5px;
background-color: {{ theme_codebgcolor }};
color: {{ theme_codetextcolor }};
line-height: 120%;
border: 1px solid #ac9;
border-left: none;
border-right: none;
}
tt {
background-color: #ecf0f3;
padding: 0 1px 0 1px;
font-size: 0.95em;
}
th {
background-color: #ede;
}
.warning tt {
background: #efc2c2;
}
.note tt {
background: #d6d6d6;
}
.viewcode-back {
font-family: {{ theme_bodyfont }};
}
div.viewcode-block:target {
background-color: #f4debf;
border-top: 1px solid #ac9;
border-bottom: 1px solid #ac9;
}

View File

@ -0,0 +1,31 @@
[theme]
inherit = basic
stylesheet = default.css
pygments_style = sphinx
[options]
rightsidebar = false
stickysidebar = false
collapsiblesidebar = false
externalrefs = false
footerbgcolor = #b11818
footertextcolor = #ffffff
sidebarbgcolor = #6a0000
sidebartextcolor = #ffffff
sidebarlinkcolor = #98dbcc
relbarbgcolor = #b11818
relbartextcolor = #ffffff
relbarlinkcolor = #ffffff
bgcolor = #ffffff
textcolor = #000000
headbgcolor = #fdeded
headtextcolor = #20435c
headlinkcolor = #c60f0f
linkcolor = #355f7c
visitedlinkcolor = #355f7c
codebgcolor = #eeffcc
codetextcolor = #333333
bodyfont = sans-serif
headfont = 'Trebuchet MS', sans-serif

View File

@ -21,7 +21,7 @@ various recipes for getting things done.
for where we hang out. for where we hang out.
For more information on how to get started hacking on GNU MediaGoblin, For more information on how to get started hacking on GNU MediaGoblin,
see :ref:`hacking-howto`. see `the wiki <http://wiki.mediagoblin.org/>`_.
Software Stack Software Stack

View File

@ -48,9 +48,9 @@ copyright = u'2011, Free Software Foundation, Inc and contributors'
# built documents. # built documents.
# #
# The short X.Y version. # The short X.Y version.
version = '0.0.3' version = '0.0.4'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = '0.0.3' release = '0.0.4'
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.
@ -64,7 +64,7 @@ release = '0.0.3'
# List of patterns, relative to source directory, that match files and # List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files. # directories to ignore when looking for source files.
exclude_patterns = ['_build'] exclude_patterns = ['_build', 'mgext', '_templates', '_static']
# The reST default role (used for this markup: `text`) to use for all documents. # The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None #default_role = None
@ -214,3 +214,26 @@ man_pages = [
('index', 'gnumediagoblin', u'GNU MediaGoblin Documentation', ('index', 'gnumediagoblin', u'GNU MediaGoblin Documentation',
[u'Chris Webber, et al'], 1) [u'Chris Webber, et al'], 1)
] ]
# If true, show URL addresses after external links.
#man_show_urls = False
# -- Options for Texinfo output ------------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'gnumediagoblin', u'GNU MediaGoblin Documentation', u'gnumediagoblin',
'GNU MediaGoblin', 'Media sharing web application.', 'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'

View File

@ -46,8 +46,8 @@ Here are some things you can do today:
**Write/Fix some code** **Write/Fix some code**
If you are a coder and you're looking to code, check out the If you are a coder and you're looking to code, check out the
:ref:`hacking-howto`. We even have tips on *becoming* a coder `wiki <http://wiki.mediagoblin.org/`_. We even have tips on
and we're willing to help you! *becoming* a coder and we're willing to help you!
**Send encouragement** **Send encouragement**
@ -135,7 +135,7 @@ the project, Chris Webber, will make a custom drawing of a goblin
dedicated specifically to you. dedicated specifically to you.
For why we're doing copyright assignment, see the For why we're doing copyright assignment, see the
:ref:`design-decisions-chapter`. `wiki <http://wiki.mediagoblin.org/>`_.
.. _filing-bugs: .. _filing-bugs:

View File

@ -12,5 +12,5 @@ Step 3: Write the deployment guide and profit!
But seriously, this is a stub since we're not quite there (yet) but if But seriously, this is a stub since we're not quite there (yet) but if
you want to see where we are now, you can try to run the latest you want to see where we are now, you can try to run the latest
development version by following the instructions at development version by following the instructions on
:ref:`hacking-howto`. `the wiki <http://wiki.mediagoblin.org/>`_.

View File

@ -221,4 +221,4 @@ because he doesn't need it anymore.
How to learn git How to learn git
================ ================
Check out :ref:`hacking-howto-git`! Check out `the wiki <http://wiki.mediagoblin.org/>`_.

View File

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 47 KiB

View File

@ -15,11 +15,9 @@ Table of Contents:
mediagoblin mediagoblin
contributinghowto contributinghowto
deploymenthowto deploymenthowto
hackinghowto
theminghowto theminghowto
git git
codebase codebase
designdecisions
vision vision

View File

@ -30,9 +30,9 @@ Why are we doing this?
Centralization and proprietization of media on the internet is a Centralization and proprietization of media on the internet is a
serious problem and makes the web go from a system of extreme serious problem and makes the web go from a system of extreme
resilience to a system of frightening fragility. We believe people resilience to a system of frightening fragility. We believe people
should be able to own their data and that means someone has to build should be able to free their data from proprietary control and that
the tools to make it possible. We decided that in this case, that means someone has to build the tools to make it possible. We decided
someone would be us! that in this case, that someone would be us!
Who are you? Who are you?

View File

Before

Width:  |  Height:  |  Size: 160 KiB

After

Width:  |  Height:  |  Size: 160 KiB

54
extlib/960.gs/README.txt Executable file
View File

@ -0,0 +1,54 @@
===============
960 GRID SYSTEM
===============
Created by Nathan Smith. See the official site for more info: http://960.gs/
============================================================================
To install the Adobe Fireworks extension, simply double-click the *.mxp file
included in the /fireworks_extension directory. If you are running Windows 7
you will need admin permissions in order to install this extension properly.
============================================================================
Thank you for downloading the 960 Grid System. I hope it helps to streamline
web development workflow. Enclosed in the bundle are printable sketch sheets
and template files for Adobe Fireworks and Photoshop, OmniGraffle and Visio.
Also included is a lightweight CSS file, which contains the grid dimensions.
To use this file, simply include the 960.css in the <head> of the HTML page.
You may also use the reset.css and text.css files, or opt to leave them out.
Here is an example of the XHTML code necessary to incorporate the CSS files:
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" />
<link rel="stylesheet" type="text/css" media="all" href="css/text.css" />
<link rel="stylesheet" type="text/css" media="all" href="css/960.css" />
</head>
It is worth noting that these styles do not automatically make up a finished
site design. They are simply a starting point, ideally for rapid prototyping
or as a basis for creating your own designs. You should not feel constrained
by the way I have built the initial code. If you disagree with how something
has been done, feel free to revise it for the needs of your particular site.
The files in the 960 Grid System are free of charge, licensed under MIT/GPL.
============================================================================
Note that if you are building a site in a language which reads from right to
left, use the CSS files that end in "_rtl.css" instead. Denote the language:
<html lang="..." dir="rtl">
Be sure to replace "..." with the appropriate two-letter abbreviation of the
language you are using. Example: lang="he" for Hebrew, lang="ar" for Arabic.
============================================================================
GPL license:
http://www.gnu.org/licenses/gpl.html
MIT license:
http://www.opensource.org/licenses/mit-license.php

71
extlib/README Normal file
View File

@ -0,0 +1,71 @@
=========================
External Library README
=========================
DO NOT "FIX" CODE IN THIS DIRECTORY.
ONLY UPSTREAM VERSIONS OF SOFTWARE GO IN THIS DIRECTORY.
This directory is provided as a courtesy to our users who might be
unable or unwilling to find and install libraries we depend on.
If we "fix" software in this directory, we hamstring users who do the
right thing and keep a single version of upstream libraries in a
system-wide library. We introduce subtle and maddening bugs where
our code is "accidentally" using the "wrong" library version. We may
unwittingly interfere with other software that depends on the
canonical release versions of those same libraries!
Forking upstream software for trivial reasons makes us bad citizens in
the Open Source community and adds unnecessary heartache for our
users. Don't make us "that" project.
FAQ
===
:Q: What should we do when we find a bug in upstream software?
:A: First and foremost, REPORT THE BUG, and if possible send in a patch.
Watch for a release of the upstream software and integrate with it
when it's released.
In the meantime, work around the bug, if at all possible. Usually,
it's quite possible, if slightly harder or less efficient.
:Q: What if the bug can't be worked around?
:A: If the upstream developers have accepted a bug patch, it's
undesirable but acceptable to apply that patch to the library in
the ``extlib/`` dir. Ideally, use a release version for upstream or a
version control system snapshot.
Note that this is a last resort.
:Q: What if upstream is unresponsive or won't accept a patch?
:A: Try again.
:Q: I tried again, and upstream is still unresponsive and nobody's
checked on my patch. Now what?
:A: If the upstream project is moribund and there's a way to adopt it,
propose having the MediaGoblin dev team adopt the project. Or, adopt
it yourself.
:Q: What if there's no upstream authority and it can't be adopted?
:A: Then we fork it. Make a new name and a new version. Include it in
``lib/`` instead of ``extlib/``, and use the GMG_* prefix to change
the namespace to avoid collisions (or something like that).
This is a last resort; consult with the rest of the dev group
before taking this radical step.
Thanks
======
This policy originally copied from Status.net. Many many thanks to them
for working out such a nice system for doing things.

View File

@ -18,18 +18,18 @@
if [ "$1" = "-h" ] if [ "$1" = "-h" ]
then then
echo "$0 [-h] [-c paste.ini] ARGS_to_paster" echo "$0 [-h] [-c paste.ini] ARGS_to_paster"
echo " For example:" echo " For example:"
echo " $0 -c fcgi.ini port_number=23371" echo " $0 -c fcgi.ini port_number=23371"
exit 1 exit 1
fi fi
PASTE_INI=paste.ini PASTE_INI=paste.ini
if [ "$1" = "-c" ] if [ "$1" = "-c" ]
then then
PASTE_INI="$2" PASTE_INI="$2"
shift shift
shift shift
fi fi
if [ -f ./bin/paster ]; then if [ -f ./bin/paster ]; then

165
licenses/LGPLv3.txt Normal file
View File

@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

View File

@ -1,57 +1,178 @@
#!/bin/bash #!/bin/bash
# usage: maketarball # GNU MediaGoblin -- federated, autonomous media hosting
# maketarball <tag> # Copyright (C) 2011 Free Software Foundation, Inc
# #
# With no arguments, this creates a source tarball from git master with a # This program is free software: you can redistribute it and/or modify
# filename based on today's date. # 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.
# #
# With a <tag> argument, this creates a tarball of the tag. # 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/>.
# usage: maketarball [-drh] REVISH
#
# Creates a tarball of the repository at rev REVISH.
# If -d is passed in, then it adds the date to the directory name.
#
# If -r is passed in, then it does some additional things required
# for a release-ready tarball.
#
# If -h is passed in, shows help and exits.
# #
# Examples: # Examples:
# #
# ./maketarball
# ./maketarball v0.0.2 # ./maketarball v0.0.2
# ./maketarball -d master
# ./maketarball -r v0.0.2
NOWDATE=`date "+%Y-%m-%d"`
if [ -z "$1" ] USAGE="Usage: $0 -h | [-dr] REVISH"
then
REVISH=master
PREFIX="$NOWDATE-$REVISH"
else
REVISH=$1
PREFIX="$REVISH"
fi
# convert PREFIX to all lowercase. REVISH="none"
# nix the v from tag names. PREFIX="none"
PREFIX=`echo "$PREFIX" | tr '[A-Z]' '[a-z]' | sed s/v//` NOWDATE=""
RELEASE="no"
echo "== REVISH $REVISH" while getopts ":dhr" opt;
echo "== PREFIX $PREFIX" do
case "$opt" in
h)
echo "$USAGE"
echo ""
echo "Creates a tarball of the repository at rev REVISH."
echo ""
echo " -h Shows this help message"
echo " -d Includes date in tar file name and directory"
echo " -r Performs other release-related actions"
exit 0
;;
d)
NOWDATE=`date "+%Y-%m-%d-"`
shift $((OPTIND-1))
;;
r)
RELEASE="yes"
shift $((OPTIND-1))
;;
\?)
echo "Invalid option: -$OPTARG" >&2
echo "$USAGE" >&2
;;
esac
done
echo "" if [[ -z "$1" ]]; then
echo "$USAGE";
echo "generating archive...."
git archive \
--format=tar \
--prefix=mediagoblin-$PREFIX/ \
$REVISH > mediagoblin-$PREFIX.tar
if [[ $? -ne 0 ]]
then
echo "git archive command failed. See above text for reason."
if [[ -e mediagoblin-$PREFIX.tar ]]
then
rm mediagoblin-$PREFIX.tar
fi
exit 1; exit 1;
fi fi
echo "compressing...." REVISH=$1
gzip mediagoblin-$PREFIX.tar PREFIX="$NOWDATE$REVISH"
echo "archive at mediagoblin-$PREFIX.tar.gz" # convert PREFIX to all lowercase and nix the v from tag names.
PREFIX=`echo "$PREFIX" | tr '[A-Z]' '[a-z]' | sed s/v//`
echo "done." # build the filename base minus the .tar.gz stuff--this is also
# the directory in the tarball.
FNBASE="mediagoblin-$PREFIX"
STARTDIR=`pwd`
function cleanup {
pushd $STARTDIR
if [[ -e tmp ]]
then
echo "+ cleaning up tmp/"
rm -rf tmp
fi
popd
}
echo "+ Building tarball from: $REVISH"
echo "+ Using prefix: $PREFIX"
echo "+ Release?: $RELEASE"
echo ""
if [[ -e tmp ]]
then
echo "+ there's an existing tmp/. please remove it."
exit 1
fi
mkdir $STARTDIR/tmp
echo "+ generating archive...."
git archive \
--format=tar \
--prefix=$FNBASE/ \
$REVISH > tmp/$FNBASE.tar
if [[ $? -ne 0 ]]
then
echo "+ git archive command failed. See above text for reason."
cleanup
exit 1
fi
if [[ $RELEASE = "yes" ]]
then
pushd tmp/
tar -xvf $FNBASE.tar
pushd $FNBASE
pushd docs
echo "+ generating html docs"
make html
if [[ $? -ne 0 ]]
then
echo "+ sphinx docs generation failed. See above text for reason."
cleanup
exit 1
fi
# NOTE: this doesn't work for gmg prior to v0.0.4.
echo "+ generating texinfo docs (doesn't work prior to v0.0.4)"
make info
popd
echo "+ moving docs to the right place"
if [[ -e docs/build/html/ ]]
then
mv docs/build/html/ docs/html/
mv docs/build/texinfo/ docs/texinfo/
rm -rf docs/build/
rm -rf docs/source/mgext/*.pyc
else
# this is the old directory structure pre-0.0.4
mv docs/_build/html/ docs/html/
rm -rf docs/_build/
rm -rf docs/mgext/*.pyc
fi
popd
tar -cvf $FNBASE.tar $FNBASE
popd
fi
echo "+ compressing...."
gzip tmp/$FNBASE.tar
echo "+ archive at tmp/$FNBASE.tar.gz"
echo "+ done."

View File

@ -20,11 +20,12 @@ import urllib
import routes import routes
from webob import Request, exc from webob import Request, exc
from mediagoblin import routing, util, storage from mediagoblin import routing, util
from mediagoblin.mg_globals import setup_globals from mediagoblin.mg_globals import setup_globals
from mediagoblin.init.celery import setup_celery_from_config from mediagoblin.init.celery import setup_celery_from_config
from mediagoblin.init import get_jinja_loader, get_staticdirector, \ from mediagoblin.init import (get_jinja_loader, get_staticdirector,
setup_global_and_app_config, setup_workbench, setup_database setup_global_and_app_config, setup_workbench, setup_database,
setup_storage)
class MediaGoblinApp(object): class MediaGoblinApp(object):
@ -62,10 +63,7 @@ class MediaGoblinApp(object):
app_config.get('user_template_path')) app_config.get('user_template_path'))
# Set up storage systems # Set up storage systems
self.public_store = storage.storage_system_from_config( self.public_store, self.queue_store = setup_storage()
app_config, 'publicstore')
self.queue_store = storage.storage_system_from_config(
app_config, 'queuestore')
# set up routing # set up routing
self.routing = routing.get_mapper() self.routing = routing.get_mapper()
@ -90,10 +88,7 @@ class MediaGoblinApp(object):
# object. # object.
####################################################### #######################################################
setup_globals( setup_globals(app = self)
app=self,
public_store=self.public_store,
queue_store=self.queue_store)
# Workbench *currently* only used by celery, so this only # Workbench *currently* only used by celery, so this only
# matters in always eager mode :) # matters in always eager mode :)

View File

@ -16,34 +16,36 @@
import wtforms import wtforms
from mediagoblin.util import fake_ugettext_passthrough as _
class RegistrationForm(wtforms.Form): class RegistrationForm(wtforms.Form):
username = wtforms.TextField( username = wtforms.TextField(
'Username', _('Username'),
[wtforms.validators.Required(), [wtforms.validators.Required(),
wtforms.validators.Length(min=3, max=30), wtforms.validators.Length(min=3, max=30),
wtforms.validators.Regexp(r'^\w+$')]) wtforms.validators.Regexp(r'^\w+$')])
password = wtforms.PasswordField( password = wtforms.PasswordField(
'Password', _('Password'),
[wtforms.validators.Required(), [wtforms.validators.Required(),
wtforms.validators.Length(min=6, max=30), wtforms.validators.Length(min=6, max=30),
wtforms.validators.EqualTo( wtforms.validators.EqualTo(
'confirm_password', 'confirm_password',
'Passwords must match.')]) _('Passwords must match.'))])
confirm_password = wtforms.PasswordField( confirm_password = wtforms.PasswordField(
'Confirm password', _('Confirm password'),
[wtforms.validators.Required()]) [wtforms.validators.Required()])
email = wtforms.TextField( email = wtforms.TextField(
'Email address', _('Email address'),
[wtforms.validators.Required(), [wtforms.validators.Required(),
wtforms.validators.Email()]) wtforms.validators.Email()])
class LoginForm(wtforms.Form): class LoginForm(wtforms.Form):
username = wtforms.TextField( username = wtforms.TextField(
'Username', _('Username'),
[wtforms.validators.Required(), [wtforms.validators.Required(),
wtforms.validators.Regexp(r'^\w+$')]) wtforms.validators.Regexp(r'^\w+$')])
password = wtforms.PasswordField( password = wtforms.PasswordField(
'Password', _('Password'),
[wtforms.validators.Required()]) [wtforms.validators.Required()])

View File

@ -19,18 +19,12 @@ from routes.route import Route
auth_routes = [ auth_routes = [
Route('mediagoblin.auth.register', '/register/', Route('mediagoblin.auth.register', '/register/',
controller='mediagoblin.auth.views:register'), controller='mediagoblin.auth.views:register'),
Route('mediagoblin.auth.register_success', '/register/success/',
template='mediagoblin/auth/register_success.html',
controller='mediagoblin.views:simple_template_render'),
Route('mediagoblin.auth.login', '/login/', Route('mediagoblin.auth.login', '/login/',
controller='mediagoblin.auth.views:login'), controller='mediagoblin.auth.views:login'),
Route('mediagoblin.auth.logout', '/logout/', Route('mediagoblin.auth.logout', '/logout/',
controller='mediagoblin.auth.views:logout'), controller='mediagoblin.auth.views:logout'),
Route('mediagoblin.auth.verify_email', '/verify_email/', Route('mediagoblin.auth.verify_email', '/verify_email/',
controller='mediagoblin.auth.views:verify_email'), controller='mediagoblin.auth.views:verify_email'),
Route('mediagoblin.auth.verify_email_notice', '/verification_required/',
template='mediagoblin/auth/verification_needed.html',
controller='mediagoblin.views:simple_template_render'),
Route('mediagoblin.auth.resend_verification', '/resend_verification/', Route('mediagoblin.auth.resend_verification', '/resend_verification/',
controller='mediagoblin.auth.views:resend_activation'), controller='mediagoblin.auth.views:resend_activation'),
Route('mediagoblin.auth.resend_verification_success', Route('mediagoblin.auth.resend_verification_success',

View File

@ -21,6 +21,7 @@ from webob import exc
from mediagoblin import messages from mediagoblin import messages
from mediagoblin import mg_globals from mediagoblin import mg_globals
from mediagoblin.util import render_to_response, redirect from mediagoblin.util import render_to_response, redirect
from mediagoblin.util import pass_to_ugettext as _
from mediagoblin.db.util import ObjectId from mediagoblin.db.util import ObjectId
from mediagoblin.auth import lib as auth_lib from mediagoblin.auth import lib as auth_lib
from mediagoblin.auth import forms as auth_forms from mediagoblin.auth import forms as auth_forms
@ -36,7 +37,7 @@ def register(request):
messages.add_message( messages.add_message(
request, request,
messages.WARNING, messages.WARNING,
('Sorry, registration is disabled on this instance.')) _('Sorry, registration is disabled on this instance.'))
return redirect(request, "index") return redirect(request, "index")
register_form = auth_forms.RegistrationForm(request.POST) register_form = auth_forms.RegistrationForm(request.POST)
@ -51,20 +52,29 @@ def register(request):
if users_with_username: if users_with_username:
register_form.username.errors.append( register_form.username.errors.append(
u'Sorry, a user with that name already exists.') _(u'Sorry, a user with that name already exists.'))
else: else:
# Create the user # Create the user
entry = request.db.User() user = request.db.User()
entry['username'] = request.POST['username'].lower() user['username'] = request.POST['username'].lower()
entry['email'] = request.POST['email'] user['email'] = request.POST['email']
entry['pw_hash'] = auth_lib.bcrypt_gen_password_hash( user['pw_hash'] = auth_lib.bcrypt_gen_password_hash(
request.POST['password']) request.POST['password'])
entry.save(validate=True) user.save(validate=True)
send_verification_email(entry, request) # log the user in
request.session['user_id'] = unicode(user['_id'])
request.session.save()
return redirect(request, "mediagoblin.auth.register_success") # send verification email
send_verification_email(user, request)
# redirect the user to their homepage... there will be a
# message waiting for them to verify their email
return redirect(
request, 'mediagoblin.user_pages.user_home',
user=user['username'])
return render_to_response( return render_to_response(
request, request,
@ -136,23 +146,20 @@ def verify_email(request):
user['status'] = u'active' user['status'] = u'active'
user['email_verified'] = True user['email_verified'] = True
user.save() user.save()
verification_successful = True
messages.add_message( messages.add_message(
request, request,
messages.SUCCESS, messages.SUCCESS,
('Your email address has been verified. ' _("Your email address has been verified. "
'You may now login, edit your profile, and submit images!')) "You may now login, edit your profile, and submit images!"))
else: else:
verification_successful = False messages.add_message(
messages.add_message(request, request,
messages.ERROR, messages.ERROR,
'The verification key or user id is incorrect') _('The verification key or user id is incorrect'))
return render_to_response( return redirect(
request, request, 'mediagoblin.user_pages.user_home',
'mediagoblin/user_pages/user.html', user=request.user['username'])
{'user': user,
'verification_successful' : verification_successful})
def resend_activation(request): def resend_activation(request):
@ -166,4 +173,10 @@ def resend_activation(request):
send_verification_email(request.user, request) send_verification_email(request.user, request)
return redirect(request, 'mediagoblin.auth.resend_verification_success') messages.add_message(
request,
messages.INFO,
_('Resent your verification email.'))
return redirect(
request, 'mediagoblin.user_pages.user_home',
user=request.user['username'])

View File

@ -24,6 +24,10 @@ email_sender_address = string(default="notice@mediagoblin.example.org")
# Set to false to disable registrations # Set to false to disable registrations
allow_registration = boolean(default=True) allow_registration = boolean(default=True)
# tag parsing
tags_delimiter = string(default=",")
tags_max_length = integer(default=50)
# By default not set, but you might want something like: # By default not set, but you might want something like:
# "%(here)s/user_dev/templates/" # "%(here)s/user_dev/templates/"
local_templates = string() local_templates = string()

View File

@ -90,6 +90,21 @@ MEDIAENTRY_INDEXES = {
# Indexing on uploaders and when media entries are created. # Indexing on uploaders and when media entries are created.
# Used for showing a user gallery, etc. # Used for showing a user gallery, etc.
'index': [('uploader', ASCENDING), 'index': [('uploader', ASCENDING),
('created', DESCENDING)]},
'state_uploader_tags_created': {
# Indexing on processed?, media uploader, associated tags, and timestamp
# Used for showing media items matching a tag search, most recent first.
'index': [('state', ASCENDING),
('uploader', ASCENDING),
('tags.slug', DESCENDING),
('created', DESCENDING)]},
'state_tags_created': {
# Indexing on processed?, media tags, and timestamp (across all users)
# This is used for a front page tag search.
'index': [('state', ASCENDING),
('tags.slug', DESCENDING),
('created', DESCENDING)]}} ('created', DESCENDING)]}}

View File

@ -186,7 +186,7 @@ class MediaEntry(Document):
'media_type': unicode, 'media_type': unicode,
'media_data': dict, # extra data relevant to this media_type 'media_data': dict, # extra data relevant to this media_type
'plugin_data': dict, # plugins can dump stuff here. 'plugin_data': dict, # plugins can dump stuff here.
'tags': [unicode], 'tags': [dict],
'state': unicode, 'state': unicode,
# For now let's assume there can only be one main file queued # For now let's assume there can only be one main file queued

View File

@ -38,8 +38,9 @@ def require_active_login(controller):
def new_controller_func(request, *args, **kwargs): def new_controller_func(request, *args, **kwargs):
if request.user and \ if request.user and \
request.user.get('status') == u'needs_email_verification': request.user.get('status') == u'needs_email_verification':
return redirect(request, return redirect(
'mediagoblin.auth.verify_email_notice') request, 'mediagoblin.user_pages.user_home',
user=request.user['username'])
elif not request.user or request.user.get('status') != u'active': elif not request.user or request.user.get('status') != u'active':
return exc.HTTPFound( return exc.HTTPFound(
location="%s?next=%s" % ( location="%s?next=%s" % (

View File

@ -0,0 +1,17 @@
# 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/>.

View File

@ -17,20 +17,27 @@
import wtforms 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): class EditForm(wtforms.Form):
title = wtforms.TextField( title = wtforms.TextField(
'Title', _('Title'),
[wtforms.validators.Length(min=0, max=500)]) [wtforms.validators.Length(min=0, max=500)])
slug = wtforms.TextField( slug = wtforms.TextField(
'Slug', _('Slug'),
[wtforms.validators.Required(message="The slug can't be empty")]) [wtforms.validators.Required(message=_("The slug can't be empty"))])
description = wtforms.TextAreaField('Description of this work') description = wtforms.TextAreaField('Description of this work')
tags = wtforms.TextField(
_('Tags'),
[tag_length_validator])
class EditProfileForm(wtforms.Form): class EditProfileForm(wtforms.Form):
bio = wtforms.TextAreaField('Bio', bio = wtforms.TextAreaField(
_('Bio'),
[wtforms.validators.Length(min=0, max=500)]) [wtforms.validators.Length(min=0, max=500)])
url = wtforms.TextField( url = wtforms.TextField(
'Website', _('Website'),
[wtforms.validators.Optional(), [wtforms.validators.Optional(),
wtforms.validators.URL(message='Improperly formed URL')]) wtforms.validators.URL(message=_('Improperly formed URL'))])

View File

@ -16,10 +16,14 @@
from webob import exc from webob import exc
from string import split
from mediagoblin import messages from mediagoblin import messages
from mediagoblin import mg_globals
from mediagoblin.util import ( from mediagoblin.util import (
render_to_response, redirect, cleaned_markdown_conversion) 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 import forms
from mediagoblin.edit.lib import may_edit_media from mediagoblin.edit.lib import may_edit_media
from mediagoblin.decorators import require_active_login, get_user_media_entry from mediagoblin.decorators import require_active_login, get_user_media_entry
@ -34,7 +38,8 @@ def edit_media(request, media):
form = forms.EditForm(request.POST, form = forms.EditForm(request.POST,
title = media['title'], title = media['title'],
slug = media['slug'], slug = media['slug'],
description = media['description']) description = media['description'],
tags = media_tags_as_string(media['tags']))
if request.method == 'POST' and form.validate(): if request.method == 'POST' and form.validate():
# Make sure there isn't already a MediaEntry with such a slug # Make sure there isn't already a MediaEntry with such a slug
@ -46,11 +51,13 @@ def edit_media(request, media):
if existing_user_slug_entries: if existing_user_slug_entries:
form.slug.errors.append( 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: else:
media['title'] = request.POST['title'] media['title'] = request.POST['title']
media['description'] = request.POST.get('description') media['description'] = request.POST.get('description')
media['tags'] = convert_to_tag_list_of_dicts(
request.POST.get('tags'))
media['description_html'] = cleaned_markdown_conversion( media['description_html'] = cleaned_markdown_conversion(
media['description']) media['description'])
@ -65,7 +72,7 @@ def edit_media(request, media):
and request.method != 'POST': and request.method != 'POST':
messages.add_message( messages.add_message(
request, messages.WARNING, 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( return render_to_response(
@ -86,7 +93,7 @@ def edit_profile(request):
if request.method != 'POST': if request.method != 'POST':
messages.add_message( messages.add_message(
request, messages.WARNING, request, messages.WARNING,
"You are editing a user's profile. Proceed with caution.") _("You are editing a user's profile. Proceed with caution."))
else: else:
user = request.user user = request.user

View File

@ -40,6 +40,10 @@ SUBCOMMAND_MAP = {
'setup': 'mediagoblin.gmg_commands.users:changepw_parser_setup', 'setup': 'mediagoblin.gmg_commands.users:changepw_parser_setup',
'func': 'mediagoblin.gmg_commands.users:changepw', 'func': 'mediagoblin.gmg_commands.users:changepw',
'help': 'Makes admin an user'}, 'help': 'Makes admin an user'},
'wipealldata': {
'setup': 'mediagoblin.gmg_commands.wipealldata:wipe_parser_setup',
'func': 'mediagoblin.gmg_commands.wipealldata:wipe',
'help': 'Wipes **all** the data for this MediaGoblin instance'},
} }

View File

@ -1,3 +1,19 @@
# 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.gmg_commands import util as commands_util from mediagoblin.gmg_commands import util as commands_util
from mediagoblin.auth import lib as auth_lib from mediagoblin.auth import lib as auth_lib
from mediagoblin import mg_globals from mediagoblin import mg_globals

View File

@ -0,0 +1,51 @@
# GNU MediaGoblin -- federated, autonomous media hosting
# Copyright (C) 2011 Free Software Foundation, Inc
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys
import pymongo
import sys
import os
import shutil
def wipe_parser_setup(subparser):
pass
def wipe(args):
print "*** WARNING! ***"
print ""
print "Running this will destroy your mediagoblin database,"
print "remove all your media files in user_dev/, etc."
drop_it = raw_input(
'Are you **SURE** you want to destroy your environment? '
'(if so, type "yes")> ')
if not drop_it == 'yes':
return
print "nixing data in mongodb...."
conn = pymongo.Connection()
conn.drop_database('mediagoblin')
for directory in [os.path.join(os.getcwd(), "user_dev", "media"),
os.path.join(os.getcwd(), "user_dev", "beaker")]:
if os.path.exists(directory):
print "nixing %s...." % directory
shutil.rmtree(directory)
print "removed all your stuff! okay, now re-run ./bin/buildout"

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,292 @@
# 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-08 22:53-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: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,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,305 @@
# Translations template for PROJECT.
# Copyright (C) 2011 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
#
# <marktraceur@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:24+0000\n"
"Last-Translator: MarkTraceur <marktraceur@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: fr\n"
"Plural-Forms: nplurals=2; plural=(n > 1)\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 "Nous avons renvoyé votre e-mail de vérification."
#: 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 "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 "Soumettez des médias"
#: mediagoblin/templates/mediagoblin/base.html:62
msgid "verify your email!"
msgstr "vérifiez votre addresse e-mail"
#: mediagoblin/templates/mediagoblin/base.html:72
msgid "Login"
msgstr "Connexion"
#: 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 ""
"Alimenté par <a href=\"http://mediagoblin.org\">MediaGoblin</a>, un <a "
"href=\"http://gnu.org/\">projet GNU</a>"
#: mediagoblin/templates/mediagoblin/root.html:21
msgid "Welcome to GNU MediaGoblin!"
msgstr "Bienvenue à GNU MediaGoblin!"
#: mediagoblin/templates/mediagoblin/root.html:26
msgid "Submit an item"
msgstr "Soumettez un fichier"
#: 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 vous avez un compte, vous pouvez <a href=\"%(login_url)s\">Connecter</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 vous n'avez pas un compte, s'il vous plaît, <a "
"href=\"%(register_url)s\">vous inscrivez</a>."
#: mediagoblin/templates/mediagoblin/auth/login.html:26
msgid "Log in"
msgstr "Connexion"
#: mediagoblin/templates/mediagoblin/auth/login.html:29
msgid "Login failed!"
msgstr "Connexion manqué"
#: 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 "Soumettez"
#: mediagoblin/templates/mediagoblin/auth/login.html:42
msgid "Don't have an account yet?"
msgstr "N'avez-vous toujours un compte?"
#: mediagoblin/templates/mediagoblin/auth/login.html:45
msgid "Create one here!"
msgstr "En créez un ici!"
#: mediagoblin/templates/mediagoblin/auth/register.html:27
msgid "Create an account!"
msgstr "Créez 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 de GNU MediaGoblin, ouvrez l'URL suite avec votre navigateur web:\n"
"\n"
"%(verification_url)s"
#: mediagoblin/templates/mediagoblin/edit/edit.html:29
#, python-format
msgid "Editing %(media_title)s"
msgstr "On édit %(media_title)s"
#: mediagoblin/templates/mediagoblin/edit/edit.html:36
msgid "Cancel"
msgstr "Annulez"
#: mediagoblin/templates/mediagoblin/edit/edit.html:37
msgid "Save changes"
msgstr "Enregistrez les modifications"
#: 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,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,311 @@
# 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-08 22:53-0500\n"
"PO-Revision-Date: 2011-08-09 15:00+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:55
msgid "Sorry, a user with that name already exists."
msgstr "En användare med det användarnamnet finns redan."
#: mediagoblin/auth/views.py:152
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:158
msgid "The verification key or user id is incorrect"
msgstr "Verifieringsnyckeln eller användar-IDt är fel."
#: mediagoblin/auth/views.py:179
#: 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:26
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:29
msgid "File"
msgstr "Fil"
#: mediagoblin/submit/views.py:45
msgid "You must provide a file."
msgstr "Du måste ange en fil"
#: mediagoblin/submit/views.py:48
msgid "The file doesn't seem to be an image!"
msgstr "Filen verkar inte vara en giltig bildfil!"
#: mediagoblin/submit/views.py:96
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:21
msgid "Welcome to GNU MediaGoblin!"
msgstr "Välkommen till GNU MediaGoblin!"
#: mediagoblin/templates/mediagoblin/root.html:26
msgid "Submit an item"
msgstr "Ladda upp"
#: 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 ett konto? <a href=\"%(login_url)s\">Logga in</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 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:32
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:29
msgid "Media tagged with:"
msgstr "Taggat med:"
#: 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 "Ladda upp"
#: 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 media"
#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:51
#: mediagoblin/templates/mediagoblin/user_pages/user.html:30
msgid "Sorry, no such user found."
msgstr "Finns ingen sådan användare ännu."
#: mediagoblin/templates/mediagoblin/user_pages/user.html:37
#: mediagoblin/templates/mediagoblin/user_pages/user.html:57
msgid "Verification needed"
msgstr "Verifiering krävs"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:40
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:45
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:49
msgid "In case it doesn't:"
msgstr "Om det inte skulle göra det:"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:52
msgid "Resend verification email"
msgstr "Skicka ett nytt e-postmeddelande"
#: 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 finns redan ett konto med det här användarnamnet, men det behöver "
"verifieras."
#: 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 ""
"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:76
#, python-format
msgid "%(username)s's profile"
msgstr "%(username)ss profil"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:84
msgid "Edit profile"
msgstr "Redigera profil"
#: mediagoblin/templates/mediagoblin/user_pages/user.html:95
#, python-format
msgid "View all of %(username)s's media"
msgstr "Se all media från %(username)s"

View File

@ -23,6 +23,7 @@ from mediagoblin.mg_globals import setup_globals
from mediagoblin.db.open import setup_connection_and_db_from_config from mediagoblin.db.open import setup_connection_and_db_from_config
from mediagoblin.db.util import MigrationManager from mediagoblin.db.util import MigrationManager
from mediagoblin.workbench import WorkbenchManager from mediagoblin.workbench import WorkbenchManager
from mediagoblin.storage import storage_system_from_config
class Error(Exception): pass class Error(Exception): pass
@ -60,9 +61,16 @@ def setup_database():
# Tiny hack to warn user if our migration is out of date # Tiny hack to warn user if our migration is out of date
if not migration_manager.database_at_latest_migration(): if not migration_manager.database_at_latest_migration():
print ( db_migration_num = migration_manager.database_current_migration()
"*WARNING:* Your migrations are out of date, " latest_migration_num = migration_manager.latest_migration()
"maybe run ./bin/gmg migrate?") if db_migration_num < latest_migration_num:
print (
"*WARNING:* Your migrations are out of date, "
"maybe run ./bin/gmg migrate?")
elif db_migration_num > latest_migration_num:
print (
"*WARNING:* Your migrations are out of date... "
"in fact they appear to be from the future?!")
setup_globals( setup_globals(
db_connection = connection, db_connection = connection,
@ -103,6 +111,19 @@ def get_staticdirector(app_config):
"direct_remote_paths must be provided") "direct_remote_paths must be provided")
def setup_storage():
app_config = mg_globals.app_config
public_store = storage_system_from_config(app_config, 'publicstore')
queue_store = storage_system_from_config(app_config, 'queuestore')
setup_globals(
public_store = public_store,
queue_store = queue_store)
return public_store, queue_store
def setup_workbench(): def setup_workbench():
app_config = mg_globals.app_config app_config = mg_globals.app_config

View File

@ -1,4 +1,3 @@
{#
# GNU MediaGoblin -- federated, autonomous media hosting # GNU MediaGoblin -- federated, autonomous media hosting
# Copyright (C) 2011 Free Software Foundation, Inc # Copyright (C) 2011 Free Software Foundation, Inc
# #
@ -14,12 +13,7 @@
# #
# You should have received a copy of the GNU Affero General Public License # 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/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
#}
{% extends "mediagoblin/base.html" %}
{% block mediagoblin_content %} """
<p> Non-user listing views and routing should go in this submodule.
Register successful! :D <br /> """
You should get a confirmation email soon.
</p>
{% endblock %}

View File

@ -0,0 +1,28 @@
# 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 routes.route import Route
tag_routes = [
# Route('mediagoblin.listings.tags_home', "/",
# controller="mediagoblin.listings.views:tags_home"),
Route('mediagoblin.listings.tags_listing', "/{tag}/",
controller="mediagoblin.listings.views:tag_listing"),
Route('mediagoblin.listings.tag_atom_feed', "/{tag}/atom/",
controller="mediagoblin.listings.views:tag_atom_feed"),
]

View File

@ -0,0 +1,91 @@
# 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.db.util import DESCENDING
from mediagoblin.util import Pagination, render_to_response
from mediagoblin.decorators import uses_pagination
from werkzeug.contrib.atom import AtomFeed
def _get_tag_name_from_entries(media_entries, tag_slug):
"""
Get a tag name from the first entry by looking it up via its slug.
"""
# ... this is slightly hacky looking :\
tag_name = tag_slug
if media_entries.count():
for tag in media_entries[0]['tags']:
if tag['slug'] == tag_slug:
tag_name == tag['name']
break
return tag_name
@uses_pagination
def tag_listing(request, page):
"""'Gallery'/listing for this tag slug"""
tag_slug = request.matchdict[u'tag']
cursor = request.db.MediaEntry.find(
{u'state': u'processed',
u'tags.slug': tag_slug})
cursor = cursor.sort('created', DESCENDING)
pagination = Pagination(page, cursor)
media_entries = pagination()
tag_name = _get_tag_name_from_entries(media_entries, tag_slug)
return render_to_response(
request,
'mediagoblin/listings/tag.html',
{'tag_slug': tag_slug,
'tag_name': tag_name,
'media_entries': media_entries,
'pagination': pagination})
ATOM_DEFAULT_NR_OF_UPDATED_ITEMS = 15
def tag_atom_feed(request):
"""
generates the atom feed with the tag images
"""
tag_slug = request.matchdict[u'tag']
cursor = request.db.MediaEntry.find(
{u'state': u'processed',
u'tags.slug': tag_slug})
cursor = cursor.sort('created', DESCENDING)
cursor = cursor.limit(ATOM_DEFAULT_NR_OF_UPDATED_ITEMS)
feed = AtomFeed(
"MediaGoblin: Feed for tag '%s'" % tag_slug,
feed_url=request.url,
url=request.host_url)
for entry in cursor:
feed.add(entry.get('title'),
entry.get('description_html'),
content_type='html',
author=entry.uploader()['username'],
updated=entry.get('created'),
url=entry.url_for_self(request.urlgen))
return feed.get_response()

View File

@ -1,3 +1,18 @@
# 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/>.
""" """
In some places, we need to access the database, public_store, queue_store In some places, we need to access the database, public_store, queue_store
""" """

View File

@ -19,6 +19,7 @@ from mediagoblin.db.util import ObjectId
from celery.task import task from celery.task import task
from mediagoblin import mg_globals as mgg from mediagoblin import mg_globals as mgg
from contextlib import contextmanager
THUMB_SIZE = 180, 180 THUMB_SIZE = 180, 180
@ -31,6 +32,12 @@ def create_pub_filepath(entry, filename):
unicode(entry['_id']), unicode(entry['_id']),
filename]) filename])
@contextmanager
def closing(callback):
try:
yield callback
finally:
pass
@task @task
def process_media_initial(media_id): def process_media_initial(media_id):
@ -53,7 +60,7 @@ def process_media_initial(media_id):
thumb_filepath = create_pub_filepath(entry, 'thumbnail.jpg') thumb_filepath = create_pub_filepath(entry, 'thumbnail.jpg')
thumb_file = mgg.public_store.get_file(thumb_filepath, 'w') thumb_file = mgg.public_store.get_file(thumb_filepath, 'w')
with thumb_file: with closing(thumb_file):
thumb.save(thumb_file, "JPEG", quality=90) thumb.save(thumb_file, "JPEG", quality=90)
""" """
@ -73,7 +80,7 @@ def process_media_initial(media_id):
medium_filepath = create_pub_filepath(entry, 'medium.jpg') medium_filepath = create_pub_filepath(entry, 'medium.jpg')
medium_file = mgg.public_store.get_file(medium_filepath, 'w') 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.save(medium_file, "JPEG", quality=90)
medium_processed = True medium_processed = True
@ -84,7 +91,7 @@ def process_media_initial(media_id):
with queued_file: with queued_file:
original_filepath = create_pub_filepath(entry, queued_filepath[-1]) 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()) original_file.write(queued_file.read())
mgg.queue_store.delete_file(queued_filepath) mgg.queue_store.delete_file(queued_filepath)

View File

@ -20,6 +20,8 @@ from mediagoblin.auth.routing import auth_routes
from mediagoblin.submit.routing import submit_routes from mediagoblin.submit.routing import submit_routes
from mediagoblin.user_pages.routing import user_routes from mediagoblin.user_pages.routing import user_routes
from mediagoblin.edit.routing import edit_routes from mediagoblin.edit.routing import edit_routes
from mediagoblin.listings.routing import tag_routes
def get_mapper(): def get_mapper():
mapping = Mapper() mapping = Mapper()
@ -33,5 +35,6 @@ def get_mapper():
mapping.extend(submit_routes, '/submit') mapping.extend(submit_routes, '/submit')
mapping.extend(user_routes, '/u') mapping.extend(user_routes, '/u')
mapping.extend(edit_routes, '/edit') mapping.extend(edit_routes, '/edit')
mapping.extend(tag_routes, '/tag')
return mapping return mapping

View File

@ -1,15 +1,17 @@
body { body {
background-color: #1F1F1F; background-color: #111;
color: #aaa; background-image: url("../images/background.png");
color: #999;
font-family: sans-serif; font-family: sans-serif;
padding:none; padding: none;
margin:0px; margin: 0px;
height:100%; height: 100%;
font: 16px "HelveticaNeue-Light","Helvetica Neue Light","Helvetica Neue",Helvetica,Arial,sans-serif;
} }
form { form {
margin:0px; margin: 0px;
padding:0px; padding: 0px;
} }
/* Carter One font */ /* Carter One font */
@ -18,22 +20,34 @@ form {
font-family: 'Carter One'; font-family: 'Carter One';
font-style: normal; font-style: normal;
font-weight: normal; font-weight: normal;
src: local('CarterOne'), url('http://themes.googleusercontent.com/font?kit=FWNn6ITYqL6or7ZTmBxRhq3fkYX5z1QtDUdIWoaaD_k') format('woff'); src: local('CarterOne'), url('http://themes.googleusercontent.com/font?kit=VjW2qt1pkqVtO22ObxgEBRsxEYwM7FgeyaSgU71cLG0') format('woff');
} }
/* text styles */ /* text styles */
h1{ h1{
font-family: 'Carter One', arial, serif; font-family: 'Carter One',arial,serif;
margin-bottom: 15px; margin-bottom: 15px;
margin-top:15px; margin-top: 15px;
color: #fff;
font-size: 30px;
} }
h2{ h2{
margin-top:20px; margin-top: 20px;
color: #fff;
}
h3{
border-bottom: 1px solid #222;
font-size: 18px;
} }
a { a {
color: #999;
}
a.highlight {
color: #fff; color: #fff;
} }
@ -44,202 +58,207 @@ label {
/* website structure */ /* website structure */
.mediagoblin_body { .mediagoblin_body {
position:relative; position: relative;
min-height:100%; min-height: 100%;
} }
.mediagoblin_header { .mediagoblin_header {
width:100%; height: 36px;
height:36px; padding-top: 14px;
background-color:#2F2F2F; margin-bottom: 20px;
padding-top:14px; border-bottom: 1px solid #222222;
margin-bottom:40px;
} }
.header_submit{ .header_submit{
color:#272727; color: #272727;
background-color:#aaa; background-color: #aaa;
background-image: -webkit-gradient(linear, left top, left bottom, from(##D2D2D2), to(#aaa)); background-image: -webkit-gradient(linear, left top, left bottom, from(##D2D2D2), to(#aaa));
background-image: -webkit-linear-gradient(top, #D2D2D2, #aaa); background-image: -webkit-linear-gradient(top, #D2D2D2, #aaa);
background-image: -moz-linear-gradient(top, #D2D2D2, #aaa); background-image: -moz-linear-gradient(top, #D2D2D2, #aaa);
background-image: -ms-linear-gradient(top, #D2D2D2, #aaa); background-image: -ms-linear-gradient(top, #D2D2D2, #aaa);
background-image: -o-linear-gradient(top, #D2D2D2, #aaa); background-image: -o-linear-gradient(top, #D2D2D2, #aaa);
background-image: linear-gradient(top, #D2D2D2, #aaa); background-image: linear-gradient(top, #D2D2D2, #aaa);
box-shadow:0px 0px 4px #000; box-shadow: 0px 0px 4px #000;
border-radius:5px 5px 5px 5px; border-radius: 5px 5px 5px 5px;
margin:8px; margin: 8px;
padding:3px 8px; padding: 3px 8px;
text-decoration:none; text-decoration: none;
border:medium none; border: medium none;
font-family:'Carter One',arial,serif; font-family: 'Carter One',arial,serif;
} }
.mediagoblin_footer { .mediagoblin_footer {
width:100%; height: 30px;
height:30px; border-top: 1px solid #222222;
background-color:#2F2F2F; bottom: 0px;
bottom:0px; padding-top: 8px;
padding-top:8px; text-align: center;
position:absolute; font-size: 14px;
text-align:center; color: #999;
font-size:14px;
color:#999;
} }
.mediagoblin_content { .mediagoblin_content {
padding-bottom:74px; padding-bottom: 74px;
} }
.mediagoblin_header_right { .mediagoblin_header_right {
float:right; float: right;
} }
/* common website elements */ /* common website elements */
.button { .button {
font-family:'Carter One', arial, serif; font-family: 'Carter One', arial, serif;
height:32px; height: 32px;
min-width:99px; min-width: 99px;
background-color:#86d4b1; background-color: #86d4b1;
background-image: -webkit-gradient(linear, left top, left bottom, from(#86d4b1), to(#62caa2)); background-image: -webkit-gradient(linear, left top, left bottom, from(#86d4b1), to(#62caa2));
background-image: -webkit-linear-gradient(top, #86d4b1, #62caa2); background-image: -webkit-linear-gradient(top, #86d4b1, #62caa2);
background-image: -moz-linear-gradient(top, #86d4b1, #62caa2); background-image: -moz-linear-gradient(top, #86d4b1, #62caa2);
background-image: -ms-linear-gradient(top, #86d4b1, #62caa2); background-image: -ms-linear-gradient(top, #86d4b1, #62caa2);
background-image: -o-linear-gradient(top, #86d4b1, #62caa2); background-image: -o-linear-gradient(top, #86d4b1, #62caa2);
background-image: linear-gradient(top, #86d4b1, #62caa2); background-image: linear-gradient(top, #86d4b1, #62caa2);
box-shadow:0px 0px 4px #000; box-shadow: 0px 0px 4px #000;
border-radius:5px; border-radius: 5px;
border:none; border: none;
color:#272727; color: #272727;
margin:10px 0px 10px 15px; margin: 10px 0px 10px 15px;
font-size:1em; font-size: 1em;
text-align:center; text-align: center;
padding-left:11px; padding-left: 11px;
padding-right:11px; padding-right: 11px;
text-decoration: none;
} }
.pagination{ .pagination{
text-align:center; text-align: center;
} }
.pagination_arrow{ .pagination_arrow{
margin:5px; margin: 5px;
} }
/* forms */ /* forms */
.form_box { .form_box {
background-color:#393939; background-color: #222;
background-image:url("../images/background_lines.png"); background-image: url("../images/background_lines.png");
background-repeat:repeat-x; background-repeat: repeat-x;
font-size:18px; font-size: 18px;
padding-bottom:30px; padding-bottom: 30px;
padding-top:30px; padding-top: 30px;
margin-left:auto; margin-left: auto;
margin-right:auto; margin-right: auto;
display:block; display: block;
float:none; float: none;
} }
.edit_box { .edit_box {
background-image:url("../images/background_edit.png"); background-image: url("../images/background_edit.png");
} }
.form_box h1 { .form_box h1 {
font-size:28px; font-size: 28px;
} }
.form_field_input input, .form_field_input textarea { .form_field_input input, .form_field_input textarea {
width:100%; width: 100%;
font-size:18px; font-size: 18px;
} }
.form_field_box { .form_field_box {
margin-bottom:24px; margin-bottom: 24px;
} }
.form_field_label,.form_field_input { .form_field_label,.form_field_input {
margin-bottom:4px; margin-bottom: 4px;
} }
.form_field_error { .form_field_error {
background-color:#87453b; background-color: #87453b;
color:#fff; color: #fff;
border:none; border: none;
font-size:16px; font-size: 16px;
padding:9px; padding: 9px;
margin-top:8px; margin-top: 8px;
margin-bottom:8px; margin-bottom: 8px;
} }
.form_submit_buttons { .form_submit_buttons {
text-align:right; text-align: right;
} }
/* comments */ /* comments */
.comment_author { .comment_author {
margin-bottom:40px; margin-bottom: 40px;
padding-top:4px; padding-top: 4px;
font-size: 14px;
} }
.comment_content p { .comment_content p {
margin-bottom:4px; margin-bottom: 4px;
} }
/* media galleries */ /* media galleries */
.media_thumbnail { .media_thumbnail {
padding:0px; padding: 0px;
width:180px; width: 180px;
height:180px; height: 180px;
overflow:hidden; overflow: hidden;
float:left; float: left;
margin:0px 4px 10px 4px; margin: 0px 4px 10px 4px;
text-align:center; text-align: center;
}
/* media detail */
.media_image_container {
text-align: center;
} }
/* icons */ /* icons */
img.media_icon{ img.media_icon{
margin:0 4px; margin: 0 4px;
vertical-align:sub; vertical-align: sub;
} }
/* navigation */ /* navigation */
.navigation_button{ .navigation_button{
width:139px; width: 139px;
display:block; display: block;
float:left; float: left;
text-align:center; text-align: center;
background-color:#393939; background-color: #222;
text-decoration:none; text-decoration: none;
padding:12px 0pt; padding: 12px 0pt;
font-family:'Carter One', arial, serif; font-family: 'Carter One', arial, serif;
font-size:2em; font-size: 2em;
margin:0 0 20px margin: 0 0 20px
} }
p.navigation_button{ p.navigation_button{
color:#272727; color: #272727;
} }
.navigation_left{ .navigation_left{
margin-right:2px; margin-right: 2px;
} }
/* messages */ /* messages */
ul.mediagoblin_messages { ul.mediagoblin_messages {
list-style:none inside; list-style: none inside;
color:#f7f7f7; color: #f7f7f7;
} }
.mediagoblin_messages li { .mediagoblin_messages li {
margin:5px 0; margin: 5px 0;
padding:8px; padding: 8px;
text-align:center; text-align: center;
} }
.message_success { .message_success {
@ -260,5 +279,15 @@ ul.mediagoblin_messages {
.message_debug { .message_debug {
background-color: #f7f7f7; background-color: #f7f7f7;
color:#272727; color: #272727;
}
ul.mediaentry_tags {
list-style-type: none;
}
ul.mediaentry_tags li {
display: inline;
margin: 0px 5px 0px 0px;
padding: 0px;
} }

View File

@ -1 +0,0 @@
../../../contrib/960_16_col.css

View File

@ -1 +0,0 @@
../../../contrib/reset.css

View File

@ -1 +0,0 @@
../../../contrib/text.css

View File

@ -0,0 +1 @@
../../../../extlib/960.gs/960_16_col.css

View File

@ -0,0 +1 @@
../../../../extlib/960.gs/reset.css

View File

@ -0,0 +1 @@
../../../../extlib/960.gs/text.css

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -19,6 +19,7 @@ import re
import shutil import shutil
import urlparse import urlparse
import uuid import uuid
import cloudfiles
from werkzeug.utils import secure_filename from werkzeug.utils import secure_filename
@ -28,11 +29,21 @@ from mediagoblin import util
# Errors # 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 +128,7 @@ class StorageInterface(object):
Eg, if the filename doesn't exist: Eg, if the filename doesn't exist:
>>> storage_handler.get_unique_filename(['dir1', 'dir2', 'fname.jpg']) >>> storage_handler.get_unique_filename(['dir1', 'dir2', 'fname.jpg'])
[u'dir1', u'dir2', u'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: 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']) >>> storage_handler.get_unique_filename(['dir1', 'dir2', 'fname.jpg'])
[u'dir1', u'dir2', u'd02c3571-dd62-4479-9d62-9e3012dada29-fname.jpg'] [u'dir1', u'dir2', u'd02c3571-dd62-4479-9d62-9e3012dada29-fname.jpg']
@ -184,7 +195,7 @@ class BasicFileStorage(StorageInterface):
""" """
return os.path.join( return os.path.join(
self.base_dir, *clean_listy_filepath(filepath)) self.base_dir, *clean_listy_filepath(filepath))
def file_exists(self, filepath): def file_exists(self, filepath):
return os.path.exists(self._resolve_filepath(filepath)) return os.path.exists(self._resolve_filepath(filepath))
@ -216,6 +227,191 @@ class BasicFileStorage(StorageInterface):
return self._resolve_filepath(filepath) 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, requests for ["store1", "a"] to first
storage with the path ["a"], etc.
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 # Utilities
########### ###########
@ -283,7 +479,7 @@ def storage_system_from_config(paste_config, storage_prefix):
for key, value in paste_config.iteritems() for key, value in paste_config.iteritems()
if prefix_re.match(key)]) if prefix_re.match(key)])
if config_params.has_key('storage_class'): if 'storage_class' in config_params:
storage_class = config_params['storage_class'] storage_class = config_params['storage_class']
config_params.pop('storage_class') config_params.pop('storage_class')
else: else:
@ -291,5 +487,3 @@ def storage_system_from_config(paste_config, storage_prefix):
storage_class = util.import_component(storage_class) storage_class = util.import_component(storage_class)
return storage_class(**config_params) return storage_class(**config_params)

View File

@ -0,0 +1,17 @@
# 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/>.

View File

@ -17,10 +17,16 @@
import wtforms import wtforms
from mediagoblin.util import tag_length_validator
from mediagoblin.util import fake_ugettext_passthrough as _
class SubmitStartForm(wtforms.Form): class SubmitStartForm(wtforms.Form):
title = wtforms.TextField( title = wtforms.TextField(
'Title', _('Title'),
[wtforms.validators.Length(min=0, max=500)]) [wtforms.validators.Length(min=0, max=500)])
description = wtforms.TextAreaField('Description of this work') description = wtforms.TextAreaField('Description of this work')
file = wtforms.FileField('File') file = wtforms.FileField(_('File'))
tags = wtforms.TextField(
_('Tags'),
[tag_length_validator])

View File

@ -16,11 +16,14 @@
from os.path import splitext from os.path import splitext
from cgi import FieldStorage from cgi import FieldStorage
from string import split
from werkzeug.utils import secure_filename from werkzeug.utils import secure_filename
from mediagoblin.util import ( from mediagoblin.util import (
render_to_response, redirect, cleaned_markdown_conversion) 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.decorators import require_active_login
from mediagoblin.submit import forms as submit_forms, security from mediagoblin.submit import forms as submit_forms, security
from mediagoblin.process_media import process_media_initial from mediagoblin.process_media import process_media_initial
@ -39,10 +42,10 @@ def submit_start(request):
and isinstance(request.POST['file'], FieldStorage) and isinstance(request.POST['file'], FieldStorage)
and request.POST['file'].file): and request.POST['file'].file):
submit_form.file.errors.append( 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']): elif not security.check_filetype(request.POST['file']):
submit_form.file.errors.append( 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: else:
filename = request.POST['file'].filename filename = request.POST['file'].filename
@ -59,6 +62,10 @@ def submit_start(request):
entry['media_type'] = u'image' # heh entry['media_type'] = u'image' # heh
entry['uploader'] = request.user['_id'] entry['uploader'] = request.user['_id']
# Process the user's folksonomy "tags"
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 # Save, just so we can get the entry id for the sake of using
# it to generate the file path # it to generate the file path
entry.save(validate=False) entry.save(validate=False)
@ -87,7 +94,7 @@ def submit_start(request):
result = process_media_initial.delay(unicode(entry['_id'])) result = process_media_initial.delay(unicode(entry['_id']))
entry['queued_task_id'] = result.task_id entry['queued_task_id'] = result.task_id
add_message(request, SUCCESS, 'Woohoo! Submitted!') add_message(request, SUCCESS, _('Woohoo! Submitted!'))
return redirect(request, "mediagoblin.user_pages.user_home", return redirect(request, "mediagoblin.user_pages.user_home",
user = request.user['username']) user = request.user['username'])

View File

@ -23,20 +23,27 @@
<form action="{{ request.urlgen('mediagoblin.auth.login') }}" <form action="{{ request.urlgen('mediagoblin.auth.login') }}"
method="POST" enctype="multipart/form-data"> method="POST" enctype="multipart/form-data">
<div class="grid_6 prefix_1 suffix_1 form_box"> <div class="grid_6 prefix_1 suffix_1 form_box">
<h1>Log in</h1> <h1>{% trans %}Log in{% endtrans %}</h1>
{% if login_failed %} {% if login_failed %}
<div class="form_field_error">Login failed!</div> <div class="form_field_error">
{% trans %}Login failed!{% endtrans %}
</div>
{% endif %} {% endif %}
{{ wtforms_util.render_divs(login_form) }} {{ wtforms_util.render_divs(login_form) }}
<div class="form_submit_buttons"> <div class="form_submit_buttons">
<input type="submit" value="submit" class="button"/> <input type="submit" value="{% trans %}Submit{% endtrans %}" class="button"/>
</div> </div>
{% if next %} {% if next %}
<input type="hidden" name="next" value="{{ next }}" class="button" <input type="hidden" name="next" value="{{ next }}" class="button"
style="display: none;"/> style="display: none;"/>
{% endif %} {% endif %}
{% if allow_registration %} {% 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 %} {% endif %}
</div> </div>
</form> </form>

View File

@ -24,10 +24,11 @@
<form action="{{ request.urlgen('mediagoblin.auth.register') }}" <form action="{{ request.urlgen('mediagoblin.auth.register') }}"
method="POST" enctype="multipart/form-data"> method="POST" enctype="multipart/form-data">
<div class="grid_6 prefix_1 suffix_1 form_box"> <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) }} {{ wtforms_util.render_divs(register_form) }}
<div class="form_submit_buttons"> <div class="form_submit_buttons">
<input type="submit" value="submit" class="button" /> <input type="submit" value="{% trans %}Submit{% endtrans %}"
class="button" />
</div> </div>
</div> </div>
</form> </form>

View File

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

View File

@ -14,9 +14,13 @@
# #
# You should have received a copy of the GNU Affero General Public License # 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/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
#} -#}
{% trans username=username, verification_url=verification_url|safe -%}
Hi {{ username }}, 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,13 +19,13 @@
<html> <html>
<head> <head>
<meta charset="utf-8"> <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" <link rel="stylesheet" type="text/css"
href="{{ request.staticdirect('/css/contrib/reset.css') }}"/> href="{{ request.staticdirect('/css/extlib/reset.css') }}"/>
<link rel="stylesheet" type="text/css" <link rel="stylesheet" type="text/css"
href="{{ request.staticdirect('/css/contrib/text.css') }}"/> href="{{ request.staticdirect('/css/extlib/text.css') }}"/>
<link rel="stylesheet" type="text/css" <link rel="stylesheet" type="text/css"
href="{{ request.staticdirect('/css/contrib/960_16_col.css') }}"/> href="{{ request.staticdirect('/css/extlib/960_16_col.css') }}"/>
<link rel="stylesheet" type="text/css" <link rel="stylesheet" type="text/css"
href="{{ request.staticdirect('/css/base.css') }}"/> href="{{ request.staticdirect('/css/base.css') }}"/>
{% block mediagoblin_head %} {% block mediagoblin_head %}
@ -36,27 +36,41 @@
{% block mediagoblin_body %} {% block mediagoblin_body %}
<div class="mediagoblin_body"> <div class="mediagoblin_body">
{% block mediagoblin_header %} {% block mediagoblin_header %}
<div class="mediagoblin_header"> <div class="container_16">
<div class="container_16"> <div class="grid_16 mediagoblin_header">
<div class="grid_16"> {% block mediagoblin_logo %}
{% block mediagoblin_logo %} <a class="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') }}">
{% endblock %} <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') }}">
{% trans %}Submit media{% endtrans %}
</a>
{% endif %}
{% block mediagoblin_header_title %}{% endblock %}
<div class="mediagoblin_header_right">
{% if request.user %} {% if request.user %}
<a class="header_submit" href="{{ request.urlgen('mediagoblin.submit.start') }}">Submit media</a> {# the following link should only appear when verification is needed #}
{% endif %} {% if request.user.status == "needs_email_verification" %}
{% block mediagoblin_header_title %}{% endblock %}
<div class="mediagoblin_header_right">
{% if request.user %}
<a href="{{ request.urlgen('mediagoblin.user_pages.user_home', <a href="{{ request.urlgen('mediagoblin.user_pages.user_home',
user= request.user['username']) }}"> user=request.user['username']) }}"
{{ request.user['username'] }}</a>'s account class="header_submit">
(<a href="{{ request.urlgen('mediagoblin.auth.logout') }}">logout</a>) {% trans %}verify your email!{% endtrans %}</a>
{% else %}
<a href="{{ request.urlgen('mediagoblin.auth.login') }}">
Login</a>
{% endif %} {% endif %}
</div>
<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>)
{% else %}
<a href="{{ request.urlgen('mediagoblin.auth.login') }}">
{% trans %}Login{% endtrans %}</a>
{% endif %}
</div> </div>
</div> </div>
</div> </div>
@ -69,11 +83,11 @@
</div> </div>
</div> </div>
{% block mediagoblin_footer %} {% block mediagoblin_footer %}
<div class="mediagoblin_footer"> <div class="container_16">
<div class="container_16"> <div class="grid_16 mediagoblin_footer">
<div class="grid_16"> {% trans -%}
Powered by <a href="http://mediagoblin.org">MediaGoblin</a>, a <a href="http://gnu.org/">GNU project</a> Powered by <a href="http://mediagoblin.org">MediaGoblin</a>, a <a href="http://gnu.org/">GNU project</a>
</div> {%- endtrans %}
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -26,15 +26,15 @@
media= media._id) }}" media= media._id) }}"
method="POST" enctype="multipart/form-data"> method="POST" enctype="multipart/form-data">
<div class="grid_8 prefix_1 suffix_1 edit_box form_box"> <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;" > <div style="text-align: center;" >
<img src="{{ request.app.public_store.file_url( <img src="{{ request.app.public_store.file_url(
media['media_files']['thumb']) }}" /> media['media_files']['thumb']) }}" />
</div> </div>
{{ wtforms_util.render_divs(form) }} {{ wtforms_util.render_divs(form) }}
<div class="form_submit_buttons"> <div class="form_submit_buttons">
<a href="{{ media.url_for_self(request.urlgen) }}">Cancel</a> <a href="{{ media.url_for_self(request.urlgen) }}">{% trans %}Cancel{% endtrans %}</a>
<input type="submit" value="Save changes" class="button" /> <input type="submit" value="{% trans %}Save changes{% endtrans %}" class="button" />
</div> </div>
</div> </div>
</form> </form>

View File

@ -25,10 +25,14 @@
user['username'] }}" user['username'] }}"
method="POST" enctype="multipart/form-data"> method="POST" enctype="multipart/form-data">
<div class="grid_8 prefix_1 suffix_1 edit_box form_box"> <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) }} {{ wtforms_util.render_divs(form) }}
<div class="form_submit_buttons"> <div class="form_submit_buttons">
<input type="submit" value="submit" class="button" /> <input type="submit" value="{% trans %}Submit{% endtrans %}" class="button" />
</div> </div>
</div> </div>
</form> </form>

View File

@ -0,0 +1,43 @@
{#
# 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_head %}
<link rel="alternate" type="application/atom+xml"
href="{{ request.urlgen(
'mediagoblin.listings.tag_atom_feed',
tag=tag_slug) }}">
{% endblock mediagoblin_head %}
{% block mediagoblin_content -%}
<h1>
{% trans %}Media tagged with:{% endtrans %} {{ tag_name }}
</h1>
<div class="container_16 media_gallery">
{% include "mediagoblin/utils/object_gallery.html" %}
</div>
<div class="grid_16">
<a href="{{ request.urlgen(
'mediagoblin.listings.tag_atom_feed',
tag=tag_slug) }}">
{%- trans %}atom feed{% endtrans -%}
</a>
</div>
{% endblock %}

View File

@ -22,22 +22,26 @@
{% if request.user %} {% if request.user %}
<p> <p>
<a href="{{ request.urlgen('mediagoblin.submit.start') }}">Submit an item</a> <a href="{{ request.urlgen('mediagoblin.submit.start') }}">
{%- trans %}Submit an item{% endtrans -%}
</a>
</p> </p>
{% else %} {% else %}
<p> <p>
If you have an account, you can {% trans login_url=request.urlgen('mediagoblin.auth.login') -%}
<a href="{{ request.urlgen('mediagoblin.auth.login') }}">Login</a>. If you have an account, you can <a href="{{ login_url }}">Login</a>.
{%- endtrans %}
</p> </p>
{% if allow_registration %} {% if allow_registration %}
<p> <p>
If you don't have an account, please {% trans register_url=request.urlgen('mediagoblin.auth.register') -%}
<a href="{{ request.urlgen('mediagoblin.auth.register') }}">Register</a>. If you don't have an account, please <a href="{{ register_url }}">Register</a>.
{%- endtrans %}
</p> </p>
{% endif %} {% endif %}
{% endif %} {% endif %}
{# temporarily, an "image gallery" that isn't one really ;) #} {# temporarily, an "image gallery" that isn't one really ;) #}
{% include "mediagoblin/utils/object_gallery.html" %} {% include "mediagoblin/utils/object_gallery.html" %}
{% endblock %} {% endblock %}

View File

@ -23,12 +23,13 @@
<form action="{{ request.urlgen('mediagoblin.submit.start') }}" <form action="{{ request.urlgen('mediagoblin.submit.start') }}"
method="POST" enctype="multipart/form-data"> method="POST" enctype="multipart/form-data">
<div class="grid_8 prefix_1 suffix_1 form_box"> <div class="grid_8 prefix_1 suffix_1 form_box">
<h1>Submit yer media</h1> <h1>{% trans %}Submit yer media{% endtrans %}</h1>
{{ wtforms_util.render_field_div(submit_form.file) }} {{ wtforms_util.render_field_div(submit_form.file) }}
{{ wtforms_util.render_field_div(submit_form.title) }} {{ wtforms_util.render_field_div(submit_form.title) }}
{{ wtforms_util.render_textarea_div(submit_form.description) }} {{ wtforms_util.render_textarea_div(submit_form.description) }}
{{ wtforms_util.render_field_div(submit_form.tags) }}
<div class="form_submit_buttons"> <div class="form_submit_buttons">
<input type="submit" value="Submit" class="button" /> <input type="submit" value="{% trans %}Submit{% endtrans %}" class="button" />
</div> </div>
</div> </div>
</form> </form>

View File

@ -27,21 +27,27 @@
{% block mediagoblin_content -%} {% block mediagoblin_content -%}
{% if user %} {% if user %}
<h1> <h1>
<a href="{{ request.urlgen( {%- trans username=user.username,
'mediagoblin.user_pages.user_home', user_url=request.urlgen(
user=user.username) }}">{{ user.username }}</a>'s media</h1> 'mediagoblin.user_pages.user_home',
user=user.username) -%}
<a href="{{ user_url }}">{{ username }}</a>'s media
{%- endtrans %}
</h1>
</div> </div>
<div class="container_16 media_gallery"> <div class="container_16 media_gallery">
{% include "mediagoblin/utils/object_gallery.html" %} {% include "mediagoblin/utils/object_gallery.html" %}
</div> </div>
<div class="grid_16"> <div class="grid_16">
<a href="{{ request.urlgen(
<a href={{ request.urlgen( 'mediagoblin.user_pages.atom_feed',
'mediagoblin.user_pages.atom_feed', user=user.username) }}">
user=user.username) }}> atom feed</a> {%- trans %}atom feed{% endtrans -%}
</a>
</div>
{% else %} {% else %}
{# This *should* not occur as the view makes sure we pass in a user. #} {# 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 %} {% endif %}
{% endblock %} {% endblock %}

Some files were not shown because too many files have changed in this diff Show More