diff options
173 files changed, 8293 insertions, 4016 deletions
@@ -13,6 +13,7 @@ Thank you! * Alex Camelio * Bernhard Keller * Caleb Forbes Davis V +* Corey Farwell * Chris Moylan * Christopher Allan Webber * Daniel Neel @@ -27,6 +28,7 @@ Thank you! * Nathan Yergler * Odin Hørthe Omdal * Osama Khalid +* Pablo J. Urbano Santos * Rasmus Larsson * Sam Kleinman * Sebastian Spaeth @@ -8,19 +8,18 @@ What is GNU MediaGoblin? * Initially, a place to store all your photos that’s as awesome as, if not more awesome than, existing network services (Flickr, SmugMug, Picasa, etc) -* Later, a place for all sorts of media, such as video, music, etc hosting. -* Federated with OStatus! * Customizable! * A place for people to collaborate and show off original and derived - creations. Free, as in freedom. We’re a GNU project in the making, - afterall. + creations. Free, as in freedom. We’re a GNU project after all. +* Later, a place for all sorts of media, such as video, music, etc hosting. +* Later, federated with OStatus! Is it ready for me to use? ========================== -Not yet! We're working on it and we hope to have a usable system by -September / October 2011. +Yes! But with caveats. The software is usable and there are instances +running, but it's still in its early stages. Can I help/hang out/participate/whisper sweet nothings in your ear? @@ -33,9 +32,9 @@ hang out, see `our Join page <http://mediagoblin.org/join/>`_ Where is the documentation? =========================== -The beginnings of a user manual is located in the ``docs/`` directory -in HTML, Texinfo, and source (Restructured Text) forms. It's also -available online at http://docs.mediagoblin.org/ in HTML form. +The beginnings of a site administration manual is located in the ``docs/`` +directory in HTML, Texinfo, and source (Restructured Text) forms. It's +also 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 @@ -4,9 +4,12 @@ [jinja2: mediagoblin/templates/**.html] # Extract jinja templates (html) encoding = utf-8 +extensions = jinja2.ext.autoescape + [jinja2: mediagoblin/templates/**.txt] # Extract jinja templates (text) encoding = utf-8 +extensions = jinja2.ext.autoescape # # Extraction from JavaScript files # [javascript: mediagoblin/static/js/**.js] diff --git a/docs/source/_templates/mg_theme/layout.html b/docs/source/_templates/mg_theme/layout.html deleted file mode 100644 index eccda14b..00000000 --- a/docs/source/_templates/mg_theme/layout.html +++ /dev/null @@ -1,39 +0,0 @@ -{# - 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 %}© <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 %} diff --git a/docs/source/_templates/mg_theme/static/default.css_t b/docs/source/_templates/mg_theme/static/default.css_t deleted file mode 100644 index f200a0fe..00000000 --- a/docs/source/_templates/mg_theme/static/default.css_t +++ /dev/null @@ -1,299 +0,0 @@ -/* - * 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; -} diff --git a/docs/source/_templates/mg_theme/theme.conf b/docs/source/_templates/mg_theme/theme.conf deleted file mode 100644 index 49442e3b..00000000 --- a/docs/source/_templates/mg_theme/theme.conf +++ /dev/null @@ -1,31 +0,0 @@ -[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 diff --git a/docs/source/conf.py b/docs/source/conf.py index eee9900f..dce254a1 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -28,7 +28,7 @@ sys.path.insert(0, os.path.abspath('.')) extensions = ["mgext.youcanhelp"] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ['source/_templates'] # The suffix of source filenames. source_suffix = '.rst' @@ -48,9 +48,9 @@ copyright = u'2011, Free Software Foundation, Inc and contributors' # built documents. # # The short X.Y version. -version = '0.1.0' +version = '0.3.0' # The full version, including alpha/beta/rc tags. -release = '0.1.0' +release = '0.3.0-dev' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -91,7 +91,8 @@ pygments_style = 'sphinx' # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'default' +# html_theme = 'default' +html_theme = 'mg' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the @@ -99,7 +100,7 @@ html_theme = 'default' #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] +html_theme_path = ['themes'] # The name for this set of Sphinx documents. If None, it defaults to # "<project> v<release> documentation". diff --git a/docs/source/configuration.rst b/docs/source/configuration.rst index 093f492c..1e22ad2d 100644 --- a/docs/source/configuration.rst +++ b/docs/source/configuration.rst @@ -19,13 +19,13 @@ mediagoblin.ini tweak settings for MediaGoblin, you'll usually tweak them here. paste.ini - This is primarily a server configuration file, on the python side - (specifically, on the wsgi side, via `paste deploy + This is primarily a server configuration file, on the Python side + (specifically, on the WSGI side, via `paste deploy <http://pythonpaste.org/deploy/>`_ / `paste script <http://pythonpaste.org/script/>`_). It also sets up some middleware that you can mostly ignore, except to configure sessions... more on that later. If you are adding a different - python server other than fastcgi / plain http, you might configure + Python server other than fastcgi / plain HTTP, you might configure it here. You probably won't need to change this file very much. @@ -47,19 +47,23 @@ Let's assume you're doing the virtualenv setup described elsewhere in this manual, and you need to make local tweaks to the config files. How do you do that? Let's see. -To make changes to mediagoblin.ini: +To make changes to mediagoblin.ini :: - cp mediagoblin.ini mediagoblin_local.ini + cp mediagoblin.ini mediagoblin_local.ini -To make changes to paste.ini: - cp paste.ini paste_local.ini +To make changes to paste.ini :: + + cp paste.ini paste_local.ini From here you should be able to make direct adjustments to the files, and most of the commands described elsewhere in this manual will "notice" your local config files and use those instead of the non-local version. -(Note that all commands provide a way to pass in a specific config -file also, usually by a -cf flag.) +.. note:: + + Note that all commands provide a way to pass in a specific config + file also, usually by a ``-cf`` flag. + Common changes ============== @@ -69,9 +73,9 @@ Enabling email notifications You'll almost certainly want to enable sending emails. By default, MediaGoblin doesn't really do this... for the sake of developer -convenience, it runs in "email debug mode". Change this: +convenience, it runs in "email debug mode". Change this:: - email_debug_mode = false + email_debug_mode = false You can (and should) change the "from" email address by setting ``email_sender_address``. @@ -82,21 +86,21 @@ If you have more custom SMTP settings, you also have the following options at your disposal, which are all optional, and do exactly what they sound like. - - email_smtp_host - - email_smtp_port - - email_smtp_user - - email_smtp_pass +- email_smtp_host +- email_smtp_port +- email_smtp_user +- email_smtp_pass All other configuration changes ------------------------------- -To be perfectly honest, there are quite a few options and I'm not -going to be able to get to documanting them all in time for 0.1.0. +To be perfectly honest, there are quite a few options and we haven't had +time to document them all So here's a cop-out section saying that if you get into trouble, hop -onto IRC and we'll help you out: +onto IRC and we'll help you out:: - #mediagoblin on irc.freenode.net + #mediagoblin on irc.freenode.net Celery ====== diff --git a/docs/source/deploying.rst b/docs/source/deploying.rst index c2ba0c47..4aded2e6 100644 --- a/docs/source/deploying.rst +++ b/docs/source/deploying.rst @@ -11,9 +11,11 @@ it simple with some assumptions and use a setup that combines mediagoblin + virtualenv + fastcgi + nginx on a .deb or .rpm based GNU/Linux distro. -Note: these tools are for administrators wanting to deploy a fresh -install. If instead you want to join in as a contributor, see our -`Hacking HOWTO <http://wiki.mediagoblin.org/HackingHowto>`_ instead. +.. note:: + + These tools are for site administrators wanting to deploy a fresh + install. If instead you want to join in as a contributor, see our + `Hacking HOWTO <http://wiki.mediagoblin.org/HackingHowto>`_ instead. Prepare System -------------- @@ -33,12 +35,15 @@ MediaGoblin has the following core dependencies: On a DEB-based system (e.g Debian, gNewSense, Trisquel, Ubuntu, and derivatives) issue the following command: :: - sudo apt-get install mongodb git-core python python-dev python-lxml python-imaging python-virtualenv + sudo apt-get install mongodb git-core python python-dev python-lxml \ + python-imaging python-virtualenv On a RPM-based system (e.g. Fedora, RedHat, and derivatives) issue the following command: :: - yum install mongodb-server python-paste-deploy python-paste-script git-core python python-devel python-lxml python-imaging python-virtualenv + yum install mongodb-server python-paste-deploy python-paste-script \ + git-core python python-devel python-lxml python-imaging \ + python-virtualenv Configure MongoDB ~~~~~~~~~~~~~~~~~ @@ -46,10 +51,11 @@ Configure MongoDB After installing MongoDB some preliminary database configuration may be necessary. -Ensure that MongoDB `journaling <http://www.mongodb.org/display/DOCS/Journaling>`_ -is enabled. Journaling is enabled by default in version 2.0 and later -64-bit MongoDB instances. Check your deployment, and consider enabling -journaling if you're running 32-bit systems or earlier version. +Ensure that MongoDB `journaling +<http://www.mongodb.org/display/DOCS/Journaling>`_ is enabled. Journaling +is enabled by default in version 2.0 and later 64-bit MongoDB instances. +Check your deployment, and consider enabling journaling if you're running +32-bit systems or earlier version. .. warning:: @@ -77,41 +83,42 @@ create "system account" or dedicated service user. Ensure that it is not possible to log in to your system with as this user. You should create a working directory for MediaGoblin. This document -assumes your local git repository will be located at ``/srv/mediagoblin.example.org/mediagoblin/`` -for this documentation. Substitute your prefer ed local deployment path -as needed. +assumes your local git repository will be located at +``/srv/mediagoblin.example.org/mediagoblin/`` for this documentation. +Substitute your prefer ed local deployment path as needed. This document assumes that all operations are performed as this user. To drop privileges to this user, run the following command: :: + su - [mediagoblin] - su - [mediagoblin]`` - -Where, "``[mediagoblin]`` is the username of the system user that will +Where, "``[mediagoblin]``" is the username of the system user that will run MediaGoblin. Install MediaGoblin and Virtualenv ---------------------------------- -As of |version|, MediaGoblin has a rapid development pace. As a result -the following instructions recommend installing from the ``master`` -branch of the git repository. Eventually production deployments will -want to transition to running from more consistent releases. +.. note:: + + As of |version|, MediaGoblin has a rapid development pace. As a result + the following instructions recommend installing from the ``master`` + branch of the git repository. Eventually production deployments will + want to transition to running from more consistent releases. Issue the following commands, to create and change the working -directory. Modify these commands to reflect your own environment: :: +directory. Modify these commands to reflect your own environment:: - mkdir -p /srv/mediagoblin.example.org/ - cd /srv/mediagoblin.example.org/ + mkdir -p /srv/mediagoblin.example.org/ + cd /srv/mediagoblin.example.org/ -Clone the MediaGoblin repository: :: +Clone the MediaGoblin repository:: - git clone git://gitorious.org/mediagoblin/mediagoblin.git + git clone git://gitorious.org/mediagoblin/mediagoblin.git -And setup the in-package virtualenv: :: +And setup the in-package virtualenv:: - cd mediagoblin - virtualenv . && ./bin/python setup.py develop + cd mediagoblin + virtualenv . && ./bin/python setup.py develop .. note:: @@ -127,16 +134,16 @@ more reliable and considerably easier to configure and illustrate. If you're familiar with Python packaging you may consider deploying with your preferred the method. -Assuming you are going to deploy with fastcgi, you should also install -flup: :: +Assuming you are going to deploy with FastCGI, you should also install +flup:: - ./bin/easy_install flup + ./bin/easy_install flup This concludes the initial configuration of the development environment. In the future, if at any point you want update your -codebase, you should also run: :: +codebase, you should also run:: - ./bin/python setup.py develop --upgrade && ./bin/gmg migrate. + ./bin/python setup.py develop --upgrade && ./bin/gmg migrate. Deploy MediaGoblin Services --------------------------- @@ -145,9 +152,9 @@ Test the Server ~~~~~~~~~~~~~~~ At this point MediaGoblin should be properly installed. You can -test the deployment with the following command: :: +test the deployment with the following command:: - ./lazyserver.sh --server-name=broadcast + ./lazyserver.sh --server-name=broadcast You should be able to connect to the machine on port 6543 in your browser to confirm that the service is operable. @@ -156,7 +163,7 @@ Connect the Webserver to MediaGoblin with FastCGI ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This section describes how to configure MediaGoblin to work via -fastcgi. Our configuration example will use nginx, however, you may +FastCGI. Our configuration example will use nginx, however, you may use any webserver of your choice as long as it supports the FastCGI protocol. If you do not already have a web server, consider nginx, as the configuration files may be more clear than the @@ -166,99 +173,85 @@ Create a configuration file at ``/srv/mediagoblin.example.org/nginx.conf`` and create a symbolic link into a directory that will be included in your ``nginx`` configuration (e.g. "``/etc/nginx/sites-enabled`` or ``/etc/nginx/conf.d``) with -one of the following commands (as the root user:) :: +one of the following commands (as the root user):: - ln -s /srv/mediagoblin.example.org/nginx.conf /etc/nginx/conf.d/ - ln -s /srv/mediagoblin.example.org/nginx.conf /etc/nginx/sites-enabled/ + ln -s /srv/mediagoblin.example.org/nginx.conf /etc/nginx/conf.d/ + ln -s /srv/mediagoblin.example.org/nginx.conf /etc/nginx/sites-enabled/ Modify these commands and locations depending on your preferences and the existing configuration of your nginx instance. The contents of -this ``nginx.conf`` file should be modeled on the following: :: - - server { - ################################################# - # Stock useful config options, but ignore them :) - ################################################# - include /etc/nginx/mime.types; - - autoindex off; - default_type application/octet-stream; - sendfile on; - - # Gzip - gzip on; - gzip_min_length 1024; - gzip_buffers 4 32k; - gzip_types text/plain text/html application/x-javascript text/javascript text/xml text/css; - - ##################################### - # Mounting MediaGoblin stuff - # This is the section you should read - ##################################### - - server_name mediagoblin.example.org www.mediagoblin.example.org; - access_log /var/log/nginx/mediagoblin.example.access.log; - error_log /var/log/nginx/mediagoblin.example.error.log; - - # MediaGoblin's stock static files: CSS, JS, etc. - location /mgoblin_static/ { - alias /srv/mediagoblin.example.org/mediagoblin/mediagoblin/static/; - } - - # Instance specific media: - location /mgoblin_media/ { - alias /srv/mediagoblin.example.org/mediagoblin/mediagoblin/user_dev/media/public/; - } - - # Mounting MediaGoblin itself via fastcgi. - location / { - fastcgi_pass 127.0.0.1:26543; - include /etc/nginx/fastcgi_params; - - # our understanding vs nginx's handling of script_name vs - # path_info don't match :) - fastcgi_param PATH_INFO $fastcgi_script_name; - fastcgi_param SCRIPT_NAME ""; - } +this ``nginx.conf`` file should be modeled on the following:: + + server { + ################################################# + # Stock useful config options, but ignore them :) + ################################################# + include /etc/nginx/mime.types; + + autoindex off; + default_type application/octet-stream; + sendfile on; + + # Gzip + gzip on; + gzip_min_length 1024; + gzip_buffers 4 32k; + gzip_types text/plain text/html application/x-javascript text/javascript text/xml text/css; + + ##################################### + # Mounting MediaGoblin stuff + # This is the section you should read + ##################################### + + # Change this to update the upload size limit for your users + client_max_body_size 8m; + + server_name mediagoblin.example.org www.mediagoblin.example.org; + access_log /var/log/nginx/mediagoblin.example.access.log; + error_log /var/log/nginx/mediagoblin.example.error.log; + + # MediaGoblin's stock static files: CSS, JS, etc. + location /mgoblin_static/ { + alias /srv/mediagoblin.example.org/mediagoblin/mediagoblin/static/; + } + + # Instance specific media: + location /mgoblin_media/ { + alias /srv/mediagoblin.example.org/mediagoblin/user_dev/media/public/; } + # Mounting MediaGoblin itself via FastCGI. + location / { + fastcgi_pass 127.0.0.1:26543; + include /etc/nginx/fastcgi_params; + + # our understanding vs nginx's handling of script_name vs + # path_info don't match :) + fastcgi_param PATH_INFO $fastcgi_script_name; + fastcgi_param SCRIPT_NAME ""; + } + } + Now, nginx instance is configured to serve the MediaGoblin application. Perform a quick test to ensure that this configuration works. Restart nginx so it picks up your changes, with a command that -resembles one of the following (as the root user:) :: +resembles one of the following (as the root user):: - sudo /etc/init.d/nginx restart - sudo /etc/rc.d/nginx restart + sudo /etc/init.d/nginx restart + sudo /etc/rc.d/nginx restart Now start MediaGoblin. Use the following command sequence as an -example: :: +example:: - cd /srv/mediagoblin.example.org/mediagoblin/ - ./lazyserver.sh --server-name=fcgi fcgi_host=127.0.0.1 fcgi_port=26543 + cd /srv/mediagoblin.example.org/mediagoblin/ + ./lazyserver.sh --server-name=fcgi fcgi_host=127.0.0.1 fcgi_port=26543 Visit the site you've set up in your browser by visiting <http://mediagobilin.example.org>. You should see MediaGoblin! -Production MediaGoblin Deployments with Paste -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The instance configured with ``lazyserver`` is not ideal for a -production MediaGoblin deployment. Ideally, you should be able to use -a a control script (i.e. init script.) to launch and restart the -MediaGoblin process. - -Use the following command as the basis for such a script: :: - - CELERY_ALWAYS_EAGER=true \ - /srv/mediagoblin.example.org/mediagoblin/bin/paster serve \ - /srv/mediagoblin.example.org/mediagoblin/paste.ini \ - --pid-file=/tmp/mediagoblin.pid \ - --server-name=fcgi fcgi_host=127.0.0.1 fcgi_port=26543 \ - .. note:: - The above configuration places MediaGoblin in "always eager" mode - with Celery. This is fine for development and smaller - deployments. However, if you're getting into the really large - deployment category, consider reading the section of this manual on - Celery. + The configuration described above is sufficient for development and + smaller deployments. However, for larger production deployments + with larger processing requirements, see the + ":doc:`production-deployments`" documentation. diff --git a/docs/source/foreword.rst b/docs/source/foreword.rst index 835a7e7a..aa27647f 100644 --- a/docs/source/foreword.rst +++ b/docs/source/foreword.rst @@ -5,14 +5,14 @@ Foreword About the MediaGoblin Manual ============================ -This is the user manual for MediaGoblin. It covers how to set up and -configure MediaGoblin and the kind of information that someone running -MediaGoblin would need to know. +This is the site administrator manual for MediaGoblin. It covers how +to set up and configure MediaGoblin and the kind of information that +someone running MediaGoblin would need to know. We have other documentation at: * http://mediagoblin.org/join/ for general "join us" information -* http://wiki.mediagoblin.org/ for our contributor-focused wiki +* http://wiki.mediagoblin.org/ for our contributor/developer-focused wiki Improving the MediaGobiin Manual diff --git a/docs/source/index.rst b/docs/source/index.rst index e9f3993e..f9c9285d 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -14,7 +14,9 @@ Table of Contents: foreword about deploying + production-deployments configuration + media-types help theming codebase diff --git a/docs/source/media-types.rst b/docs/source/media-types.rst new file mode 100644 index 00000000..76478143 --- /dev/null +++ b/docs/source/media-types.rst @@ -0,0 +1,34 @@ +.. _media-types-chapter: + +==================== +Enabling Media Types +==================== + +In the future, there will be all sorts of media types you can enable, +but in the meanwhile there's only one additional media type: video. + +First, you should probably read ":doc:`configuration`" to make sure +you know how to modify the mediagoblin config file. + +Video +===== + +To enable video, first install gstreamer and the python-gstreamer +bindings (as well as whatever gstremaer extensions you want, +good/bad/ugly). On Debianoid systems:: + + sudo apt-get install python-gst0.10 + +Next, modify (and possibly copy over from ``mediagoblin.ini``) your +``mediagoblin_local.ini``. Uncomment this line in the ``[mediagoblin]`` +section:: + + media_types = mediagoblin.media_types.image, mediagoblin.media_types.video + +Now you should be able to submit videos, and mediagoblin should +transcode them. + +Note that you almost certainly want to separate Celery from the normal +paste process or your users will probably find that their connections +time out as the video transcodes. To set that up, check out the +":doc:`production-deployments`" section of this manual. diff --git a/docs/source/production-deployments.rst b/docs/source/production-deployments.rst new file mode 100644 index 00000000..ef0bcad6 --- /dev/null +++ b/docs/source/production-deployments.rst @@ -0,0 +1,81 @@ +========================================= +Considerations for Production Deployments +========================================= + +This document contains a number of suggestions for deploying +MediaGoblin in actual production environments. Consider +":doc:`deploying`" for a basic overview of how to deploy MediaGoblin. + +Deploy with Paste +----------------- + +The instance configured with ``./lazyserver.sh`` is not ideal for a +production MediaGoblin deployment. Ideally, you should be able to use +an "init" or "control" script to launch and restart the MediaGoblin +process. + +Use the following command as the basis for such a script: :: + + CELERY_ALWAYS_EAGER=true \ + /srv/mediagoblin.example.org/mediagoblin/bin/paster serve \ + /srv/mediagoblin.example.org/mediagoblin/paste.ini \ + --pid-file=/var/run/mediagoblin.pid \ + --server-name=fcgi fcgi_host=127.0.0.1 fcgi_port=26543 + +The above configuration places MediaGoblin in "always eager" mode +with Celery, this means that submissions of content will be processed +synchronously, and the user will advance to the next page only after +processing is complete. If we take Celery out of "always eager mode," +the user will be able to immediately return to the MediaGoblin site +while processing is ongoing. In these cases, use the following command +as the basis for your script: :: + + CELERY_ALWAYS_EAGER=false \ + /srv/mediagoblin.example.org/mediagoblin/bin/paster serve \ + /srv/mediagoblin.example.org/mediagoblin/paste.ini \ + --pid-file=/var/run/mediagoblin.pid \ + --server-name=fcgi fcgi_host=127.0.0.1 fcgi_port=26543 + +Separate Celery +--------------- + +While the ``./lazyserer.sh`` configuration provides an efficient way to +start using a MediaGoblin instance, it is not suitable for production +deployments for several reasons: + +In nearly every scenario, work on the Celery queue will need to +balance with the demands of other processes, and cannot proceed +synchronously. This is a particularly relevant problem if you use +MediaGoblin to host video content. Processing with Celery ought to be +operationally separate from the MediaGoblin application itself, this +simplifies management and support better workload distribution. + +Basically, if you're doing anything beyond a trivial workload, such as +image hosting for a small set of users, or have limited media types +such as "ASCII art" or icon sharing, you will need to run ``celeryd`` +as a separate process. + +Build an :ref:`init script <init-script>` around the following +command:: + + CELERY_CONFIG_MODULE=mediagoblin.init.celery.from_celery ./bin/celeryd + +Modify your existing MediaGoblin and application init scripts, if +necessary, to prevent them from starting their own ``celeryd`` +processes. + +.. _init-script: + +Use an Init Script +------------------ + +Look in your system's ``/etc/init.d/`` or ``/etc/rc.d/`` directory for +examples of how to build scripts that will start, stop, and restart +MediaGoblin and Celery. These scripts will vary by +distribution/operating system. In the future, MediaGoblin will provide +example scripts as examples. + +.. TODO insert init script here +.. TODO are additional concerns ? + .. Other Concerns + .. -------------- diff --git a/docs/source/themes/mg/layout.html b/docs/source/themes/mg/layout.html new file mode 100644 index 00000000..891ed64c --- /dev/null +++ b/docs/source/themes/mg/layout.html @@ -0,0 +1,29 @@ +{# + 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> + +MediaGoblin documentation released into the public domain via <a href="http://creativecommons.org/publicdomain/zero/1.0/">CC0</a>. + + {%- 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> + </div> +{%- endblock %} diff --git a/docs/source/themes/mg/theme.conf b/docs/source/themes/mg/theme.conf new file mode 100644 index 00000000..f4fbd8cc --- /dev/null +++ b/docs/source/themes/mg/theme.conf @@ -0,0 +1,5 @@ +[theme] +inherit = default +stylesheet = default.css +pygments_style = sphinx + diff --git a/extlib/jquery/MIT.txt b/extlib/jquery/MIT.txt new file mode 100644 index 00000000..5a2aeb47 --- /dev/null +++ b/extlib/jquery/MIT.txt @@ -0,0 +1,20 @@ +Copyright (c) <year> <copyright holders> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/extlib/jquery/jquery.js b/extlib/jquery/jquery.js new file mode 100644 index 00000000..198b3ff0 --- /dev/null +++ b/extlib/jquery/jquery.js @@ -0,0 +1,4 @@ +/*! jQuery v1.7.1 jquery.com | jquery.org/license */ +(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function cb(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function ca(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bE.test(a)?d(a,e):ca(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)ca(a+"["+e+"]",b[e],c,d);else d(a,b)}function b_(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function b$(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bT,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=b$(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=b$(a,c,d,e,"*",g));return l}function bZ(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bP),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bC(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bx:by,g=0,h=e.length;if(d>0){if(c!=="border")for(;g<h;g++)c||(d-=parseFloat(f.css(a,"padding"+e[g]))||0),c==="margin"?d+=parseFloat(f.css(a,c+e[g]))||0:d-=parseFloat(f.css(a,"border"+e[g]+"Width"))||0;return d+"px"}d=bz(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0;if(c)for(;g<h;g++)d+=parseFloat(f.css(a,"padding"+e[g]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+e[g]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+e[g]))||0);return d+"px"}function bp(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c+(i[c][d].namespace?".":"")+i[c][d].namespace,i[c][d],i[c][d].data)}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?m(g):h==="function"&&(!a.unique||!o.has(g))&&c.push(g)},n=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,l=j||0,j=0,k=c.length;for(;c&&l<k;l++)if(c[l].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}i=!1,c&&(a.once?e===!0?o.disable():c=[]:d&&d.length&&(e=d.shift(),o.fireWith(e[0],e[1])))},o={add:function(){if(c){var a=c.length;m(arguments),i?k=c.length:e&&e!==!0&&(j=a,n(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){i&&f<=k&&(k--,f<=l&&l--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&o.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(i?a.once||d.push([b,c]):(!a.once||!e)&&n(b,c));return this},fire:function(){o.fireWith(this,arguments);return this},fired:function(){return!!e}};return o};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p,q=c.createElement("div"),r=c.documentElement;q.setAttribute("className","t"),q.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="<div "+n+"><div></div></div>"+"<table "+n+" cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="<div style='width:4px;'></div>",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h=null;if(typeof a=="undefined"){if(this.length){h=f.data(this[0]);if(this[0].nodeType===1&&!f._data(this[0],"parsedAttrs")){e=this[0].attributes;for(var i=0,j=e.length;i<j;i++)g=e[i].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),l(this[0],g,h[g]));f._data(this[0],"parsedAttrs",!0)}}return h}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split("."),d[1]=d[1]?"."+d[1]:"";if(c===b){h=this.triggerHandler("getData"+d[1]+"!",[d[0]]),h===b&&this.length&&(h=f.data(this[0],a),h=l(this[0],a,h));return h===b&&d[1]?this.data(d[0]):h}return this.each(function(){var b=f(this),e=[d[0],c];b.triggerHandler("setData"+d[1]+"!",e),f.data(this,a,c),b.triggerHandler("changeData"+d[1]+"!",e)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise()}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h<g;h++)e=d[h],e&&(c=f.propFix[e]||e,f.attr(a,e,""),a.removeAttribute(v?e:c),u.test(e)&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")}; +f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=[],j,k,l,m,n,o,p,q,r,s,t;g[0]=c,c.delegateTarget=this;if(e&&!c.target.disabled&&(!c.button||c.type!=="click")){m=f(this),m.context=this.ownerDocument||this;for(l=c.target;l!=this;l=l.parentNode||this){o={},q=[],m[0]=l;for(j=0;j<e;j++)r=d[j],s=r.selector,o[s]===b&&(o[s]=r.quick?H(l,r.quick):m.is(s)),o[s]&&q.push(r);q.length&&i.push({elem:l,matches:q})}}d.length>e&&i.push({elem:this,matches:d.slice(e)});for(j=0;j<i.length&&!c.isPropagationStopped();j++){p=i[j],c.currentTarget=p.elem;for(k=0;k<p.matches.length&&!c.isImmediatePropagationStopped();k++){r=p.matches[k];if(h||!c.namespace&&!r.namespace||c.namespace_re&&c.namespace_re.test(r.namespace))c.data=r.data,c.handleObj=r,n=((f.event.special[r.origType]||{}).handle||r.handler).apply(p.elem,g),n!==b&&(c.result=n,n===!1&&(c.preventDefault(),c.stopPropagation()))}}return c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0)}),d._submit_attached=!0)})},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on.call(this,a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.type+"."+e.namespace:e.type,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.POS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function() +{for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bp)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1></$2>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bn(k[i]);else bn(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||be.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bq=/alpha\([^)]*\)/i,br=/opacity=([^)]*)/,bs=/([A-Z]|^ms)/g,bt=/^-?\d+(?:px)?$/i,bu=/^-?\d/,bv=/^([\-+])=([\-+.\de]+)/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Left","Right"],by=["Top","Bottom"],bz,bA,bB;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bz(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bv.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bz)return bz(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return bC(a,b,d);f.swap(a,bw,function(){e=bC(a,b,d)});return e}},set:function(a,b){if(!bt.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS)return bS.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bU,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)ca(g,a[g],c,e);return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch)ch[a](0,1)}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cv(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cu("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cu("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cv(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cn.test(h)?(o=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),o?(f._data(this,"toggle"+i,o==="show"?"hide":"show"),j[o]()):j[h]()):(k=co.exec(h),l=j.cur(),k?(m=parseFloat(k[2]),n=k[3]||(f.cssNumber[i]?"":"px"),n!=="px"&&(f.style(this,i,(m||1)+n),l=(m||1)/j.cur()*l,f.style(this,i,l+n)),k[1]&&(m=(k[1]==="-="?-1:1)*m+l),j.custom(l,m,n)):j.custom(l,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:cu("show",1),slideUp:cu("hide",1),slideToggle:cu("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cr||cs(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){e.options.hide&&f._data(e.elem,"fxshow"+e.prop)===b&&f._data(e.elem,"fxshow"+e.prop,e.start)},h()&&f.timers.push(h)&&!cp&&(cp=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cr||cs(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cp),cp=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(["width","height"],function(a,b){f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cy(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.support.fixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.support.fixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window);
\ No newline at end of file diff --git a/lazyserver.sh b/lazyserver.sh index 63818a6a..4ca073b5 100755 --- a/lazyserver.sh +++ b/lazyserver.sh @@ -16,6 +16,10 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# This runs Mediagoblin using Paste with Celery set to always eager mode. +# + if [ "$1" = "-h" ] then echo "$0 [-h] [-c paste.ini] [ARGS_to_paster ...]" diff --git a/mediagoblin.ini b/mediagoblin.ini index 728ab2f2..dbde6e51 100644 --- a/mediagoblin.ini +++ b/mediagoblin.ini @@ -11,6 +11,9 @@ email_debug_mode = true # Set to false to disable registrations allow_registration = true +## Uncomment this to turn on video or enable other media types +# media_types = mediagoblin.media_types.image, mediagoblin.media_types.video + ## Uncomment this to put some user-overriding templates here #local_templates = %(here)s/user_dev/templates/ diff --git a/mediagoblin/_version.py b/mediagoblin/_version.py index d6c6e20d..5e69f21a 100644 --- a/mediagoblin/_version.py +++ b/mediagoblin/_version.py @@ -14,4 +14,13 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -__version__ = "0.1.0" +# valid version formats: +# * x.y - final release +# * x.ya1 - alpha 1 +# * x.yb1 - beta 1 +# * x.yrc1 - release candidate 1 +# * x.y.dev - dev + +# see http://www.python.org/dev/peps/pep-0386/ + +__version__ = "0.3.0.dev" diff --git a/mediagoblin/app.py b/mediagoblin/app.py index d39469c3..04eb2acc 100644 --- a/mediagoblin/app.py +++ b/mediagoblin/app.py @@ -20,7 +20,7 @@ import urllib import routes from webob import Request, exc -from mediagoblin import routing, middleware +from mediagoblin import routing, meddleware from mediagoblin.tools import common, translate, template from mediagoblin.tools.response import render_404 from mediagoblin.tools import request as mg_request @@ -63,7 +63,7 @@ class MediaGoblinApp(object): # Get the template environment self.template_loader = get_jinja_loader( - app_config.get('user_template_path')) + app_config.get('local_templates')) # Set up storage systems self.public_store, self.queue_store = setup_storage() @@ -94,26 +94,19 @@ class MediaGoblinApp(object): # object. ####################################################### - setup_globals(app = self) + setup_globals(app=self) # Workbench *currently* only used by celery, so this only # matters in always eager mode :) setup_workbench() - # instantiate application middleware - self.middleware = [common.import_component(m)(self) - for m in middleware.ENABLED_MIDDLEWARE] - + # instantiate application meddleware + self.meddleware = [common.import_component(m)(self) + for m in meddleware.ENABLED_MEDDLEWARE] def __call__(self, environ, start_response): request = Request(environ) - # pass the request through our middleware classes - for m in self.middleware: - response = m.process_request(request) - if response is not None: - return response(environ, start_response) - ## Routing / controller loading stuff path_info = request.path_info route_match = self.routing.match(path_info) @@ -165,13 +158,20 @@ class MediaGoblinApp(object): return render_404(request)(environ, start_response) controller = common.import_component(route_match['controller']) + + # pass the request through our meddleware classes + for m in self.meddleware: + response = m.process_request(request, controller) + if response is not None: + return response(environ, start_response) + request.start_response = start_response # get the response from the controller response = controller(request) - # pass the response through the middleware - for m in self.middleware[::-1]: + # pass the response through the meddleware + for m in self.meddleware[::-1]: m.process_response(request, response) return response(environ, start_response) diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index a932ad26..4cd3e9d8 100644 --- a/mediagoblin/auth/forms.py +++ b/mediagoblin/auth/forms.py @@ -29,15 +29,7 @@ class RegistrationForm(wtforms.Form): password = wtforms.PasswordField( _('Password'), [wtforms.validators.Required(), - wtforms.validators.Length(min=6, max=30), - wtforms.validators.EqualTo( - 'confirm_password', - _('Passwords must match.'))]) - confirm_password = wtforms.PasswordField( - _('Confirm password'), - [wtforms.validators.Required()], - description=_( - u"Type it again here to make sure there are no spelling mistakes.")) + wtforms.validators.Length(min=6, max=30)]) email = wtforms.TextField( _('Email address'), [wtforms.validators.Required(), @@ -59,9 +51,10 @@ class ForgotPassForm(wtforms.Form): 'Username or email', [wtforms.validators.Required()]) - def validate_username(form,field): - if not (re.match(r'^\w+$',field.data) or - re.match(r'^.+@[^.].*\.[a-z]{2,10}$',field.data, re.IGNORECASE)): + def validate_username(form, field): + if not (re.match(r'^\w+$', field.data) or + re.match(r'^.+@[^.].*\.[a-z]{2,10}$', field.data, + re.IGNORECASE)): raise wtforms.ValidationError(u'Incorrect input') @@ -82,4 +75,3 @@ class ChangePassForm(wtforms.Form): token = wtforms.HiddenField( '', [wtforms.validators.Required()]) - diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index 4c57ef88..c0af3b5b 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -94,6 +94,7 @@ EMAIL_VERIFICATION_TEMPLATE = ( u"http://{host}{uri}?" u"userid={userid}&token={verification_key}") + def send_verification_email(user, request): """ Send the verification email to users to activate their accounts. @@ -104,17 +105,17 @@ def send_verification_email(user, request): """ rendered_email = render_template( request, 'mediagoblin/auth/verification_email.txt', - {'username': user['username'], + {'username': user.username, 'verification_url': EMAIL_VERIFICATION_TEMPLATE.format( host=request.host, uri=request.urlgen('mediagoblin.auth.verify_email'), - userid=unicode(user['_id']), - verification_key=user['verification_key'])}) + userid=unicode(user._id), + verification_key=user.verification_key)}) # TODO: There is no error handling in place send_email( mg_globals.app_config['email_sender_address'], - [user['email']], + [user.email], # TODO # Due to the distributed nature of GNU MediaGoblin, we should # find a way to send some additional information about the @@ -128,6 +129,7 @@ EMAIL_FP_VERIFICATION_TEMPLATE = ( u"http://{host}{uri}?" u"userid={userid}&token={fp_verification_key}") + def send_fp_verification_email(user, request): """ Send the verification email to users to change their password. @@ -138,17 +140,16 @@ def send_fp_verification_email(user, request): """ rendered_email = render_template( request, 'mediagoblin/auth/fp_verification_email.txt', - {'username': user['username'], + {'username': user.username, 'verification_url': EMAIL_FP_VERIFICATION_TEMPLATE.format( host=request.host, uri=request.urlgen('mediagoblin.auth.verify_forgot_password'), - userid=unicode(user['_id']), - fp_verification_key=user['fp_verification_key'])}) + userid=unicode(user._id), + fp_verification_key=user.fp_verification_key)}) # TODO: There is no error handling in place send_email( mg_globals.app_config['email_sender_address'], - [user['email']], + [user.email], 'GNU MediaGoblin - Change forgotten password!', rendered_email) - diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py index 912d89fa..365ccfaa 100644 --- a/mediagoblin/auth/routing.py +++ b/mediagoblin/auth/routing.py @@ -33,7 +33,8 @@ auth_routes = [ controller='mediagoblin.views:simple_template_render'), Route('mediagoblin.auth.forgot_password', '/forgot_password/', controller='mediagoblin.auth.views:forgot_password'), - Route('mediagoblin.auth.verify_forgot_password', '/forgot_password/verify/', + Route('mediagoblin.auth.verify_forgot_password', + '/forgot_password/verify/', controller='mediagoblin.auth.views:verify_forgot_password'), Route('mediagoblin.auth.fp_changed_success', '/forgot_password/changed_success/', diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 2a670679..919aa3cd 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -74,20 +74,20 @@ def register(request): extra_validation_passes = False if users_with_email: register_form.email.errors.append( - _(u'Sorry, that email address has already been taken.')) + _(u'Sorry, a user with that email address already exists.')) extra_validation_passes = False if extra_validation_passes: # Create the user user = request.db.User() - user['username'] = username - user['email'] = email - user['pw_hash'] = auth_lib.bcrypt_gen_password_hash( + user.username = username + user.email = email + user.pw_hash = auth_lib.bcrypt_gen_password_hash( request.POST['password']) user.save(validate=True) # log the user in - request.session['user_id'] = unicode(user['_id']) + request.session['user_id'] = unicode(user._id) request.session.save() # send verification email @@ -98,7 +98,7 @@ def register(request): # message waiting for them to verify their email return redirect( request, 'mediagoblin.user_pages.user_home', - user=user['username']) + user=user.username) return render_to_response( request, @@ -122,7 +122,7 @@ def login(request): if user and user.check_login(request.POST['password']): # set up login in session - request.session['user_id'] = unicode(user['_id']) + request.session['user_id'] = unicode(user._id) request.session.save() if request.POST.get('next'): @@ -160,16 +160,16 @@ def verify_email(request): you are lucky :) """ # If we don't have userid and token parameters, we can't do anything; 404 - if not request.GET.has_key('userid') or not request.GET.has_key('token'): + if not 'userid' in request.GET or not 'token' in request.GET: return render_404(request) user = request.db.User.find_one( {'_id': ObjectId(unicode(request.GET['userid']))}) - if user and user['verification_key'] == unicode(request.GET['token']): - user[u'status'] = u'active' - user[u'email_verified'] = True - user[u'verification_key'] = None + if user and user.verification_key == unicode(request.GET['token']): + user.status = u'active' + user.email_verified = True + user.verification_key = None user.save() @@ -186,7 +186,7 @@ def verify_email(request): return redirect( request, 'mediagoblin.user_pages.user_home', - user=user['username']) + user=user.username) def resend_activation(request): @@ -195,9 +195,26 @@ def resend_activation(request): Resend the activation email. """ - request.user[u'verification_key'] = unicode(uuid.uuid4()) - request.user.save() + if request.user is None: + messages.add_message( + request, + messages.ERROR, + _('You must be logged in so we know who to send the email to!')) + + return redirect(request, 'mediagoblin.auth.login') + + if request.user["email_verified"]: + messages.add_message( + request, + messages.ERROR, + _("You've already verified your email address!")) + + return redirect(request, "mediagoblin.user_pages.user_home", user=request.user['username']) + + request.user.verification_key = unicode(uuid.uuid4()) + request.user.save() + email_debug_message(request) send_verification_email(request.user, request) @@ -207,7 +224,7 @@ def resend_activation(request): _('Resent your verification email.')) return redirect( request, 'mediagoblin.user_pages.user_home', - user=request.user['username']) + user=request.user.username) def forgot_password(request): @@ -232,9 +249,9 @@ def forgot_password(request): {'email': request.POST['username']}) if user: - if user['email_verified'] and user['status'] == 'active': - user[u'fp_verification_key'] = unicode(uuid.uuid4()) - user[u'fp_token_expire'] = datetime.datetime.now() + \ + if user.email_verified and user.status == 'active': + user.fp_verification_key = unicode(uuid.uuid4()) + user.fp_token_expire = datetime.datetime.now() + \ datetime.timedelta(days=10) user.save() @@ -251,10 +268,9 @@ def forgot_password(request): return redirect( request, 'mediagoblin.user_pages.user_home', - user=user['username']) - + user=user.username) - # do not reveal whether or not there is a matching user, just move along + # do not reveal whether or not there is a matching user return redirect(request, 'mediagoblin.auth.fp_email_sent') return render_to_response( @@ -285,18 +301,18 @@ def verify_forgot_password(request): return render_404(request) # check if we have a real user and correct token - if ((user and user['fp_verification_key'] and - user['fp_verification_key'] == unicode(formdata_token) and - datetime.datetime.now() < user['fp_token_expire'] - and user['email_verified'] and user['status'] == 'active')): + if ((user and user.fp_verification_key and + user.fp_verification_key == unicode(formdata_token) and + datetime.datetime.now() < user.fp_token_expire + and user.email_verified and user.status == 'active')): cp_form = auth_forms.ChangePassForm(formdata_vars) if request.method == 'POST' and cp_form.validate(): - user[u'pw_hash'] = auth_lib.bcrypt_gen_password_hash( + user.pw_hash = auth_lib.bcrypt_gen_password_hash( request.POST['password']) - user[u'fp_verification_key'] = None - user[u'fp_token_expire'] = None + user.fp_verification_key = None + user.fp_token_expire = None user.save() return redirect(request, 'mediagoblin.auth.fp_changed_success') @@ -328,6 +344,6 @@ def _process_for_token(request): formdata = { 'vars': formdata_vars, 'has_userid_and_token': - formdata_vars.has_key('userid') and formdata_vars.has_key('token')} + 'userid' in formdata_vars and 'token' in formdata_vars} return formdata diff --git a/mediagoblin/config_spec.ini b/mediagoblin/config_spec.ini index 900957ce..eb22bc1b 100644 --- a/mediagoblin/config_spec.ini +++ b/mediagoblin/config_spec.ini @@ -1,14 +1,18 @@ [mediagoblin] +# HTML title of the pages +html_title = string(default="GNU MediaGoblin") + +# Enabled media types +media_types = string_list(default=list("mediagoblin.media_types.image")) + # database stuff db_host = string() db_name = string(default="mediagoblin") db_port = integer() - # Where temporary files used in processing and etc are kept workbench_path = string(default="%(here)s/user_dev/media/workbench") - # Where mediagoblin-builtin static assets are kept direct_remote_path = string(default="/mgoblin_static/") @@ -24,9 +28,11 @@ email_smtp_pass = string(default=None) allow_registration = boolean(default=True) # tag parsing -tags_delimiter = string(default=",") tags_max_length = integer(default=50) +# Whether comments are ascending or descending +comments_ascending = boolean(default=True) + # By default not set, but you might want something like: # "%(here)s/user_dev/templates/" local_templates = string() @@ -44,6 +50,7 @@ allow_attachments = boolean(default=False) # Cookie stuff csrf_cookie_name = string(default='mediagoblin_csrftoken') + [storage:publicstore] storage_class = string(default="mediagoblin.storage.filestorage:BasicFileStorage") base_dir = string(default="%(here)s/user_dev/media/public") @@ -54,6 +61,11 @@ storage_class = string(default="mediagoblin.storage.filestorage:BasicFileStorage base_dir = string(default="%(here)s/user_dev/media/queue") +# Should we keep the original file? +[media_type:mediagoblin.media_types.video] +keep_original = boolean(default=False) + + [beaker.cache] type = string(default="file") data_dir = string(default="%(here)s/user_dev/beaker/cache/data") diff --git a/mediagoblin/db/__init__.py b/mediagoblin/db/__init__.py index c5124b1a..27e8a90f 100644 --- a/mediagoblin/db/__init__.py +++ b/mediagoblin/db/__init__.py @@ -23,7 +23,7 @@ Database Abstraction/Wrapper Layer pymongo. Read beow for why, but note that nobody is actually doing this and there's no proof that we'll ever support more than MongoDB... it would be a huge amount of work to do so. - + If you really want to prove that possible, jump on IRC and talk to us about making such a branch. In the meanwhile, it doesn't hurt to have things as they are... if it ever makes it hard for us to diff --git a/mediagoblin/db/indexes.py b/mediagoblin/db/indexes.py index 75394a31..1dd73f2b 100644 --- a/mediagoblin/db/indexes.py +++ b/mediagoblin/db/indexes.py @@ -93,8 +93,9 @@ MEDIAENTRY_INDEXES = { ('created', DESCENDING)]}, 'state_uploader_tags_created': { - # Indexing on processed?, media uploader, associated tags, and timestamp - # Used for showing media items matching a tag search, most recent first. + # Indexing on processed?, media uploader, associated tags, and + # timestamp Used for showing media items matching a tag + # search, most recent first. 'index': [('state', ASCENDING), ('uploader', ASCENDING), ('tags.slug', DESCENDING), diff --git a/mediagoblin/db/migrations.py b/mediagoblin/db/migrations.py index edaf5630..cfc01287 100644 --- a/mediagoblin/db/migrations.py +++ b/mediagoblin/db/migrations.py @@ -100,3 +100,11 @@ def user_add_forgot_password_token_and_expires(database): """ add_table_field(database, 'users', 'fp_verification_key', None) add_table_field(database, 'users', 'fp_token_expire', None) + + +@RegisterMigration(7) +def media_type_image_to_multimedia_type_image(database): + database['media_entries'].update( + {'media_type': 'image'}, + {'$set': {'media_type': 'mediagoblin.media_types.image'}}, + multi=True) diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py index 0f5174cc..569c3600 100644 --- a/mediagoblin/db/models.py +++ b/mediagoblin/db/models.py @@ -14,7 +14,8 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -import datetime, uuid +import datetime +import uuid from mongokit import Document @@ -62,22 +63,23 @@ class User(Document): - bio_html: biography of the user converted to proper HTML. """ __collection__ = 'users' + use_dot_notation = True structure = { 'username': unicode, 'email': unicode, 'created': datetime.datetime, - 'plugin_data': dict, # plugins can dump stuff here. + 'plugin_data': dict, # plugins can dump stuff here. 'pw_hash': unicode, 'email_verified': bool, 'status': unicode, 'verification_key': unicode, 'is_admin': bool, - 'url' : unicode, - 'bio' : unicode, # May contain markdown - 'bio_html': unicode, # May contain plaintext, or HTML - 'fp_verification_key': unicode, # forgotten password verification key - 'fp_token_expire': datetime.datetime + 'url': unicode, + 'bio': unicode, # May contain markdown + 'bio_html': unicode, # May contain plaintext, or HTML + 'fp_verification_key': unicode, # forgotten password verification key + 'fp_token_expire': datetime.datetime, } required_fields = ['username', 'created', 'pw_hash', 'email'] @@ -94,7 +96,7 @@ class User(Document): See if a user can login with this password """ return auth_lib.bcrypt_check_password( - password, self['pw_hash']) + password, self.pw_hash) class MediaEntry(Document): @@ -129,7 +131,7 @@ class MediaEntry(Document): For example, images might contain some EXIF data that's not appropriate to other formats. You might store it like: - mediaentry['media_data']['exif'] = { + mediaentry.media_data['exif'] = { 'manufacturer': 'CASIO', 'model': 'QV-4000', 'exposure_time': .659} @@ -137,7 +139,7 @@ class MediaEntry(Document): Alternately for video you might store: # play length in seconds - mediaentry['media_data']['play_length'] = 340 + mediaentry.media_data['play_length'] = 340 ... so what's appropriate here really depends on the media type. @@ -172,21 +174,22 @@ class MediaEntry(Document): critical to this piece of media but may be usefully relevant to people viewing the work. (currently unused.) - - fail_error: path to the exception raised - - fail_metadata: + - fail_error: path to the exception raised + - fail_metadata: """ __collection__ = 'media_entries' + use_dot_notation = True structure = { 'uploader': ObjectId, 'title': unicode, 'slug': unicode, 'created': datetime.datetime, - 'description': unicode, # May contain markdown/up - 'description_html': unicode, # May contain plaintext, or HTML + 'description': unicode, # May contain markdown/up + 'description_html': unicode, # May contain plaintext, or HTML 'media_type': unicode, - 'media_data': dict, # extra data relevant to this media_type - 'plugin_data': dict, # plugins can dump stuff here. + 'media_data': dict, # extra data relevant to this media_type + 'plugin_data': dict, # plugins can dump stuff here. 'tags': [dict], 'state': unicode, @@ -214,11 +217,17 @@ class MediaEntry(Document): 'created': datetime.datetime.utcnow, 'state': u'unprocessed'} - def get_comments(self): + def get_comments(self, ascending=False): + if ascending: + order = ASCENDING + else: + order = DESCENDING + return self.db.MediaComment.find({ - 'media_entry': self['_id']}).sort('created', DESCENDING) + 'media_entry': self._id}).sort('created', order) - def get_display_media(self, media_map, fetch_order=common.DISPLAY_IMAGE_FETCHING_ORDER): + def get_display_media(self, media_map, + fetch_order=common.DISPLAY_IMAGE_FETCHING_ORDER): """ Find the best media for display. @@ -240,13 +249,13 @@ class MediaEntry(Document): pass def generate_slug(self): - self['slug'] = url.slugify(self['title']) + self.slug = url.slugify(self.title) duplicate = mg_globals.database.media_entries.find_one( - {'slug': self['slug']}) + {'slug': self.slug}) if duplicate: - self['slug'] = "%s-%s" % (self['_id'], self['slug']) + self.slug = "%s-%s" % (self._id, self.slug) def url_for_self(self, urlgen): """ @@ -254,48 +263,48 @@ class MediaEntry(Document): Use a slug if we have one, else use our '_id'. """ - uploader = self.uploader() + uploader = self.get_uploader() if self.get('slug'): return urlgen( 'mediagoblin.user_pages.media_home', - user=uploader['username'], - media=self['slug']) + user=uploader.username, + media=self.slug) else: return urlgen( 'mediagoblin.user_pages.media_home', - user=uploader['username'], - media=unicode(self['_id'])) + user=uploader.username, + media=unicode(self._id)) def url_to_prev(self, urlgen): """ Provide a url to the previous entry from this user, if there is one """ - cursor = self.db.MediaEntry.find({'_id' : {"$gt": self['_id']}, - 'uploader': self['uploader'], + cursor = self.db.MediaEntry.find({'_id': {"$gt": self._id}, + 'uploader': self.uploader, 'state': 'processed'}).sort( '_id', ASCENDING).limit(1) if cursor.count(): return urlgen('mediagoblin.user_pages.media_home', - user=self.uploader()['username'], - media=unicode(cursor[0]['slug'])) + user=self.get_uploader().username, + media=unicode(cursor[0].slug)) def url_to_next(self, urlgen): """ Provide a url to the next entry from this user, if there is one """ - cursor = self.db.MediaEntry.find({'_id' : {"$lt": self['_id']}, - 'uploader': self['uploader'], + cursor = self.db.MediaEntry.find({'_id': {"$lt": self._id}, + 'uploader': self.uploader, 'state': 'processed'}).sort( '_id', DESCENDING).limit(1) if cursor.count(): return urlgen('mediagoblin.user_pages.media_home', - user=self.uploader()['username'], - media=unicode(cursor[0]['slug'])) + user=self.get_uploader().username, + media=unicode(cursor[0].slug)) - def uploader(self): - return self.db.User.find_one({'_id': self['uploader']}) + def get_uploader(self): + return self.db.User.find_one({'_id': self.uploader}) def get_fail_exception(self): """ @@ -319,6 +328,7 @@ class MediaComment(Document): """ __collection__ = 'media_comments' + use_dot_notation = True structure = { 'media_entry': ObjectId, @@ -351,4 +361,3 @@ def register_models(connection): Register all models in REGISTER_MODELS with this connection. """ connection.register(REGISTER_MODELS) - diff --git a/mediagoblin/db/open.py b/mediagoblin/db/open.py index e73b6258..e677ba12 100644 --- a/mediagoblin/db/open.py +++ b/mediagoblin/db/open.py @@ -29,7 +29,7 @@ def connect_database_from_config(app_config, use_pymongo=False): port = app_config.get('db_port') if port: port = asint(port) - + if use_pymongo: connection = pymongo.Connection( app_config.get('db_host'), port) diff --git a/mediagoblin/db/util.py b/mediagoblin/db/util.py index 84a6cbce..52e97f6d 100644 --- a/mediagoblin/db/util.py +++ b/mediagoblin/db/util.py @@ -118,11 +118,12 @@ def remove_deprecated_indexes(database, deprecated_indexes=DEPRECATED_INDEXES): ################# # The default migration registry... -# +# # Don't set this yourself! RegisterMigration will automatically fill # this with stuff via decorating methods in migrations.py -class MissingCurrentMigration(Exception): pass +class MissingCurrentMigration(Exception): + pass MIGRATIONS = {} @@ -147,7 +148,7 @@ class RegisterMigration(object): """ def __init__(self, migration_number, migration_registry=MIGRATIONS): assert migration_number > 0, "Migration number must be > 0!" - assert not migration_registry.has_key(migration_number), \ + assert migration_number not in migration_registry, \ "Duplicate migration numbers detected! That's not allowed!" self.migration_number = migration_number diff --git a/mediagoblin/decorators.py b/mediagoblin/decorators.py index 6431d67e..229664d7 100644 --- a/mediagoblin/decorators.py +++ b/mediagoblin/decorators.py @@ -40,7 +40,7 @@ def require_active_login(controller): request.user.get('status') == u'needs_email_verification': return redirect( request, 'mediagoblin.user_pages.user_home', - user=request.user['username']) + user=request.user.username) elif not request.user or request.user.get('status') != u'active': return exc.HTTPFound( location="%s?next=%s" % ( @@ -58,9 +58,9 @@ def user_may_delete_media(controller): """ def wrapper(request, *args, **kwargs): uploader = request.db.MediaEntry.find_one( - {'_id': ObjectId(request.matchdict['media'])}).uploader() - if not (request.user['is_admin'] or - request.user['_id'] == uploader['_id']): + {'_id': ObjectId(request.matchdict['media'])}).get_uploader() + if not (request.user.is_admin or + request.user._id == uploader._id): return exc.HTTPForbidden() return controller(request, *args, **kwargs) @@ -95,11 +95,10 @@ def get_user_media_entry(controller): if not user: return render_404(request) - media = request.db.MediaEntry.find_one( {'slug': request.matchdict['media'], 'state': 'processed', - 'uploader': user['_id']}) + 'uploader': user._id}) # no media via slug? Grab it via ObjectId if not media: @@ -107,7 +106,7 @@ def get_user_media_entry(controller): media = request.db.MediaEntry.find_one( {'_id': ObjectId(request.matchdict['media']), 'state': 'processed', - 'uploader': user['_id']}) + 'uploader': user._id}) except InvalidId: return render_404(request) @@ -119,6 +118,7 @@ def get_user_media_entry(controller): return _make_safe(wrapper, controller) + def get_media_entry_by_id(controller): """ Pass in a MediaEntry based off of a url component @@ -138,4 +138,3 @@ def get_media_entry_by_id(controller): return controller(request, media=media, *args, **kwargs) return _make_safe(wrapper, controller) - diff --git a/mediagoblin/edit/__init__.py b/mediagoblin/edit/__init__.py index 576bd0f5..ba347c69 100644 --- a/mediagoblin/edit/__init__.py +++ b/mediagoblin/edit/__init__.py @@ -13,5 +13,3 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. - - diff --git a/mediagoblin/edit/forms.py b/mediagoblin/edit/forms.py index 7e71722c..dd339e08 100644 --- a/mediagoblin/edit/forms.py +++ b/mediagoblin/edit/forms.py @@ -26,7 +26,9 @@ class EditForm(wtforms.Form): description = wtforms.TextAreaField('Description of this work') tags = wtforms.TextField( _('Tags'), - [tag_length_validator]) + [tag_length_validator], + description=_( + "Seperate tags by commas.")) slug = wtforms.TextField( _('Slug'), [wtforms.validators.Required(message=_("The slug can't be empty"))], @@ -43,6 +45,19 @@ class EditProfileForm(wtforms.Form): _('Website'), [wtforms.validators.Optional(), wtforms.validators.URL(message='Improperly formed URL')]) + old_password = wtforms.PasswordField( + _('Old password'), + [wtforms.validators.Optional()]) + new_password = wtforms.PasswordField( + _('New Password'), + [wtforms.validators.Optional(), + wtforms.validators.Length(min=6, max=30), + wtforms.validators.EqualTo( + 'confirm_password', + 'Passwords must match.')]) + confirm_password = wtforms.PasswordField( + 'Confirm password', + [wtforms.validators.Optional()]) class EditAttachmentsForm(wtforms.Form): diff --git a/mediagoblin/edit/lib.py b/mediagoblin/edit/lib.py index b722e9c1..a199cbf7 100644 --- a/mediagoblin/edit/lib.py +++ b/mediagoblin/edit/lib.py @@ -17,8 +17,8 @@ def may_edit_media(request, media): """Check, if the request's user may edit the media details""" - if media['uploader'] == request.user['_id']: + if media.uploader == request.user._id: return True - if request.user['is_admin']: + if request.user.is_admin: return True return False diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py index a6ddb553..4cb98c15 100644 --- a/mediagoblin/edit/views.py +++ b/mediagoblin/edit/views.py @@ -26,6 +26,7 @@ from werkzeug.utils import secure_filename from mediagoblin import messages from mediagoblin import mg_globals +from mediagoblin.auth import lib as auth_lib from mediagoblin.edit import forms from mediagoblin.edit.lib import may_edit_media from mediagoblin.decorators import require_active_login, get_user_media_entry @@ -42,9 +43,9 @@ def edit_media(request, media): return exc.HTTPForbidden() defaults = dict( - title=media['title'], - slug=media['slug'], - description=media['description'], + title=media.title, + slug=media.slug, + description=media.description, tags=media_tags_as_string(media['tags'])) form = forms.EditForm( @@ -56,29 +57,29 @@ def edit_media(request, media): # and userid. existing_user_slug_entries = request.db.MediaEntry.find( {'slug': request.POST['slug'], - 'uploader': media['uploader'], - '_id': {'$ne': media['_id']}}).count() + 'uploader': media.uploader, + '_id': {'$ne': media._id}}).count() if existing_user_slug_entries: form.slug.errors.append( _(u'An entry with that slug already exists for this user.')) else: - media['title'] = unicode(request.POST['title']) - media['description'] = unicode(request.POST.get('description')) + media.title = unicode(request.POST['title']) + media.description = unicode(request.POST.get('description')) media['tags'] = convert_to_tag_list_of_dicts( request.POST.get('tags')) - media['description_html'] = cleaned_markdown_conversion( - media['description']) + media.description_html = cleaned_markdown_conversion( + media.description) - media['slug'] = unicode(request.POST['slug']) + media.slug = unicode(request.POST['slug']) media.save() return exc.HTTPFound( location=media.url_for_self(request.urlgen)) - if request.user['is_admin'] \ - and media['uploader'] != request.user['_id'] \ + if request.user.is_admin \ + and media.uploader != request.user._id \ and request.method != 'POST': messages.add_message( request, messages.WARNING, @@ -104,7 +105,7 @@ def edit_attachments(request, media): attachment_public_filepath \ = mg_globals.public_store.get_unique_filepath( - ['media_entries', unicode(media['_id']), 'attachment', + ['media_entries', unicode(media._id), 'attachment', secure_filename(request.POST['attachment_file'].filename)]) attachment_public_file = mg_globals.public_store.get_file( @@ -120,7 +121,7 @@ def edit_attachments(request, media): name=request.POST['attachment_name'] \ or request.POST['attachment_file'].filename, filepath=attachment_public_filepath, - created=datetime.utcnow() + created=datetime.utcnow(), )) media.save() @@ -146,7 +147,7 @@ def edit_attachments(request, media): def edit_profile(request): # admins may edit any user profile given a username in the querystring edit_username = request.GET.get('username') - if request.user['is_admin'] and request.user['username'] != edit_username: + if request.user.is_admin and request.user.username != edit_username: user = request.db.User.find_one({'username': edit_username}) # No need to warn again if admin just submitted an edited profile if request.method != 'POST': @@ -161,19 +162,37 @@ def edit_profile(request): bio=user.get('bio')) if request.method == 'POST' and form.validate(): - user['url'] = unicode(request.POST['url']) - user['bio'] = unicode(request.POST['bio']) + password_matches = auth_lib.bcrypt_check_password( + request.POST['old_password'], + user['pw_hash']) - user['bio_html'] = cleaned_markdown_conversion(user['bio']) + if (request.POST['old_password'] or request.POST['new_password']) and not \ + password_matches: + form.old_password.errors.append(_('Wrong password')) - user.save() + return render_to_response( + request, + 'mediagoblin/edit/edit_profile.html', + {'user': user, + 'form': form}) - messages.add_message(request, - messages.SUCCESS, - 'Profile edited!') - return redirect(request, - 'mediagoblin.user_pages.user_home', - user=edit_username) + user.url = unicode(request.POST['url']) + user.bio = unicode(request.POST['bio']) + + if password_matches: + user['pw_hash'] = auth_lib.bcrypt_gen_password_hash( + request.POST['new_password']) + + user.bio_html = cleaned_markdown_conversion(user['bio']) + + user.save() + + messages.add_message(request, + messages.SUCCESS, + _("Profile edited!")) + return redirect(request, + 'mediagoblin.user_pages.user_home', + user=user['username']) return render_to_response( request, diff --git a/mediagoblin/gmg_commands/__init__.py b/mediagoblin/gmg_commands/__init__.py index 10c30385..04187ff2 100644 --- a/mediagoblin/gmg_commands/__init__.py +++ b/mediagoblin/gmg_commands/__init__.py @@ -29,7 +29,7 @@ SUBCOMMAND_MAP = { 'setup': 'mediagoblin.gmg_commands.migrate:migrate_parser_setup', 'func': 'mediagoblin.gmg_commands.migrate:migrate', 'help': 'Apply all unapplied bulk migrations to the database'}, - 'adduser':{ + 'adduser': { 'setup': 'mediagoblin.gmg_commands.users:adduser_parser_setup', 'func': 'mediagoblin.gmg_commands.users:adduser', 'help': 'Creates an user'}, @@ -68,7 +68,7 @@ def main_cli(): subparsers = parser.add_subparsers(help='sub-command help') for command_name, command_struct in SUBCOMMAND_MAP.iteritems(): - if command_struct.has_key('help'): + if 'help' in command_struct: subparser = subparsers.add_parser( command_name, help=command_struct['help']) else: @@ -94,4 +94,3 @@ def main_cli(): if __name__ == '__main__': main_cli() - diff --git a/mediagoblin/gmg_commands/import_export.py b/mediagoblin/gmg_commands/import_export.py index 78d30713..1308f09e 100644 --- a/mediagoblin/gmg_commands/import_export.py +++ b/mediagoblin/gmg_commands/import_export.py @@ -16,7 +16,6 @@ from mediagoblin import mg_globals from mediagoblin.db.open import setup_connection_and_db_from_config -from mediagoblin.init.config import read_mediagoblin_config from mediagoblin.storage.filestorage import BasicFileStorage from mediagoblin.init import setup_storage, setup_global_and_app_config @@ -68,7 +67,7 @@ def _import_media(db, args): for entry in db.media_entries.find(): for name, path in entry['media_files'].items(): _log.info('Importing: {0} - {1}'.format( - entry['title'], + entry.title, name)) media_file = mg_globals.public_store.get_file(path, mode='wb') @@ -88,7 +87,7 @@ def _import_database(db, args): args.mongorestore_path, '-d', db.name, os.path.join(args._cache_path['database'], db.name)]) - + p.wait() _log.info('...Database imported') @@ -209,13 +208,15 @@ def _export_media(db, args): for entry in db.media_entries.find(): for name, path in entry['media_files'].items(): - _log.info('Exporting {0} - {1}'.format( - entry['title'], + _log.info(u'Exporting {0} - {1}'.format( + entry.title, name)) - - mc_file = media_cache.get_file(path, mode='wb') - mc_file.write( - mg_globals.public_store.get_file(path, mode='rb').read()) + try: + mc_file = media_cache.get_file(path, mode='wb') + mc_file.write( + mg_globals.public_store.get_file(path, mode='rb').read()) + except e: + _log.error('Failed: {0}'.format(e)) _log.info('...Media exported') @@ -226,7 +227,8 @@ def env_export(args): ''' if args.cache_path: if os.path.exists(args.cache_path): - _log.error('The cache directory must not exist before you run this script') + _log.error('The cache directory must not exist ' + 'before you run this script') _log.error('Cache directory: {0}'.format(args.cache_path)) return False @@ -242,7 +244,7 @@ def env_export(args): globa_config, app_config = setup_global_and_app_config(args.conf_file) setup_storage() - + connection, db = setup_connection_and_db_from_config( app_config, use_pymongo=True) diff --git a/mediagoblin/gmg_commands/migrate.py b/mediagoblin/gmg_commands/migrate.py index fad9b363..bd3bcb20 100644 --- a/mediagoblin/gmg_commands/migrate.py +++ b/mediagoblin/gmg_commands/migrate.py @@ -18,7 +18,7 @@ import sys from mediagoblin.db import util as db_util from mediagoblin.db.open import setup_connection_and_db_from_config -from mediagoblin.init.config import read_mediagoblin_config +from mediagoblin.init import setup_global_and_app_config # This MUST be imported so as to set up the appropriate migrations! from mediagoblin.db import migrations @@ -41,9 +41,9 @@ def _print_finished_migration(migration_number, migration_func): def migrate(args): - config, validation_result = read_mediagoblin_config(args.conf_file) + global_config, app_config = setup_global_and_app_config(args.conf_file) connection, db = setup_connection_and_db_from_config( - config['mediagoblin'], use_pymongo=True) + app_config, use_pymongo=True) migration_manager = db_util.MigrationManager(db) # Clear old indexes @@ -53,13 +53,13 @@ def migrate(args): for collection, index_name in removed_indexes: print "Removed index '%s' in collection '%s'" % ( index_name, collection) - + # Migrate print "\n== Applying migrations... ==" migration_manager.migrate_new( pre_callback=_print_started_migration, post_callback=_print_finished_migration) - + # Add new indexes print "\n== Adding new indexes... ==" new_indexes = db_util.add_new_indexes(db) diff --git a/mediagoblin/gmg_commands/users.py b/mediagoblin/gmg_commands/users.py index 345c3e5c..4bfe30a5 100644 --- a/mediagoblin/gmg_commands/users.py +++ b/mediagoblin/gmg_commands/users.py @@ -18,27 +18,30 @@ from mediagoblin.gmg_commands import util as commands_util from mediagoblin.auth import lib as auth_lib from mediagoblin import mg_globals - def adduser_parser_setup(subparser): subparser.add_argument( - 'username', + '--username','-u', help="Username used to login") subparser.add_argument( - 'password', - help="Your supersecret word to login") + '--password','-p', + help="Your supersecret word to login, beware of storing it in bash history") subparser.add_argument( - 'email', - help="Email to recieve notifications") + '--email','-e', + help="Email to receive notifications") def adduser(args): #TODO: Lets trust admins this do not validate Emails :) commands_util.setup_app(args) + args.username = commands_util.prompt_if_not_set(args.username, "Username:") + args.password = commands_util.prompt_if_not_set(args.password, "Password:",True) + args.email = commands_util.prompt_if_not_set(args.email, "Email:") + db = mg_globals.database users_with_username = \ db.User.find({ - 'username': args.username.lower() + 'username': args.username.lower(), }).count() if users_with_username: @@ -47,11 +50,11 @@ def adduser(args): else: # Create the user entry = db.User() - entry['username'] = unicode(args.username.lower()) - entry['email'] = unicode(args.email) - entry['pw_hash'] = auth_lib.bcrypt_gen_password_hash(args.password) - entry['status'] = u'active' - entry['email_verified'] = True + entry.username = unicode(args.username.lower()) + entry.email = unicode(args.email) + entry.pw_hash = auth_lib.bcrypt_gen_password_hash(args.password) + entry.status = u'active' + entry.email_verified = True entry.save(validate=True) print "User created (and email marked as verified)" @@ -68,9 +71,9 @@ def makeadmin(args): db = mg_globals.database - user = db.User.one({'username':unicode(args.username.lower())}) + user = db.User.one({'username': unicode(args.username.lower())}) if user: - user['is_admin'] = True + user.is_admin = True user.save() print 'The user is now Admin' else: @@ -91,11 +94,10 @@ def changepw(args): db = mg_globals.database - user = db.User.one({'username':unicode(args.username.lower())}) + user = db.User.one({'username': unicode(args.username.lower())}) if user: - user['pw_hash'] = auth_lib.bcrypt_gen_password_hash(args.password) + user.pw_hash = auth_lib.bcrypt_gen_password_hash(args.password) user.save() print 'Password successfully changed' else: print 'The user doesn\'t exist' - diff --git a/mediagoblin/gmg_commands/util.py b/mediagoblin/gmg_commands/util.py index 168a0760..3e26c53f 100644 --- a/mediagoblin/gmg_commands/util.py +++ b/mediagoblin/gmg_commands/util.py @@ -16,6 +16,7 @@ from mediagoblin import app +import getpass def setup_app(args): @@ -25,3 +26,15 @@ def setup_app(args): mgoblin_app = app.MediaGoblinApp(args.conf_file) return mgoblin_app + +def prompt_if_not_set(variable, text, password=False): + """ + Checks if the variable is None and prompt for a value if it is + """ + if variable is None: + if not password: + variable=raw_input(text + u' ') + else: + variable=getpass.getpass(text + u' ') + + return variable diff --git a/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.mo Binary files differindex 4e4e8863..02dfa29a 100644 --- a/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.po index 548e971f..61abc63f 100644 --- a/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/ar/LC_MESSAGES/mediagoblin.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" "Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n" -"POT-Creation-Date: 2011-11-01 23:14-0500\n" -"PO-Revision-Date: 2011-11-02 04:13+0000\n" +"POT-Creation-Date: 2011-12-04 10:24-0600\n" +"PO-Revision-Date: 2011-12-04 16:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" @@ -21,6 +21,10 @@ msgstr "" "Language: ar\n" "Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5\n" +#: mediagoblin/processing.py:143 +msgid "Invalid file given for media type." +msgstr "" + #: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:49 msgid "Username" msgstr "اسم المستخدم" @@ -54,8 +58,8 @@ msgid "Sorry, a user with that name already exists." msgstr "عذرًا، لقد اختار مستخدم آخر هذا الاسم." #: mediagoblin/auth/views.py:77 -msgid "Sorry, that email address has already been taken." -msgstr "عÙوًا، هذا العنوان البريدي مستخدم." +msgid "Sorry, a user with that email address already exists." +msgstr "" #: mediagoblin/auth/views.py:179 msgid "" @@ -69,11 +73,19 @@ msgstr "" msgid "The verification key or user id is incorrect" msgstr "Ù…ÙØªØ§Ø التØÙ‚Ù‚ أو معر٠المستخدم خاطئ" -#: mediagoblin/auth/views.py:207 +#: mediagoblin/auth/views.py:203 +msgid "You must be logged in so we know who to send the email to!" +msgstr "" + +#: mediagoblin/auth/views.py:211 +msgid "You've already verified your email address!" +msgstr "" + +#: mediagoblin/auth/views.py:224 msgid "Resent your verification email." msgstr "أعدنا إرسال رسالة التØÙ‚Ù‚." -#: mediagoblin/auth/views.py:248 +#: mediagoblin/auth/views.py:265 msgid "" "Could not send password recovery email as your username is inactive or your " "account's email address has not been verified." @@ -89,43 +101,63 @@ msgstr "العنوان" msgid "Tags" msgstr "الوسوم" -#: mediagoblin/edit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 +msgid "Seperate tags by commas." +msgstr "" + +#: mediagoblin/edit/forms.py:33 msgid "Slug" msgstr "المسار" -#: mediagoblin/edit/forms.py:32 +#: mediagoblin/edit/forms.py:34 msgid "The slug can't be empty" msgstr "لا يمكن ترك المسار ÙØ§Ø±ØºÙ‹Ø§" -#: mediagoblin/edit/forms.py:33 +#: mediagoblin/edit/forms.py:35 msgid "" "The title part of this media's URL. You usually don't need to change this." msgstr "" "الجزء الذي يمثل عنوان المل٠ÙÙŠ المسار. لا ØØ§Ø¬Ø© إلى تغيير Ù…ØØªÙˆÙ‰ هذه الخانة " "عادةً." -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "Bio" msgstr "السيرة" -#: mediagoblin/edit/forms.py:43 +#: mediagoblin/edit/forms.py:45 msgid "Website" msgstr "الموقع الإلكتروني" -#: mediagoblin/edit/views.py:64 +#: mediagoblin/edit/forms.py:49 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:52 +msgid "New Password" +msgstr "" + +#: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." msgstr "يوجد مل٠آخر بهذا المسار لدى هذى المستخدم." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:86 msgid "You are editing another user's media. Proceed with caution." msgstr "أنت ØªØØ±Ù‘ر وسائط مستخدم آخر. كن ØØ°Ø±Ù‹Ø§ أثناء العملية." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:156 msgid "You are editing a user's profile. Proceed with caution." msgstr "أنت ØªØØ±Ù‘ر مل٠مستخدم آخر. كن ØØ°Ø±Ù‹Ø§ أثناء العملية." -#: mediagoblin/process_media/errors.py:44 -msgid "Invalid file given for media type." +#: mediagoblin/edit/views.py:171 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/edit/views.py:192 +msgid "Profile edited!" +msgstr "" + +#: mediagoblin/media_types/__init__.py:65 +msgid "Could not find any file extension in \"{filename}\"" msgstr "" #: mediagoblin/submit/forms.py:25 @@ -136,18 +168,18 @@ msgstr "الملÙ" msgid "Description of this work" msgstr "وص٠هذا العمل." -#: mediagoblin/submit/views.py:46 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "يجب أن تضع ملÙًا." -#: mediagoblin/submit/views.py:49 -msgid "The file doesn't seem to be an image!" -msgstr "لا يبدو أن هذا المل٠صورة!" - -#: mediagoblin/submit/views.py:121 +#: mediagoblin/submit/views.py:127 msgid "Woohoo! Submitted!" msgstr "يا سلام! Ù†ÙØ´Ø±ÙŽØª!" +#: mediagoblin/submit/views.py:133 +msgid "Invalid file type." +msgstr "" + #: mediagoblin/templates/mediagoblin/404.html:21 msgid "Oops!" msgstr "ويØÙŠ!" @@ -167,29 +199,29 @@ msgstr "" msgid "Image of 404 goblin stressing out" msgstr "صورة قزم مرتبك" -#: mediagoblin/templates/mediagoblin/base.html:22 -msgid "GNU MediaGoblin" -msgstr "غنو ميدياغوبلن" - -#: mediagoblin/templates/mediagoblin/base.html:47 +#: mediagoblin/templates/mediagoblin/base.html:49 msgid "MediaGoblin logo" msgstr "شعار ميدياغوبلن" -#: mediagoblin/templates/mediagoblin/base.html:52 +#: mediagoblin/templates/mediagoblin/base.html:54 msgid "Submit media" msgstr "أرسل وسائط" -#: mediagoblin/templates/mediagoblin/base.html:63 -msgid "verify your email!" -msgstr "أكّد بريدك" +#: mediagoblin/templates/mediagoblin/base.html:65 +msgid "Verify your email!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:72 +msgid "log out" +msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:73 +#: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 -#: mediagoblin/templates/mediagoblin/auth/login.html:35 +#: mediagoblin/templates/mediagoblin/auth/login.html:45 msgid "Log in" msgstr "Ù„ÙØ¬" -#: mediagoblin/templates/mediagoblin/base.html:89 +#: mediagoblin/templates/mediagoblin/base.html:91 msgid "" "Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a " "href=\"http://gnu.org/\">GNU</a> project" @@ -200,61 +232,34 @@ msgid "Explore" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:27 -msgid "Hi there, media lover! MediaGoblin is..." -msgstr "Ù…Ø±ØØ¨Ù‹Ø§ بكم يا Ù…ØØ¨ÙŠ Ø§Ù„ÙˆØ³Ø§Ø¦Ø·! ميدياغوبلن هو..." - -#: mediagoblin/templates/mediagoblin/root.html:29 -msgid "The perfect place for your media!" -msgstr "المكان الأنسب لوسائطك!" - -#: mediagoblin/templates/mediagoblin/root.html:30 -msgid "" -"A place for people to collaborate and show off original and derived " -"creations!" -msgstr "مكان يجتمع Ùيه الناس ليتعاونوا ويعرضوا إبداعاتهم الأصلية والمقتبسة!" - -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "" -"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project, " -"after all.)" -msgstr "مشروع ØØ±ØŒ ÙÙ†ØÙ† Ø£ØØ¯ مشاريع <a href=\"http://gnu.org\">غنو</a>." - -#: mediagoblin/templates/mediagoblin/root.html:32 -msgid "" -"Aiming to make the world a better place through decentralization and " -"(eventually, coming soon!) federation!" -msgstr "مشروع ÙŠØØ§ÙˆÙ„ جعل عالمنا Ø£ÙØ¶Ù„ عن طريق اللامركزية (قريبًا!)." +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:33 +#: mediagoblin/templates/mediagoblin/root.html:28 msgid "" -"Built for extensibility. (Multiple media types coming soon to the software," -" including video support!)" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." msgstr "" -"جاهز للتمدد. (Ø³ÙŠÙØ¶Ø§Ù دعم أنساق كثيرة من الوسائط قريبًا، كما سندعم الÙيديو!)." -#: mediagoblin/templates/mediagoblin/root.html:34 +#: mediagoblin/templates/mediagoblin/root.html:29 msgid "" -"Powered by people like you. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve this" -" software!</a>)" +"To add your own media, place comments, save your favourites and more, you " +"can log in with your MediaGoblin account." msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Excited to join us?" +#: mediagoblin/templates/mediagoblin/root.html:31 +msgid "Don't have one yet? It's easy!" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:39 +#: mediagoblin/templates/mediagoblin/root.html:32 #, python-format msgid "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n" +"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" " or\n" -" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" msgstr "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">أنشئ ØØ³Ø§Ø¨Ù‹Ø§ مجانيًا</a>\n" -" أو\n" -" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">ركّب ميدياغوبلن على خادومك الخاص</a>" -#: mediagoblin/templates/mediagoblin/root.html:53 +#: mediagoblin/templates/mediagoblin/root.html:44 msgid "Most recent media" msgstr "Ø£ØØ¯Ø« الوسائط" @@ -262,9 +267,18 @@ msgstr "Ø£ØØ¯Ø« الوسائط" msgid "Enter your new password" msgstr "أدخل كلمة سرك الجديدة" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29 -msgid "Enter your username or email" -msgstr "أدخل اسم المستخدم أو بريدك الإلكتروني" +#: mediagoblin/templates/mediagoblin/auth/change_fp.html:33 +#: mediagoblin/templates/mediagoblin/submit/start.html:30 +msgid "Submit" +msgstr "أرسل" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27 +msgid "Recover password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 +msgid "Send instructions" +msgstr "" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 msgid "Your password has been changed. Try to log in now." @@ -300,22 +314,18 @@ msgstr "" msgid "Logging in failed!" msgstr "ÙØ´Ù„ الولوج!" -#: mediagoblin/templates/mediagoblin/auth/login.html:43 +#: mediagoblin/templates/mediagoblin/auth/login.html:35 msgid "Don't have an account yet?" msgstr "ألا تملك ØØ³Ø§Ø¨Ù‹Ø§ بعد؟" -#: mediagoblin/templates/mediagoblin/auth/login.html:46 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 msgid "Create one here!" msgstr "أنشئ ØØ³Ø§Ø¨Ù‹Ø§ هنا!" -#: mediagoblin/templates/mediagoblin/auth/login.html:49 +#: mediagoblin/templates/mediagoblin/auth/login.html:42 msgid "Forgot your password?" msgstr "أنسيت كلمة سرك؟" -#: mediagoblin/templates/mediagoblin/auth/login.html:52 -msgid "Change it!" -msgstr "غيّرها!" - #: mediagoblin/templates/mediagoblin/auth/register.html:27 msgid "Create an account!" msgstr "أنشئ ØØ³Ø§Ø¨Ù‹Ø§!" @@ -361,27 +371,54 @@ msgstr "اØÙظ التغييرات" msgid "Editing %(username)s's profile" msgstr "ØªØØ±ÙŠØ± مل٠%(username)s الشخصي" -#: mediagoblin/templates/mediagoblin/listings/tag.html:31 -msgid "Media tagged with:" -msgstr "الوسائط الموسومة بâ€" +#: mediagoblin/templates/mediagoblin/listings/tag.html:30 +#: mediagoblin/templates/mediagoblin/listings/tag.html:35 +#, python-format +msgid "Media tagged with: %(tag_name)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:19 +msgid "Original" +msgstr "" #: mediagoblin/templates/mediagoblin/submit/start.html:26 msgid "Submit yer media" msgstr "انشر وسائطك" -#: mediagoblin/templates/mediagoblin/submit/start.html:30 -msgid "Submit" -msgstr "أرسل" +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 +#, python-format +msgid "%(username)s's media" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32 +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:37 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" msgstr "وسائط <a href=\"%(user_url)s\">%(username)s</a>" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:32 -msgid "Sorry, no such user found." -msgstr "عذرًا، تعذر العثور على مستخدم بهذا الاسم." +#: mediagoblin/templates/mediagoblin/user_pages/media.html:57 +#, python-format +msgid "By <a href=\"%(user_url)s\">%(username)s</a> on %(date)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:67 +msgid "Post a comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:85 +msgid "at" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +msgid "Post comment!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:124 +msgid "Edit" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:130 +msgid "Delete" +msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -413,35 +450,45 @@ msgstr "لا توجد وسائط ØªØØª المعالجة" msgid "These uploads failed to process:" msgstr "ÙØ´Ù„ت معالجة هذه Ø§Ù„Ù…Ù„ÙØ§Øª:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:39 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 +#, python-format +msgid "%(username)s's profile" +msgstr "مل٠%(username)s الشخصي" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 +msgid "Sorry, no such user found." +msgstr "عذرًا، تعذر العثور على مستخدم بهذا الاسم." + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 msgid "Email verification needed" msgstr "يجب التØÙ‚Ù‚ من البريد الإلكتروني" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:42 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 msgid "Almost done! Your account still needs to be activated." msgstr "أوشكنا على الانتهاء! ما زال ØØ³Ø§Ø¨Ùƒ Ø¨ØØ§Ø¬Ø© إلى Ø§Ù„ØªÙØ¹ÙŠÙ„." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 msgid "" "An email should arrive in a few moments with instructions on how to do so." msgstr "ستصلك رسالة إلكترونية خلال Ù„ØØ¸Ø§Øª بها التعليمات." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:51 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 msgid "In case it doesn't:" msgstr "إن لم تصل." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:54 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 msgid "Resend verification email" msgstr "أعد إرسال رسالة التØÙ‚Ù‚" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "" "Someone has registered an account with this username, but it still has to be" " activated." msgstr "سجّل Ø£ØØ¯Ù‡Ù… ØØ³Ø§Ø¨Ù‹Ø§ بهذا الاسم، ولكننا بانتظار Ø§Ù„ØªÙØ¹ÙŠÙ„ ØØªÙ‰ الآن." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:68 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 #, python-format msgid "" "If you are that person but you've lost your verification email, you can <a " @@ -450,40 +497,35 @@ msgstr "" "إن كنت أنت ذلك الشخص لكنك Ùقدت رسالة التØÙ‚Ù‚ØŒ يمكنك <a " "href=\"%(login_url)s\">الولوج</a> وإعادة إرسالها." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:78 -#, python-format -msgid "%(username)s's profile" -msgstr "مل٠%(username)s الشخصي" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:85 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 msgid "Here's a spot to tell others about yourself." msgstr "هذه زاوية لتخبر الآخرين Ùيها عن Ù†ÙØ³Ùƒ." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:108 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:101 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:119 msgid "Edit profile" msgstr "ØØ±Ù‘ÙØ± المل٠الشخصي" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:107 msgid "This user hasn't filled in their profile (yet)." msgstr "لم يعبئ هذا العضو بيانات ملÙÙ‡ بعد." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:122 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:133 #, python-format msgid "View all of %(username)s's media" msgstr "Ø£Ø¸Ù‡ÙØ± كل وسائط %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:135 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:146 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "هنا ستظهر وسائطك، ولكن يبدو أنك لم تض٠شيئًا بعد." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:152 msgid "Add media" msgstr "أض٠وسائط" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:147 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:158 msgid "There doesn't seem to be any media here yet..." msgstr "لا يبدو أنه توجد أي وسائط هنا ØØªÙ‰ الآن..." @@ -503,6 +545,18 @@ msgstr "Ø§Ù„Ø£ØØ¯Ø«" msgid "Older" msgstr "الأقدم" +#: mediagoblin/templates/mediagoblin/utils/pagination.html:50 +msgid "Go to page:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:20 +msgid "Tagged with" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:25 +msgid "and" +msgstr "" + #: mediagoblin/user_pages/forms.py:24 msgid "Comment" msgstr "علّÙÙ‚" @@ -511,15 +565,23 @@ msgstr "علّÙÙ‚" msgid "I am sure I want to delete this" msgstr "أنا متأكد من رغبتي Ø¨ØØ°Ù هذا العمل" -#: mediagoblin/user_pages/views.py:142 -msgid "Empty comments are not allowed." +#: mediagoblin/user_pages/views.py:155 +msgid "Oops, your comment was empty." +msgstr "" + +#: mediagoblin/user_pages/views.py:161 +msgid "Your comment has been posted!" +msgstr "" + +#: mediagoblin/user_pages/views.py:183 +msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:148 -msgid "Comment posted!" +#: mediagoblin/user_pages/views.py:190 +msgid "The media was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:181 +#: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." msgstr "أنت على وشك ØØ°Ù وسائط مستخدم آخر. كن ØØ°Ø±Ù‹Ø§ أثناء العملية." diff --git a/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.mo Binary files differindex 9b9e7e3b..34179a53 100644 --- a/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.po index e2cd8342..9609cb34 100644 --- a/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.po @@ -3,13 +3,14 @@ # This file is distributed under the same license as the PROJECT project. # # Translators: +# Al fred <devaleitzer@aim.com>, 2011. # <devaleitzer@aim.com>, 2011. msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" "Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n" -"POT-Creation-Date: 2011-11-01 23:14-0500\n" -"PO-Revision-Date: 2011-11-02 04:13+0000\n" +"POT-Creation-Date: 2011-12-04 10:24-0600\n" +"PO-Revision-Date: 2011-12-04 16:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" @@ -19,6 +20,10 @@ msgstr "" "Language: ca\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" +#: mediagoblin/processing.py:143 +msgid "Invalid file given for media type." +msgstr "Aquest tipus de fitxer no és và lid." + #: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:49 msgid "Username" msgstr "Nom d'usuari" @@ -52,8 +57,8 @@ msgid "Sorry, a user with that name already exists." msgstr "Lamentablement aquest usuari ja existeix." #: mediagoblin/auth/views.py:77 -msgid "Sorry, that email address has already been taken." -msgstr "Disculpeu, aquesta adreça electrònica ja s'està utilitzant." +msgid "Sorry, a user with that email address already exists." +msgstr "" #: mediagoblin/auth/views.py:179 msgid "" @@ -68,11 +73,19 @@ msgid "The verification key or user id is incorrect" msgstr "" "La clau de verificació o la identificació de l'usuari no són correctes." -#: mediagoblin/auth/views.py:207 +#: mediagoblin/auth/views.py:203 +msgid "You must be logged in so we know who to send the email to!" +msgstr "" + +#: mediagoblin/auth/views.py:211 +msgid "You've already verified your email address!" +msgstr "" + +#: mediagoblin/auth/views.py:224 msgid "Resent your verification email." msgstr "Torna'm a enviar el correu de verificació" -#: mediagoblin/auth/views.py:248 +#: mediagoblin/auth/views.py:265 msgid "" "Could not send password recovery email as your username is inactive or your " "account's email address has not been verified." @@ -86,42 +99,62 @@ msgstr "TÃtol" msgid "Tags" msgstr "Etiquetes" -#: mediagoblin/edit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 +msgid "Seperate tags by commas." +msgstr "" + +#: mediagoblin/edit/forms.py:33 msgid "Slug" msgstr "" -#: mediagoblin/edit/forms.py:32 +#: mediagoblin/edit/forms.py:34 msgid "The slug can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:33 +#: mediagoblin/edit/forms.py:35 msgid "" "The title part of this media's URL. You usually don't need to change this." msgstr "" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "Bio" msgstr "Biografia" -#: mediagoblin/edit/forms.py:43 +#: mediagoblin/edit/forms.py:45 msgid "Website" msgstr "Lloc web" -#: mediagoblin/edit/views.py:64 +#: mediagoblin/edit/forms.py:49 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:52 +msgid "New Password" +msgstr "" + +#: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:86 msgid "You are editing another user's media. Proceed with caution." msgstr "Esteu editant fitxers d'un altre usuari. Aneu amb compte." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:156 msgid "You are editing a user's profile. Proceed with caution." msgstr "Esteu editant el perfil d'un usuari. Aneu amb compte" -#: mediagoblin/process_media/errors.py:44 -msgid "Invalid file given for media type." -msgstr "Aquest tipus de fitxer no és và lid." +#: mediagoblin/edit/views.py:171 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/edit/views.py:192 +msgid "Profile edited!" +msgstr "" + +#: mediagoblin/media_types/__init__.py:65 +msgid "Could not find any file extension in \"{filename}\"" +msgstr "" #: mediagoblin/submit/forms.py:25 msgid "File" @@ -131,18 +164,18 @@ msgstr "Fitxer" msgid "Description of this work" msgstr "" -#: mediagoblin/submit/views.py:46 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "Heu d'escollir un fitxer." -#: mediagoblin/submit/views.py:49 -msgid "The file doesn't seem to be an image!" -msgstr "El fitxer no és una imatge" - -#: mediagoblin/submit/views.py:121 +#: mediagoblin/submit/views.py:127 msgid "Woohoo! Submitted!" msgstr "Visca! S'ha enviat!" +#: mediagoblin/submit/views.py:133 +msgid "Invalid file type." +msgstr "" + #: mediagoblin/templates/mediagoblin/404.html:21 msgid "Oops!" msgstr "Ups!" @@ -161,31 +194,31 @@ msgstr "" #: mediagoblin/templates/mediagoblin/404.html:32 msgid "Image of 404 goblin stressing out" -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:22 -msgid "GNU MediaGoblin" -msgstr "GNU MediaGoblin" +msgstr "Imatge de la pantalla 404, el goblin no sap què fer..." -#: mediagoblin/templates/mediagoblin/base.html:47 +#: mediagoblin/templates/mediagoblin/base.html:49 msgid "MediaGoblin logo" msgstr "Logo de mediagoblin" -#: mediagoblin/templates/mediagoblin/base.html:52 +#: mediagoblin/templates/mediagoblin/base.html:54 msgid "Submit media" msgstr "Envia fitxers" -#: mediagoblin/templates/mediagoblin/base.html:63 -msgid "verify your email!" -msgstr "verifiqueu el correu electrònic" +#: mediagoblin/templates/mediagoblin/base.html:65 +msgid "Verify your email!" +msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:73 +#: mediagoblin/templates/mediagoblin/base.html:72 +msgid "log out" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 -#: mediagoblin/templates/mediagoblin/auth/login.html:35 +#: mediagoblin/templates/mediagoblin/auth/login.html:45 msgid "Log in" msgstr "Entra" -#: mediagoblin/templates/mediagoblin/base.html:89 +#: mediagoblin/templates/mediagoblin/base.html:91 msgid "" "Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a " "href=\"http://gnu.org/\">GNU</a> project" @@ -196,66 +229,34 @@ msgid "Explore" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:27 -msgid "Hi there, media lover! MediaGoblin is..." -msgstr "Ei, fanà tic multimèdia! MediaGoblin és..." - -#: mediagoblin/templates/mediagoblin/root.html:29 -msgid "The perfect place for your media!" -msgstr "El lloc fitxer pels teus fitxers!" - -#: mediagoblin/templates/mediagoblin/root.html:30 -msgid "" -"A place for people to collaborate and show off original and derived " -"creations!" -msgstr "" -"Un lloc en el qual les persones poden col·laborar i mostrar les seves " -"creacions originals o obres derivades." - -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "" -"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project, " -"after all.)" +msgid "Hi there, welcome to this MediaGoblin site!" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:32 -msgid "" -"Aiming to make the world a better place through decentralization and " -"(eventually, coming soon!) federation!" -msgstr "" -"Amb l'objectiu de fer del món un lloc millor a través de la " -"descentralització i (eventualment, aviat disponible!) La federació!" - -#: mediagoblin/templates/mediagoblin/root.html:33 +#: mediagoblin/templates/mediagoblin/root.html:28 msgid "" -"Built for extensibility. (Multiple media types coming soon to the software," -" including video support!)" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." msgstr "" -"Construït per l'ampliació. (Múltiples tipus de fitxers en breu amb el " -"programari, incloent el suport de vÃdeo!)" -#: mediagoblin/templates/mediagoblin/root.html:34 +#: mediagoblin/templates/mediagoblin/root.html:29 msgid "" -"Powered by people like you. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve this" -" software!</a>)" +"To add your own media, place comments, save your favourites and more, you " +"can log in with your MediaGoblin account." msgstr "" -"Desenvolupat per persones com vostè. ( <a " -"href=\"http://mediagoblin.org/pages/join.html\"> Podeu ajudar a millorar " -"aquest programari!</a> )" -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Excited to join us?" +#: mediagoblin/templates/mediagoblin/root.html:31 +msgid "Don't have one yet? It's easy!" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:39 +#: mediagoblin/templates/mediagoblin/root.html:32 #, python-format msgid "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n" +"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" " or\n" -" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:53 +#: mediagoblin/templates/mediagoblin/root.html:44 msgid "Most recent media" msgstr "" @@ -263,8 +264,17 @@ msgstr "" msgid "Enter your new password" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29 -msgid "Enter your username or email" +#: mediagoblin/templates/mediagoblin/auth/change_fp.html:33 +#: mediagoblin/templates/mediagoblin/submit/start.html:30 +msgid "Submit" +msgstr "Envia" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27 +msgid "Recover password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 +msgid "Send instructions" msgstr "" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 @@ -294,22 +304,18 @@ msgstr "" msgid "Logging in failed!" msgstr "Inici de sessió ha fallat!" -#: mediagoblin/templates/mediagoblin/auth/login.html:43 +#: mediagoblin/templates/mediagoblin/auth/login.html:35 msgid "Don't have an account yet?" msgstr "Encara no teniu un compte?" -#: mediagoblin/templates/mediagoblin/auth/login.html:46 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 msgid "Create one here!" msgstr "Creeu-ne un aquÃ!" -#: mediagoblin/templates/mediagoblin/auth/login.html:49 +#: mediagoblin/templates/mediagoblin/auth/login.html:42 msgid "Forgot your password?" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:52 -msgid "Change it!" -msgstr "" - #: mediagoblin/templates/mediagoblin/auth/register.html:27 msgid "Create an account!" msgstr "Creeu un compte!" @@ -355,27 +361,54 @@ msgstr "Desa els canvis" msgid "Editing %(username)s's profile" msgstr "" -#: mediagoblin/templates/mediagoblin/listings/tag.html:31 -msgid "Media tagged with:" -msgstr "Etiquetat amb:" +#: mediagoblin/templates/mediagoblin/listings/tag.html:30 +#: mediagoblin/templates/mediagoblin/listings/tag.html:35 +#, python-format +msgid "Media tagged with: %(tag_name)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:19 +msgid "Original" +msgstr "" #: mediagoblin/templates/mediagoblin/submit/start.html:26 msgid "Submit yer media" msgstr "Envieu els vostres fitxers" -#: mediagoblin/templates/mediagoblin/submit/start.html:30 -msgid "Submit" -msgstr "Envia" +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 +#, python-format +msgid "%(username)s's media" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32 +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:37 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" msgstr "<a href=\"%(user_url)s\">%(username)s</a>'s media" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:32 -msgid "Sorry, no such user found." -msgstr "Lamentablement no s'ha trobat l'usuari que cercà veu." +#: mediagoblin/templates/mediagoblin/user_pages/media.html:57 +#, python-format +msgid "By <a href=\"%(user_url)s\">%(username)s</a> on %(date)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:67 +msgid "Post a comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:85 +msgid "at" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +msgid "Post comment!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:124 +msgid "Edit" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:130 +msgid "Delete" +msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -397,7 +430,7 @@ msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:28 msgid "Media in-processing" -msgstr "" +msgstr "S'està processant el fitxer" #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:46 msgid "No media in-processing" @@ -405,37 +438,49 @@ msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/processing_panel.html:50 msgid "These uploads failed to process:" +msgstr "No s'han pogut penjar els següents fitxers:" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 +#, python-format +msgid "%(username)s's profile" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:39 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 +msgid "Sorry, no such user found." +msgstr "Lamentablement no s'ha trobat l'usuari que cercà veu." + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 msgid "Email verification needed" -msgstr "" +msgstr "Cal que verifiqueu l'adreça electrònica" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:42 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 msgid "Almost done! Your account still needs to be activated." -msgstr "" +msgstr "Gairebé esteu! Tan sols falta que activeu el vostre compte" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 msgid "" "An email should arrive in a few moments with instructions on how to do so." msgstr "Us hauria d'arribar un correu amb les instruccions per a fer-ho." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:51 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 msgid "In case it doesn't:" -msgstr "" +msgstr "Per si no hi fos:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:54 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 msgid "Resend verification email" msgstr "Torna'm a enviar el correu de verificació" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "" "Someone has registered an account with this username, but it still has to be" " activated." msgstr "" +"Algú ja ha registrat un compte amb aquest nom d'usuari, però encara l'ha " +"d'activar." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:68 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 #, python-format msgid "" "If you are that person but you've lost your verification email, you can <a " @@ -444,46 +489,41 @@ msgstr "" "Si siu aqeust usuari però heu perdut el correu de verificació, podeu <a " "href=\"%(login_url)s\">entrar</a> i tornar-lo a enviar." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:78 -#, python-format -msgid "%(username)s's profile" -msgstr "" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:85 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 msgid "Here's a spot to tell others about yourself." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:108 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:101 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:119 msgid "Edit profile" msgstr "Edita el perfil" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:107 msgid "This user hasn't filled in their profile (yet)." -msgstr "" +msgstr "Aquest usuari encara no ha escrit res al seu perfil." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:122 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:133 #, python-format msgid "View all of %(username)s's media" msgstr "View all of %(username)s's media" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:135 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:146 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:152 msgid "Add media" -msgstr "" +msgstr "Tots els fitxers" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:147 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:158 msgid "There doesn't seem to be any media here yet..." msgstr "" #: mediagoblin/templates/mediagoblin/utils/feed_link.html:21 msgid "feed icon" -msgstr "" +msgstr "Icona RSS" #: mediagoblin/templates/mediagoblin/utils/feed_link.html:23 msgid "Atom feed" @@ -497,6 +537,18 @@ msgstr "" msgid "Older" msgstr "" +#: mediagoblin/templates/mediagoblin/utils/pagination.html:50 +msgid "Go to page:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:20 +msgid "Tagged with" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:25 +msgid "and" +msgstr "" + #: mediagoblin/user_pages/forms.py:24 msgid "Comment" msgstr "Comentari" @@ -505,15 +557,23 @@ msgstr "Comentari" msgid "I am sure I want to delete this" msgstr "" -#: mediagoblin/user_pages/views.py:142 -msgid "Empty comments are not allowed." +#: mediagoblin/user_pages/views.py:155 +msgid "Oops, your comment was empty." +msgstr "" + +#: mediagoblin/user_pages/views.py:161 +msgid "Your comment has been posted!" +msgstr "" + +#: mediagoblin/user_pages/views.py:183 +msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:148 -msgid "Comment posted!" +#: mediagoblin/user_pages/views.py:190 +msgid "The media was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:181 +#: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." msgstr "" diff --git a/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.mo Binary files differindex 056e3eca..a01abf9c 100644 --- a/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.po index 5c4ef0d0..e2765357 100644 --- a/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.po @@ -6,6 +6,7 @@ # <benjamin@lebsanft.org>, 2011. # <cwebber@dustycloud.org>, 2011. # Elrond <elrond+mediagoblin.org@samba-tng.org>, 2011. +# <jakob.kramer@gmx.de>, 2011. # Jan-Christoph Borchardt <JanCBorchardt@fsfe.org>, 2011. # <kyoo@kyoo.ch>, 2011. # <mediagoblin.org@samba-tng.org>, 2011. @@ -15,9 +16,9 @@ msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" "Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n" -"POT-Creation-Date: 2011-11-01 23:14-0500\n" -"PO-Revision-Date: 2011-11-02 15:18+0000\n" -"Last-Translator: piratenpanda <benjamin@lebsanft.org>\n" +"POT-Creation-Date: 2011-12-04 10:24-0600\n" +"PO-Revision-Date: 2011-12-06 21:16+0000\n" +"Last-Translator: gandaro <jakob.kramer@gmx.de>\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" @@ -26,6 +27,10 @@ msgstr "" "Language: de\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" +#: mediagoblin/processing.py:143 +msgid "Invalid file given for media type." +msgstr "Die Datei stimmt nicht mit dem gewählten Medientyp überein." + #: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:49 msgid "Username" msgstr "Benutzername" @@ -48,43 +53,52 @@ msgstr "Hier nochmal eintragen, um Tippfehler zu verhindern." #: mediagoblin/auth/forms.py:42 msgid "Email address" -msgstr "Email-Adresse" +msgstr "E-Mail-Adresse" #: mediagoblin/auth/views.py:55 msgid "Sorry, registration is disabled on this instance." -msgstr "Registrierung ist auf dieser Instanz leider deaktiviert." +msgstr "Das Registrieren ist auf dieser Instanz leider deaktiviert." #: mediagoblin/auth/views.py:73 msgid "Sorry, a user with that name already exists." msgstr "Leider gibt es bereits einen Benutzer mit diesem Namen." #: mediagoblin/auth/views.py:77 -msgid "Sorry, that email address has already been taken." -msgstr "Tut und Leid, aber diese Email-Adresse wird bereits verwendet." +msgid "Sorry, a user with that email address already exists." +msgstr "Leider gibt es bereits einen Benutzer mit dieser E-Mail-Adresse." #: mediagoblin/auth/views.py:179 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 " +"Deine E-Mail-Adresse wurde bestätigt. Du kannst dich nun anmelden, Dein " "Profil bearbeiten und Bilder hochladen!" #: mediagoblin/auth/views.py:185 msgid "The verification key or user id is incorrect" -msgstr "Der Bestätigungssschlüssel oder die Nutzernummer ist falsch." +msgstr "Der Bestätigungsschlüssel oder die Nutzernummer ist falsch." + +#: mediagoblin/auth/views.py:203 +msgid "You must be logged in so we know who to send the email to!" +msgstr "" + +#: mediagoblin/auth/views.py:211 +msgid "You've already verified your email address!" +msgstr "Deine E-Mail-Adresse wurde bereits bestätigt." -#: mediagoblin/auth/views.py:207 +#: mediagoblin/auth/views.py:224 msgid "Resent your verification email." -msgstr "Bestätigungs-Email wurde erneut versandt." +msgstr "Bestätigungs-E-Mail wurde erneut versandt." -#: mediagoblin/auth/views.py:248 +#: mediagoblin/auth/views.py:265 msgid "" "Could not send password recovery email as your username is inactive or your " "account's email address has not been verified." msgstr "" -"Konnte Email zur Wiederherstellung des Passworts nicht senden, weil dein " -"Benutzername inaktiv oder deine Email-Adresse noch nicht verifiziert ist." +"E-Mail zur Wiederherstellung des Passworts konnte nicht gesendet werden, " +"weil dein Benutzername inaktiv oder deine E-Mail-Adresse noch nicht " +"verifiziert ist." #: mediagoblin/edit/forms.py:24 mediagoblin/submit/forms.py:27 msgid "Title" @@ -94,44 +108,64 @@ msgstr "Titel" msgid "Tags" msgstr "Markierungen" -#: mediagoblin/edit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 +msgid "Seperate tags by commas." +msgstr "" + +#: mediagoblin/edit/forms.py:33 msgid "Slug" msgstr "Kurztitel" -#: mediagoblin/edit/forms.py:32 +#: mediagoblin/edit/forms.py:34 msgid "The slug can't be empty" msgstr "Bitte gib einen Kurztitel ein" -#: mediagoblin/edit/forms.py:33 +#: mediagoblin/edit/forms.py:35 msgid "" "The title part of this media's URL. You usually don't need to change this." msgstr "" "Der Titelteil der Medienadresse. Normalerweise muss hier nichts geändert " "werden." -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "Bio" msgstr "Biographie" -#: mediagoblin/edit/forms.py:43 +#: mediagoblin/edit/forms.py:45 msgid "Website" msgstr "Webseite" -#: mediagoblin/edit/views.py:64 +#: mediagoblin/edit/forms.py:49 +msgid "Old password" +msgstr "Altes Passwort" + +#: mediagoblin/edit/forms.py:52 +msgid "New Password" +msgstr "Neues Passwort" + +#: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." msgstr "Diesen Kurztitel hast du bereits vergeben." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:86 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:155 +#: mediagoblin/edit/views.py:156 msgid "You are editing a user's profile. Proceed with caution." msgstr "Du bearbeitest das Profil eines Anderen. Bitte sei vorsichtig." -#: mediagoblin/process_media/errors.py:44 -msgid "Invalid file given for media type." -msgstr "Die Datei stimmt nicht mit dem gewählten Medientyp überein." +#: mediagoblin/edit/views.py:171 +msgid "Wrong password" +msgstr "Falsches Passwort" + +#: mediagoblin/edit/views.py:192 +msgid "Profile edited!" +msgstr "Das Profil wurde aktualisiert" + +#: mediagoblin/media_types/__init__.py:65 +msgid "Could not find any file extension in \"{filename}\"" +msgstr "" #: mediagoblin/submit/forms.py:25 msgid "File" @@ -141,18 +175,18 @@ msgstr "Datei" msgid "Description of this work" msgstr "Beschreibung des Werkes" -#: mediagoblin/submit/views.py:46 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "Du musst eine Datei angeben." -#: mediagoblin/submit/views.py:49 -msgid "The file doesn't seem to be an image!" -msgstr "Diese Datei scheint kein Bild zu sein!" - -#: mediagoblin/submit/views.py:121 +#: mediagoblin/submit/views.py:127 msgid "Woohoo! Submitted!" msgstr "Yeeeaaah! Geschafft!" +#: mediagoblin/submit/views.py:133 +msgid "Invalid file type." +msgstr "Ungültiger Dateityp." + #: mediagoblin/templates/mediagoblin/404.html:21 msgid "Oops!" msgstr "Hoppla!" @@ -173,29 +207,29 @@ msgstr "" msgid "Image of 404 goblin stressing out" msgstr "Bild eines angespannten Goblins" -#: mediagoblin/templates/mediagoblin/base.html:22 -msgid "GNU MediaGoblin" -msgstr "GNU MediaGoblin" - -#: mediagoblin/templates/mediagoblin/base.html:47 +#: mediagoblin/templates/mediagoblin/base.html:49 msgid "MediaGoblin logo" msgstr "MediaGoblin-Logo" -#: mediagoblin/templates/mediagoblin/base.html:52 +#: mediagoblin/templates/mediagoblin/base.html:54 msgid "Submit media" msgstr "Medien hochladen" -#: mediagoblin/templates/mediagoblin/base.html:63 -msgid "verify your email!" -msgstr "Bitte bestätige deine Email-Adresse!" +#: mediagoblin/templates/mediagoblin/base.html:65 +msgid "Verify your email!" +msgstr "Bitte bestätige deine E-Mail-Adresse!" -#: mediagoblin/templates/mediagoblin/base.html:73 +#: mediagoblin/templates/mediagoblin/base.html:72 +msgid "log out" +msgstr "Abmelden" + +#: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 -#: mediagoblin/templates/mediagoblin/auth/login.html:35 +#: mediagoblin/templates/mediagoblin/auth/login.html:45 msgid "Log in" msgstr "Anmelden" -#: mediagoblin/templates/mediagoblin/base.html:89 +#: mediagoblin/templates/mediagoblin/base.html:91 msgid "" "Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a " "href=\"http://gnu.org/\">GNU</a> project" @@ -208,71 +242,34 @@ msgid "Explore" msgstr "Entdecke" #: mediagoblin/templates/mediagoblin/root.html:27 -msgid "Hi there, media lover! MediaGoblin is..." -msgstr "Hallo Medien-Liebhaber! MediaGoblin ist …" - -#: mediagoblin/templates/mediagoblin/root.html:29 -msgid "The perfect place for your media!" -msgstr "Der perfekte Platz für deine Medien!" - -#: mediagoblin/templates/mediagoblin/root.html:30 -msgid "" -"A place for people to collaborate and show off original and derived " -"creations!" +msgid "Hi there, welcome to this MediaGoblin site!" msgstr "" -"Ein Platz für Zusammenarbeit und um Originale und abgeleitete Werke zu " -"präsentieren!" -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "" -"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project, " -"after all.)" -msgstr "" -"Frei, wie in Freiheit. (Wir sind schließlich ein <a " -"href=\"http://gnu.org\">GNU</a>-Projekt.)" - -#: mediagoblin/templates/mediagoblin/root.html:32 +#: mediagoblin/templates/mediagoblin/root.html:28 msgid "" -"Aiming to make the world a better place through decentralization and " -"(eventually, coming soon!) federation!" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." msgstr "" -"Weltverbesserer durch Dezentralisierung und (hoffentlich bald!) unabhängige " -"Kommunikation!" -#: mediagoblin/templates/mediagoblin/root.html:33 +#: mediagoblin/templates/mediagoblin/root.html:29 msgid "" -"Built for extensibility. (Multiple media types coming soon to the software," -" including video support!)" +"To add your own media, place comments, save your favourites and more, you " +"can log in with your MediaGoblin account." msgstr "" -"Gebaut für Erweiterungen. (Bald mit Unterstützung für verschiedene " -"Medientypen inklusive Videos!)" -#: mediagoblin/templates/mediagoblin/root.html:34 -msgid "" -"Powered by people like you. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve this" -" software!</a>)" +#: mediagoblin/templates/mediagoblin/root.html:31 +msgid "Don't have one yet? It's easy!" msgstr "" -"Betrieben von Leuten wie dir. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">Du kannst uns dabei helfen, " -"die Software zu verbessern!</a>)" -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Excited to join us?" -msgstr "Neugierig dich uns anzuschließen?" - -#: mediagoblin/templates/mediagoblin/root.html:39 +#: mediagoblin/templates/mediagoblin/root.html:32 #, python-format msgid "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n" +"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" " or\n" -" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" msgstr "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Gratis ein Konto einrichten</a>\n" -" or\n" -" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">MediaGoblin auf deinem eigenen Server einrichten</a>" -#: mediagoblin/templates/mediagoblin/root.html:53 +#: mediagoblin/templates/mediagoblin/root.html:44 msgid "Most recent media" msgstr "Neuste Medien" @@ -280,9 +277,18 @@ msgstr "Neuste Medien" msgid "Enter your new password" msgstr "Neues Passwort eingeben" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29 -msgid "Enter your username or email" -msgstr "Benutzername oder Email-Adresse eingeben" +#: mediagoblin/templates/mediagoblin/auth/change_fp.html:33 +#: mediagoblin/templates/mediagoblin/submit/start.html:30 +msgid "Submit" +msgstr "Bestätigen" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27 +msgid "Recover password" +msgstr "Passwort wiederherstellen" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 +msgid "Send instructions" +msgstr "" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 msgid "Your password has been changed. Try to log in now." @@ -292,8 +298,8 @@ msgstr "Dein Passwort wurde geändert. Versuche dich jetzt einzuloggen." msgid "" "Check your inbox. We sent an email with a URL for changing your password." msgstr "" -"Prüfe deinen Posteingang. Wir haben dir eine Email mit einem Link geschickt," -" mit dem du dein Passwort ändern kannst." +"Überprüfe deinen Posteingang. Wir haben dir eine E-Mail mit einem Link " +"geschickt, mit dem du dein Passwort ändern kannst." #: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 #, python-format @@ -314,28 +320,24 @@ msgstr "" "\n" "%(verification_url)s\n" "\n" -"Wenn du denkst, dass das ein Fehler ist, ignoriere einfach diese Email und bleib ein glücklicher Goblin!" +"Wenn du denkst, dass das ein Fehler ist, ignoriere einfach diese E-Mail und bleib ein glücklicher Goblin!" #: mediagoblin/templates/mediagoblin/auth/login.html:30 msgid "Logging in failed!" msgstr "Anmeldevorgang fehlgeschlagen!" -#: mediagoblin/templates/mediagoblin/auth/login.html:43 +#: mediagoblin/templates/mediagoblin/auth/login.html:35 msgid "Don't have an account yet?" msgstr "Hast du noch kein Konto?" -#: mediagoblin/templates/mediagoblin/auth/login.html:46 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 msgid "Create one here!" msgstr "Registriere dich hier!" -#: mediagoblin/templates/mediagoblin/auth/login.html:49 +#: mediagoblin/templates/mediagoblin/auth/login.html:42 msgid "Forgot your password?" msgstr "Passwort vergessen?" -#: mediagoblin/templates/mediagoblin/auth/login.html:52 -msgid "Change it!" -msgstr "Wechsle es!" - #: mediagoblin/templates/mediagoblin/auth/register.html:27 msgid "Create an account!" msgstr "Neues Konto registrieren!" @@ -356,7 +358,7 @@ msgid "" msgstr "" "Hallo %(username)s,\n" "\n" -"um dein Konto bei GNU MediaGoblin zu aktivieren, musst du folgende Adresse in einem Webbrowser öffnen:\n" +"um dein Konto bei GNU MediaGoblin zu aktivieren, musst du folgende Adresse in deinem Webbrowser öffnen:\n" "\n" "%(verification_url)s" @@ -380,27 +382,54 @@ msgstr "Änderungen speichern" msgid "Editing %(username)s's profile" msgstr "%(username)ss Profil bearbeiten" -#: mediagoblin/templates/mediagoblin/listings/tag.html:31 -msgid "Media tagged with:" -msgstr "Medien markiert mit:" +#: mediagoblin/templates/mediagoblin/listings/tag.html:30 +#: mediagoblin/templates/mediagoblin/listings/tag.html:35 +#, python-format +msgid "Media tagged with: %(tag_name)s" +msgstr ": %(tag_name)s" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:19 +msgid "Original" +msgstr "" #: mediagoblin/templates/mediagoblin/submit/start.html:26 msgid "Submit yer media" msgstr "Medien hochladen" -#: mediagoblin/templates/mediagoblin/submit/start.html:30 -msgid "Submit" -msgstr "Bestätigen" +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 +#, python-format +msgid "%(username)s's media" +msgstr "%(username)ss Medien" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32 +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:37 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" msgstr "<a href=\"%(user_url)s\">%(username)s</a>s Medien" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:32 -msgid "Sorry, no such user found." -msgstr "Dieser Benutzer wurde leider nicht gefunden." +#: mediagoblin/templates/mediagoblin/user_pages/media.html:57 +#, python-format +msgid "By <a href=\"%(user_url)s\">%(username)s</a> on %(date)s" +msgstr "Von <a href=\"%(user_url)s\">%(username)s</a> am %(date)s" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:67 +msgid "Post a comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:85 +msgid "at" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +msgid "Post comment!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:124 +msgid "Edit" +msgstr "Bearbeiten" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:130 +msgid "Delete" +msgstr "Löschen" #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -434,31 +463,41 @@ msgstr "Keine Medien in Bearbeitung" msgid "These uploads failed to process:" msgstr "Die folgenden Uploads sind fehlgeschlagen:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:39 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 +#, python-format +msgid "%(username)s's profile" +msgstr "%(username)ss Profil" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 +msgid "Sorry, no such user found." +msgstr "Dieser Benutzer konnte leider nicht gefunden werden." + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 msgid "Email verification needed" -msgstr "Email-Bestätigung benötigt" +msgstr "E-Mail-Bestätigung benötigt" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:42 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 msgid "Almost done! Your account still needs to be activated." msgstr "Fast fertig! Dein Konto muss noch freigeschaltet werden." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 msgid "" "An email should arrive in a few moments with instructions on how to do so." msgstr "" -"Gleich solltest du eine Email bekommen, die dir sagt, was du noch machen " -"musst." +"Gleich solltest du eine E-Mail erhalten, die dir erklärt, was du noch machen" +" musst." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:51 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 msgid "In case it doesn't:" msgstr "Wenn sie nicht ankommt:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:54 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 msgid "Resend verification email" msgstr "Bestätigung erneut senden" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "" "Someone has registered an account with this username, but it still has to be" " activated." @@ -466,7 +505,7 @@ msgstr "" "Jemand hat bereits ein Konto mit diesem Benutzernamen registriert, aber es " "muss noch aktiviert werden." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:68 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 #, python-format msgid "" "If you are that person but you've lost your verification email, you can <a " @@ -476,40 +515,35 @@ msgstr "" " kannst du dich <a href=\"%(login_url)s\">anmelden</a> und sie erneut " "senden." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:78 -#, python-format -msgid "%(username)s's profile" -msgstr "%(username)ss Profil" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:85 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 msgid "Here's a spot to tell others about yourself." msgstr "Hier kannst du Anderen etwas über dich erzählen." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:108 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:101 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:119 msgid "Edit profile" msgstr "Profil bearbeiten" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:107 msgid "This user hasn't filled in their profile (yet)." msgstr "Dieser Benutzer hat (noch) keine Daten in seinem Profil." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:122 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:133 #, python-format msgid "View all of %(username)s's media" msgstr "Alle Medien von %(username)s anschauen" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:135 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:146 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "Hier erscheinen deine Medien. Sobald du etwas hochgeladen hast." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:152 msgid "Add media" msgstr "Medien hinzufügen" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:147 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:158 msgid "There doesn't seem to be any media here yet..." msgstr "Scheinbar gibt es hier noch nichts …" @@ -529,6 +563,18 @@ msgstr "Neuere" msgid "Older" msgstr "Ältere" +#: mediagoblin/templates/mediagoblin/utils/pagination.html:50 +msgid "Go to page:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:20 +msgid "Tagged with" +msgstr "Markiert mit" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:25 +msgid "and" +msgstr "und" + #: mediagoblin/user_pages/forms.py:24 msgid "Comment" msgstr "Kommentar" @@ -537,15 +583,23 @@ msgstr "Kommentar" msgid "I am sure I want to delete this" msgstr "Ja, wirklich löschen" -#: mediagoblin/user_pages/views.py:142 -msgid "Empty comments are not allowed." -msgstr "Leere Kommentare sind nicht erlaubt." +#: mediagoblin/user_pages/views.py:155 +msgid "Oops, your comment was empty." +msgstr "" -#: mediagoblin/user_pages/views.py:148 -msgid "Comment posted!" -msgstr "Kommentar hinzugefügt!" +#: mediagoblin/user_pages/views.py:161 +msgid "Your comment has been posted!" +msgstr "" + +#: mediagoblin/user_pages/views.py:183 +msgid "You deleted the media." +msgstr "" + +#: mediagoblin/user_pages/views.py:190 +msgid "The media was not deleted because you didn't check that you were sure." +msgstr "" -#: mediagoblin/user_pages/views.py:181 +#: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." msgstr "Du versuchst Medien eines anderen Nutzers zu löschen. Sei vorsichtig." diff --git a/mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po index 5e1401f6..17e6873c 100644 --- a/mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2011-11-01 23:14-0500\n" +"POT-Creation-Date: 2011-12-04 10:24-0600\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -17,6 +17,10 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 0.9.6\n" +#: mediagoblin/processing.py:143 +msgid "Invalid file given for media type." +msgstr "" + #: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:49 msgid "Username" msgstr "" @@ -50,7 +54,7 @@ msgid "Sorry, a user with that name already exists." msgstr "" #: mediagoblin/auth/views.py:77 -msgid "Sorry, that email address has already been taken." +msgid "Sorry, a user with that email address already exists." msgstr "" #: mediagoblin/auth/views.py:179 @@ -63,11 +67,19 @@ msgstr "" msgid "The verification key or user id is incorrect" msgstr "" -#: mediagoblin/auth/views.py:207 +#: mediagoblin/auth/views.py:203 +msgid "You must be logged in so we know who to send the email to!" +msgstr "" + +#: mediagoblin/auth/views.py:211 +msgid "You've already verified your email address!" +msgstr "" + +#: mediagoblin/auth/views.py:224 msgid "Resent your verification email." msgstr "" -#: mediagoblin/auth/views.py:248 +#: mediagoblin/auth/views.py:265 msgid "" "Could not send password recovery email as your username is inactive or " "your account's email address has not been verified." @@ -81,40 +93,60 @@ msgstr "" msgid "Tags" msgstr "" -#: mediagoblin/edit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 +msgid "Seperate tags by commas." +msgstr "" + +#: mediagoblin/edit/forms.py:33 msgid "Slug" msgstr "" -#: mediagoblin/edit/forms.py:32 +#: mediagoblin/edit/forms.py:34 msgid "The slug can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:33 +#: mediagoblin/edit/forms.py:35 msgid "The title part of this media's URL. You usually don't need to change this." msgstr "" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "Bio" msgstr "" -#: mediagoblin/edit/forms.py:43 +#: mediagoblin/edit/forms.py:45 msgid "Website" msgstr "" -#: mediagoblin/edit/views.py:64 +#: mediagoblin/edit/forms.py:49 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:52 +msgid "New Password" +msgstr "" + +#: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:86 msgid "You are editing another user's media. Proceed with caution." msgstr "" -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:156 msgid "You are editing a user's profile. Proceed with caution." msgstr "" -#: mediagoblin/process_media/errors.py:44 -msgid "Invalid file given for media type." +#: mediagoblin/edit/views.py:171 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/edit/views.py:192 +msgid "Profile edited!" +msgstr "" + +#: mediagoblin/media_types/__init__.py:65 +msgid "Could not find any file extension in \"{filename}\"" msgstr "" #: mediagoblin/submit/forms.py:25 @@ -125,16 +157,16 @@ msgstr "" msgid "Description of this work" msgstr "" -#: mediagoblin/submit/views.py:46 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "" -#: mediagoblin/submit/views.py:49 -msgid "The file doesn't seem to be an image!" +#: mediagoblin/submit/views.py:127 +msgid "Woohoo! Submitted!" msgstr "" -#: mediagoblin/submit/views.py:121 -msgid "Woohoo! Submitted!" +#: mediagoblin/submit/views.py:133 +msgid "Invalid file type." msgstr "" #: mediagoblin/templates/mediagoblin/404.html:21 @@ -155,29 +187,29 @@ msgstr "" msgid "Image of 404 goblin stressing out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:22 -msgid "GNU MediaGoblin" -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:47 +#: mediagoblin/templates/mediagoblin/base.html:49 msgid "MediaGoblin logo" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:52 +#: mediagoblin/templates/mediagoblin/base.html:54 msgid "Submit media" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:63 -msgid "verify your email!" +#: mediagoblin/templates/mediagoblin/base.html:65 +msgid "Verify your email!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:72 +msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:73 +#: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 -#: mediagoblin/templates/mediagoblin/auth/login.html:35 +#: mediagoblin/templates/mediagoblin/auth/login.html:45 msgid "Log in" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:89 +#: mediagoblin/templates/mediagoblin/base.html:91 msgid "" "Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a " "href=\"http://gnu.org/\">GNU</a> project" @@ -188,60 +220,37 @@ msgid "Explore" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:27 -msgid "Hi there, media lover! MediaGoblin is..." +msgid "Hi there, welcome to this MediaGoblin site!" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:29 -msgid "The perfect place for your media!" +#: mediagoblin/templates/mediagoblin/root.html:28 +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, " +"an extraordinarily great piece of media hosting software." msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:30 +#: mediagoblin/templates/mediagoblin/root.html:29 msgid "" -"A place for people to collaborate and show off original and derived " -"creations!" +"To add your own media, place comments, save your favourites and more, you" +" can log in with your MediaGoblin account." msgstr "" #: mediagoblin/templates/mediagoblin/root.html:31 -msgid "" -"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project," -" after all.)" +msgid "Don't have one yet? It's easy!" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:32 -msgid "" -"Aiming to make the world a better place through decentralization and " -"(eventually, coming soon!) federation!" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "" -"Built for extensibility. (Multiple media types coming soon to the " -"software, including video support!)" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:34 -msgid "" -"Powered by people like you. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve " -"this software!</a>)" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Excited to join us?" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:39 #, python-format msgid "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a " -"free account</a>\n" +"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an " +"account at this site</a>\n" " or\n" -" <a class=\"header_submit\" " +" <a class=\"button_action\" " "href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on " "your own server</a>" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:53 +#: mediagoblin/templates/mediagoblin/root.html:44 msgid "Most recent media" msgstr "" @@ -249,8 +258,17 @@ msgstr "" msgid "Enter your new password" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29 -msgid "Enter your username or email" +#: mediagoblin/templates/mediagoblin/auth/change_fp.html:33 +#: mediagoblin/templates/mediagoblin/submit/start.html:30 +msgid "Submit" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27 +msgid "Recover password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 +msgid "Send instructions" msgstr "" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 @@ -279,22 +297,18 @@ msgstr "" msgid "Logging in failed!" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:43 +#: mediagoblin/templates/mediagoblin/auth/login.html:35 msgid "Don't have an account yet?" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:46 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 msgid "Create one here!" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:49 +#: mediagoblin/templates/mediagoblin/auth/login.html:42 msgid "Forgot your password?" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:52 -msgid "Change it!" -msgstr "" - #: mediagoblin/templates/mediagoblin/auth/register.html:27 msgid "Create an account!" msgstr "" @@ -334,26 +348,53 @@ msgstr "" msgid "Editing %(username)s's profile" msgstr "" -#: mediagoblin/templates/mediagoblin/listings/tag.html:31 -msgid "Media tagged with:" +#: mediagoblin/templates/mediagoblin/listings/tag.html:30 +#: mediagoblin/templates/mediagoblin/listings/tag.html:35 +#, python-format +msgid "Media tagged with: %(tag_name)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:19 +msgid "Original" msgstr "" #: mediagoblin/templates/mediagoblin/submit/start.html:26 msgid "Submit yer media" msgstr "" -#: mediagoblin/templates/mediagoblin/submit/start.html:30 -msgid "Submit" +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 +#, python-format +msgid "%(username)s's media" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32 +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:37 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:32 -msgid "Sorry, no such user found." +#: mediagoblin/templates/mediagoblin/user_pages/media.html:57 +#, python-format +msgid "By <a href=\"%(user_url)s\">%(username)s</a> on %(date)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:67 +msgid "Post a comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:85 +msgid "at" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +msgid "Post comment!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:124 +msgid "Edit" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:130 +msgid "Delete" msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 @@ -385,74 +426,79 @@ msgstr "" msgid "These uploads failed to process:" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:39 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 +#, python-format +msgid "%(username)s's profile" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 +msgid "Sorry, no such user found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 msgid "Email verification needed" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:42 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 msgid "Almost done! Your account still needs to be activated." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 msgid "An email should arrive in a few moments with instructions on how to do so." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:51 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 msgid "In case it doesn't:" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:54 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 msgid "Resend verification email" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "" "Someone has registered an account with this username, but it still has to" " be activated." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:68 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 #, python-format msgid "" "If you are that person but you've lost your verification email, you can " "<a href=\"%(login_url)s\">log in</a> and resend it." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:78 -#, python-format -msgid "%(username)s's profile" -msgstr "" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:85 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 msgid "Here's a spot to tell others about yourself." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:108 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:101 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:119 msgid "Edit profile" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:107 msgid "This user hasn't filled in their profile (yet)." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:122 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:133 #, python-format msgid "View all of %(username)s's media" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:135 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:146 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:152 msgid "Add media" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:147 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:158 msgid "There doesn't seem to be any media here yet..." msgstr "" @@ -472,6 +518,18 @@ msgstr "" msgid "Older" msgstr "" +#: mediagoblin/templates/mediagoblin/utils/pagination.html:50 +msgid "Go to page:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:20 +msgid "Tagged with" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:25 +msgid "and" +msgstr "" + #: mediagoblin/user_pages/forms.py:24 msgid "Comment" msgstr "" @@ -480,15 +538,23 @@ msgstr "" msgid "I am sure I want to delete this" msgstr "" -#: mediagoblin/user_pages/views.py:142 -msgid "Empty comments are not allowed." +#: mediagoblin/user_pages/views.py:155 +msgid "Oops, your comment was empty." +msgstr "" + +#: mediagoblin/user_pages/views.py:161 +msgid "Your comment has been posted!" +msgstr "" + +#: mediagoblin/user_pages/views.py:183 +msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:148 -msgid "Comment posted!" +#: mediagoblin/user_pages/views.py:190 +msgid "The media was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:181 +#: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." msgstr "" diff --git a/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.mo Binary files differindex c537c65e..3e0a84bf 100644 --- a/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.po index f6bb1cce..c3c29b89 100644 --- a/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/eo/LC_MESSAGES/mediagoblin.po @@ -10,9 +10,9 @@ msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" "Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n" -"POT-Creation-Date: 2011-11-01 23:14-0500\n" -"PO-Revision-Date: 2011-11-02 04:13+0000\n" -"Last-Translator: cwebber <cwebber@dustycloud.org>\n" +"POT-Creation-Date: 2011-12-04 10:24-0600\n" +"PO-Revision-Date: 2011-12-06 20:04+0000\n" +"Last-Translator: aleksejrs <deletesoftware@yandex.ru>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -21,6 +21,10 @@ msgstr "" "Language: eo\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" +#: mediagoblin/processing.py:143 +msgid "Invalid file given for media type." +msgstr "La provizita dosiero ne konformas al la informtipo." + #: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:49 msgid "Username" msgstr "Uzantnomo" @@ -54,8 +58,8 @@ msgid "Sorry, a user with that name already exists." msgstr "BedaÅrinde, uzanto kun tiu nomo jam ekzistas." #: mediagoblin/auth/views.py:77 -msgid "Sorry, that email address has already been taken." -msgstr "Tiu retpoÅtadreso jam estas uzata." +msgid "Sorry, a user with that email address already exists." +msgstr "Ni bedaÅras, sed konto kun tiu retpoÅtadreso jam ekzistas." #: mediagoblin/auth/views.py:179 msgid "" @@ -69,11 +73,19 @@ msgstr "" msgid "The verification key or user id is incorrect" msgstr "La kontrol-kodo aÅ la uzantonomo ne estas korekta" -#: mediagoblin/auth/views.py:207 +#: mediagoblin/auth/views.py:203 +msgid "You must be logged in so we know who to send the email to!" +msgstr "Vi devas esti ensalutita, por ke ni sciu, al kiu sendi la retleteron!" + +#: mediagoblin/auth/views.py:211 +msgid "You've already verified your email address!" +msgstr "Vi jam konfirmis vian retpoÅtadreson!" + +#: mediagoblin/auth/views.py:224 msgid "Resent your verification email." msgstr "Resendi vian kontrol-mesaÄon." -#: mediagoblin/auth/views.py:248 +#: mediagoblin/auth/views.py:265 msgid "" "Could not send password recovery email as your username is inactive or your " "account's email address has not been verified." @@ -89,44 +101,64 @@ msgstr "Titolo" msgid "Tags" msgstr "Etikedoj" -#: mediagoblin/edit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 +msgid "Seperate tags by commas." +msgstr "Dividu la etikedojn per komoj." + +#: mediagoblin/edit/forms.py:33 msgid "Slug" msgstr "La distingiga adresparto" -#: mediagoblin/edit/forms.py:32 +#: mediagoblin/edit/forms.py:34 msgid "The slug can't be empty" msgstr "La distingiga adresparto ne povas esti malplena" -#: mediagoblin/edit/forms.py:33 +#: mediagoblin/edit/forms.py:35 msgid "" "The title part of this media's URL. You usually don't need to change this." msgstr "" "La parto de la dosieradreso, bazita sur la dosiertitolo. Ordinare ne necesas" " Äin ÅanÄi." -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "Bio" msgstr "Bio" -#: mediagoblin/edit/forms.py:43 +#: mediagoblin/edit/forms.py:45 msgid "Website" msgstr "Retejo" -#: mediagoblin/edit/views.py:64 +#: mediagoblin/edit/forms.py:49 +msgid "Old password" +msgstr "La malnova pasvorto" + +#: mediagoblin/edit/forms.py:52 +msgid "New Password" +msgstr "La nova pasvorto" + +#: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." msgstr "Ĉi tiu uzanto jam havas dosieron kun tiu distingiga adresparto." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:86 msgid "You are editing another user's media. Proceed with caution." msgstr "Vi priredaktas dosieron de alia uzanto. Agu singardeme." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:156 msgid "You are editing a user's profile. Proceed with caution." msgstr "Vi redaktas profilon de alia uzanto. Agu singardeme." -#: mediagoblin/process_media/errors.py:44 -msgid "Invalid file given for media type." -msgstr "La provizita dosiero ne konformas al la informtipo." +#: mediagoblin/edit/views.py:171 +msgid "Wrong password" +msgstr "MalÄusta pasvorto" + +#: mediagoblin/edit/views.py:192 +msgid "Profile edited!" +msgstr "La profilÅanÄo faritas!" + +#: mediagoblin/media_types/__init__.py:65 +msgid "Could not find any file extension in \"{filename}\"" +msgstr "Åœajnas, ke en «{filename}» mankas dosiernoma finaĵo" #: mediagoblin/submit/forms.py:25 msgid "File" @@ -136,18 +168,18 @@ msgstr "Dosiero" msgid "Description of this work" msgstr "Priskribo de ĉi tiu verko" -#: mediagoblin/submit/views.py:46 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "Vi devas provizi dosieron." -#: mediagoblin/submit/views.py:49 -msgid "The file doesn't seem to be an image!" -msgstr "La dosiero Åajnas ne esti bildo!" - -#: mediagoblin/submit/views.py:121 +#: mediagoblin/submit/views.py:127 msgid "Woohoo! Submitted!" msgstr "Hura! AlÅutitas!" +#: mediagoblin/submit/views.py:133 +msgid "Invalid file type." +msgstr "NetaÅga dosiertipo." + #: mediagoblin/templates/mediagoblin/404.html:21 msgid "Oops!" msgstr "Oj!" @@ -168,29 +200,29 @@ msgstr "" msgid "Image of 404 goblin stressing out" msgstr "Bildo de 404-koboldo penÅvitanta." -#: mediagoblin/templates/mediagoblin/base.html:22 -msgid "GNU MediaGoblin" -msgstr "GNU MediaGoblin" - -#: mediagoblin/templates/mediagoblin/base.html:47 +#: mediagoblin/templates/mediagoblin/base.html:49 msgid "MediaGoblin logo" msgstr "Emblemo de MediaGoblin" -#: mediagoblin/templates/mediagoblin/base.html:52 +#: mediagoblin/templates/mediagoblin/base.html:54 msgid "Submit media" msgstr "AlÅuti aÅd-vid-dosieron" -#: mediagoblin/templates/mediagoblin/base.html:63 -msgid "verify your email!" -msgstr "konfirmu vian retpoÅtadreson! " +#: mediagoblin/templates/mediagoblin/base.html:65 +msgid "Verify your email!" +msgstr "Konfirmu viecon de la retpoÅtadreso!" + +#: mediagoblin/templates/mediagoblin/base.html:72 +msgid "log out" +msgstr "elsaluti" -#: mediagoblin/templates/mediagoblin/base.html:73 +#: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 -#: mediagoblin/templates/mediagoblin/auth/login.html:35 +#: mediagoblin/templates/mediagoblin/auth/login.html:45 msgid "Log in" msgstr "Ensaluti" -#: mediagoblin/templates/mediagoblin/base.html:89 +#: mediagoblin/templates/mediagoblin/base.html:91 msgid "" "Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a " "href=\"http://gnu.org/\">GNU</a> project" @@ -200,82 +232,64 @@ msgstr "" #: mediagoblin/templates/mediagoblin/root.html:24 msgid "Explore" -msgstr "" +msgstr "ĈirkaÅrigardi" #: mediagoblin/templates/mediagoblin/root.html:27 -msgid "Hi there, media lover! MediaGoblin is..." -msgstr "Saluton, artemulo! MediaGoblin estas…" - -#: mediagoblin/templates/mediagoblin/root.html:29 -msgid "The perfect place for your media!" -msgstr "La perfekta loko por viaj aÅd-vid-dosieroj!" - -#: mediagoblin/templates/mediagoblin/root.html:30 -msgid "" -"A place for people to collaborate and show off original and derived " -"creations!" -msgstr "" -"Loko, kie homoj povas kunlabori, kaj elmeti originalajn kreaĵojn kaj " -"derivaĵojn!" - -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "" -"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project, " -"after all.)" -msgstr "" -"Libera verko. (Ni ja estas projekto de <a href=\"http://gnu.org\">GNU</a>.)" - -#: mediagoblin/templates/mediagoblin/root.html:32 -msgid "" -"Aiming to make the world a better place through decentralization and " -"(eventually, coming soon!) federation!" -msgstr "" -"Celanta plibonigi la mondon per sencentreco kaj (iam, baldaÅ!) federateco!" +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "Saluton, kaj bonvenon al ĉi tiu MediaGoblina retpaÄaro!" -#: mediagoblin/templates/mediagoblin/root.html:33 +#: mediagoblin/templates/mediagoblin/root.html:28 msgid "" -"Built for extensibility. (Multiple media types coming soon to the software," -" including video support!)" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." msgstr "" -"Kreita por etendado. (BaldaÅ en la programo aperos subteno de pluraj " -"informspecoj, inkluzive de filmoj!)" +"Ĉi tiu retpaÄaro funkcias per <a " +"href=\"http://mediagoblin.org\">MediaGoblin</a>, eksterordinare bonega " +"programaro por gastigado de aÅdâ€vidâ€dosieroj." -#: mediagoblin/templates/mediagoblin/root.html:34 +#: mediagoblin/templates/mediagoblin/root.html:29 msgid "" -"Powered by people like you. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve this" -" software!</a>)" +"To add your own media, place comments, save your favourites and more, you " +"can log in with your MediaGoblin account." msgstr "" -"Vivanta per homoj kiel vi. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">Vi povas helpi al ni " -"plibonigi la programon!</a>)" +"Por aldoni viajn proprajn dosierojn, fari al vi liston de la plej plaĉaj, " +"ks, vi povas ensaluti je via MediaGoblina konto." -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Excited to join us?" -msgstr "Ĉu vi deziregas aliÄi nin?" +#: mediagoblin/templates/mediagoblin/root.html:31 +msgid "Don't have one yet? It's easy!" +msgstr "Ĉu vi ankoraÅ ne havas tian? Ne malÄoju!" -#: mediagoblin/templates/mediagoblin/root.html:39 +#: mediagoblin/templates/mediagoblin/root.html:32 #, python-format msgid "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n" +"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" " or\n" -" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" msgstr "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Kreu senpagan" -" konton</a>⎠aÅ⎠<a class=\"header_submit\" " -"href=\"http://wiki.mediagoblin.org/HackingHowto\">Kreu senpagan konton</a>" +"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Kreu konton en ĉi tiu retejo</a>\n" +" aÅ\n" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Ekfunkciigu MediaGoblin’on en via propra servilo</a>" -#: mediagoblin/templates/mediagoblin/root.html:53 +#: mediagoblin/templates/mediagoblin/root.html:44 msgid "Most recent media" -msgstr "Plej nove aldonitaj dosieroj" +msgstr "Laste aldonitaj dosieroj" #: mediagoblin/templates/mediagoblin/auth/change_fp.html:29 msgid "Enter your new password" msgstr "Enigu vian novan pasvorton" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29 -msgid "Enter your username or email" -msgstr "Enigu vian salutnomon aÅ retpoÅtadreson" +#: mediagoblin/templates/mediagoblin/auth/change_fp.html:33 +#: mediagoblin/templates/mediagoblin/submit/start.html:30 +msgid "Submit" +msgstr "AlÅuti" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27 +msgid "Recover password" +msgstr "Ekhavo de nova pasvorto" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 +msgid "Send instructions" +msgstr "Sendi instrukcion" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 msgid "Your password has been changed. Try to log in now." @@ -313,22 +327,18 @@ msgstr "" msgid "Logging in failed!" msgstr "Ensaluto malsukcesis!" -#: mediagoblin/templates/mediagoblin/auth/login.html:43 +#: mediagoblin/templates/mediagoblin/auth/login.html:35 msgid "Don't have an account yet?" msgstr "Ĉu ankoraÅ sen konto?" -#: mediagoblin/templates/mediagoblin/auth/login.html:46 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 msgid "Create one here!" msgstr "Kreu Äin ĉi tie!" -#: mediagoblin/templates/mediagoblin/auth/login.html:49 +#: mediagoblin/templates/mediagoblin/auth/login.html:42 msgid "Forgot your password?" msgstr "Ĉu vi forgesis vian pasvorton?" -#: mediagoblin/templates/mediagoblin/auth/login.html:52 -msgid "Change it!" -msgstr "ÅœanÄu Äin!" - #: mediagoblin/templates/mediagoblin/auth/register.html:27 msgid "Create an account!" msgstr "Kreu konton!" @@ -373,27 +383,54 @@ msgstr "Konservi ÅanÄojn" msgid "Editing %(username)s's profile" msgstr "Redaktado de l’profilo de %(username)s'" -#: mediagoblin/templates/mediagoblin/listings/tag.html:31 -msgid "Media tagged with:" -msgstr "Dosieroj markitaj per:" +#: mediagoblin/templates/mediagoblin/listings/tag.html:30 +#: mediagoblin/templates/mediagoblin/listings/tag.html:35 +#, python-format +msgid "Media tagged with: %(tag_name)s" +msgstr "Dosieroj kun etikedo: %(tag_name)s" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:19 +msgid "Original" +msgstr "Originalo" #: mediagoblin/templates/mediagoblin/submit/start.html:26 msgid "Submit yer media" msgstr "AlÅutu vian aÅd-vid-dosieron" -#: mediagoblin/templates/mediagoblin/submit/start.html:30 -msgid "Submit" -msgstr "AlÅuti" +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 +#, python-format +msgid "%(username)s's media" +msgstr "Dosieroj de %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32 +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:37 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" msgstr "Dosieroj de <a href=\"%(user_url)s\">%(username)s</a>" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:32 -msgid "Sorry, no such user found." -msgstr "Uzanto ne trovita." +#: mediagoblin/templates/mediagoblin/user_pages/media.html:57 +#, python-format +msgid "By <a href=\"%(user_url)s\">%(username)s</a> on %(date)s" +msgstr "AfiÅita de <a href=\"%(user_url)s\">%(username)s</a> je %(date)s" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:67 +msgid "Post a comment" +msgstr "AfiÅi komenton" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:85 +msgid "at" +msgstr "je" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +msgid "Post comment!" +msgstr "AfiÅi la komenton!" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:124 +msgid "Edit" +msgstr "ÅœanÄi" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:130 +msgid "Delete" +msgstr "Forigi" #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -427,30 +464,40 @@ msgstr "Neniu dosieroj preparatas" msgid "These uploads failed to process:" msgstr "Preparado de ĉi tiuj alÅutaĵoj malsukcesis:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:39 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 +#, python-format +msgid "%(username)s's profile" +msgstr "Profilo de %(username)s" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 +msgid "Sorry, no such user found." +msgstr "Uzanto ne trovita." + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 msgid "Email verification needed" msgstr "Necesas konfirmo de retpoÅtadreso" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:42 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 msgid "Almost done! Your account still needs to be activated." msgstr "PreskaÅ finite! Restas nur validigi vian konton." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 msgid "" "An email should arrive in a few moments with instructions on how to do so." msgstr "" "Post kelkaj momentoj devas veni retletero kun instrukcio pri kiel tion fari." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:51 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 msgid "In case it doesn't:" msgstr "Se tio ne okazas:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:54 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 msgid "Resend verification email" msgstr "Resendi kontrolmesaÄon" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "" "Someone has registered an account with this username, but it still has to be" " activated." @@ -458,7 +505,7 @@ msgstr "" "Iu registris konton kun tiu ĉi uzantonomo, sed Äi devas ankoraÅ esti " "aktivigita." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:68 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 #, python-format msgid "" "If you are that person but you've lost your verification email, you can <a " @@ -467,41 +514,36 @@ msgstr "" "Se vi estas tiu sed vi perdis vian kontrolmesaÄon, vi povas <a " "href=\"%(login_url)s\">ensaluti</a> kaj resendi Äin." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:78 -#, python-format -msgid "%(username)s's profile" -msgstr "Profilo de %(username)s" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:85 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 msgid "Here's a spot to tell others about yourself." msgstr "Jen estas spaceto por rakonti pri vi al aliaj." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:108 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:101 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:119 msgid "Edit profile" msgstr "Redakti profilon" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:107 msgid "This user hasn't filled in their profile (yet)." msgstr "Ĉi tiu uzanto ne jam aldonis informojn pri si." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:122 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:133 #, python-format msgid "View all of %(username)s's media" msgstr "Rigardi ĉiujn dosierojn de %(username)s'" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:135 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:146 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "" "Äœuste ĉi tie aperos viaj dosieroj, sed vi Åajne ankoraÅ nenion alÅutis." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:152 msgid "Add media" msgstr "Aldoni dosieron" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:147 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:158 msgid "There doesn't seem to be any media here yet..." msgstr "Ĉi tie Åajne estas ankoraÅ neniuj dosieroj…" @@ -521,6 +563,18 @@ msgstr "Plinovaj" msgid "Older" msgstr "Malplinovaj" +#: mediagoblin/templates/mediagoblin/utils/pagination.html:50 +msgid "Go to page:" +msgstr "Iri al paÄo:" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:20 +msgid "Tagged with" +msgstr "Markita per: " + +#: mediagoblin/templates/mediagoblin/utils/tags.html:25 +msgid "and" +msgstr "kaj" + #: mediagoblin/user_pages/forms.py:24 msgid "Comment" msgstr "Komento" @@ -529,15 +583,25 @@ msgstr "Komento" msgid "I am sure I want to delete this" msgstr "Mi estas certa, ke mi volas forigi ĉi tion" -#: mediagoblin/user_pages/views.py:142 -msgid "Empty comments are not allowed." -msgstr "" +#: mediagoblin/user_pages/views.py:155 +msgid "Oops, your comment was empty." +msgstr "Oj, via komento estis malplena." + +#: mediagoblin/user_pages/views.py:161 +msgid "Your comment has been posted!" +msgstr "Via komento estis afiÅita!" + +#: mediagoblin/user_pages/views.py:183 +msgid "You deleted the media." +msgstr "Vi forigis la dosieron." -#: mediagoblin/user_pages/views.py:148 -msgid "Comment posted!" +#: mediagoblin/user_pages/views.py:190 +msgid "The media was not deleted because you didn't check that you were sure." msgstr "" +"La dosiero ne estis forigita, ĉar vi ne konfirmis vian certecon per la " +"markilo." -#: mediagoblin/user_pages/views.py:181 +#: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." msgstr "Vi estas forigonta dosieron de alia uzanto. Estu singardema." diff --git a/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.mo Binary files differindex 2d2b9243..0f7f4026 100644 --- a/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.po index a3c9939b..406e1923 100644 --- a/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/es/LC_MESSAGES/mediagoblin.po @@ -10,13 +10,14 @@ # <juangsub@gmail.com>, 2011. # <juanma@kde.org.ar>, 2011. # Mario Rodriguez <msrodriguez00@gmail.com>, 2011. +# <mu@member.fsf.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-11-01 23:14-0500\n" -"PO-Revision-Date: 2011-11-02 04:13+0000\n" -"Last-Translator: cwebber <cwebber@dustycloud.org>\n" +"POT-Creation-Date: 2011-12-04 10:24-0600\n" +"PO-Revision-Date: 2011-12-05 23:20+0000\n" +"Last-Translator: manolinux <mu@member.fsf.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" @@ -25,6 +26,10 @@ msgstr "" "Language: es\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" +#: mediagoblin/processing.py:143 +msgid "Invalid file given for media type." +msgstr "Archivo inválido para el formato seleccionado." + #: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:49 msgid "Username" msgstr "Nombre de usuario" @@ -59,8 +64,8 @@ msgid "Sorry, a user with that name already exists." msgstr "Lo sentimos, ya existe un usuario con ese nombre." #: mediagoblin/auth/views.py:77 -msgid "Sorry, that email address has already been taken." -msgstr "Lo sentimos, esa dirección de correo electrónico ya ha sido tomada." +msgid "Sorry, a user with that email address already exists." +msgstr "Lo sentimos, ya existe un usuario con esa dirección de email." #: mediagoblin/auth/views.py:179 msgid "" @@ -75,11 +80,21 @@ msgid "The verification key or user id is incorrect" msgstr "" "La clave de verificación o la identificación de usuario son incorrectas" -#: mediagoblin/auth/views.py:207 +#: mediagoblin/auth/views.py:203 +msgid "You must be logged in so we know who to send the email to!" +msgstr "" +"¡Debes iniciar sesión para que podamos saber a quién le enviamos el correo " +"electrónico!" + +#: mediagoblin/auth/views.py:211 +msgid "You've already verified your email address!" +msgstr "¡Ya has verificado tu dirección de correo!" + +#: mediagoblin/auth/views.py:224 msgid "Resent your verification email." msgstr "Se reenvió tu correo electrónico de verificación." -#: mediagoblin/auth/views.py:248 +#: mediagoblin/auth/views.py:265 msgid "" "Could not send password recovery email as your username is inactive or your " "account's email address has not been verified." @@ -96,44 +111,64 @@ msgstr "TÃtulo" msgid "Tags" msgstr "Etiquetas" -#: mediagoblin/edit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 +msgid "Seperate tags by commas." +msgstr "Separa las etiquetas con comas." + +#: mediagoblin/edit/forms.py:33 msgid "Slug" msgstr "Ficha" -#: mediagoblin/edit/forms.py:32 +#: mediagoblin/edit/forms.py:34 msgid "The slug can't be empty" msgstr "La ficha no puede estar vacÃa" -#: mediagoblin/edit/forms.py:33 +#: mediagoblin/edit/forms.py:35 msgid "" "The title part of this media's URL. You usually don't need to change this." msgstr "" "La parte del tÃtulo de la URL de este contenido. Normalmente no necesitas " "cambiar esto." -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "Bio" msgstr "Bio" -#: mediagoblin/edit/forms.py:43 +#: mediagoblin/edit/forms.py:45 msgid "Website" msgstr "Sitio web" -#: mediagoblin/edit/views.py:64 +#: mediagoblin/edit/forms.py:49 +msgid "Old password" +msgstr "Vieja contraseña" + +#: mediagoblin/edit/forms.py:52 +msgid "New Password" +msgstr "Nueva contraseña" + +#: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." msgstr "Una entrada con esa ficha ya existe para este usuario." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:86 msgid "You are editing another user's media. Proceed with caution." msgstr "Estás editando el contenido de otro usuario. Proceder con precaución." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:156 msgid "You are editing a user's profile. Proceed with caution." msgstr "Estás editando un perfil de usuario. Proceder con precaución." -#: mediagoblin/process_media/errors.py:44 -msgid "Invalid file given for media type." -msgstr "Archivo inválido para el formato seleccionado." +#: mediagoblin/edit/views.py:171 +msgid "Wrong password" +msgstr "Contraseña incorrecta" + +#: mediagoblin/edit/views.py:192 +msgid "Profile edited!" +msgstr "¡Perfil editado!" + +#: mediagoblin/media_types/__init__.py:65 +msgid "Could not find any file extension in \"{filename}\"" +msgstr "No se pudo encontrar la extensión del archivo en \"{filename}\"" #: mediagoblin/submit/forms.py:25 msgid "File" @@ -143,21 +178,21 @@ msgstr "Archivo" msgid "Description of this work" msgstr "Descripción de esta obra" -#: mediagoblin/submit/views.py:46 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "Debes proporcionar un archivo." -#: mediagoblin/submit/views.py:49 -msgid "The file doesn't seem to be an image!" -msgstr "¡El archivo no parece ser una imagen!" - -#: mediagoblin/submit/views.py:121 +#: mediagoblin/submit/views.py:127 msgid "Woohoo! Submitted!" -msgstr "¡Woohoo! ¡Enviado!" +msgstr "¡Yujú! ¡Enviado!" + +#: mediagoblin/submit/views.py:133 +msgid "Invalid file type." +msgstr "Tipo de archivo inválido." #: mediagoblin/templates/mediagoblin/404.html:21 msgid "Oops!" -msgstr "Ups!" +msgstr "¡Ups!" #: mediagoblin/templates/mediagoblin/404.html:24 msgid "There doesn't seem to be a page at this address. Sorry!" @@ -175,29 +210,29 @@ msgstr "" msgid "Image of 404 goblin stressing out" msgstr "Imagen de 404 goblin estresándose" -#: mediagoblin/templates/mediagoblin/base.html:22 -msgid "GNU MediaGoblin" -msgstr "GNU MediaGoblin" - -#: mediagoblin/templates/mediagoblin/base.html:47 +#: mediagoblin/templates/mediagoblin/base.html:49 msgid "MediaGoblin logo" msgstr "Logo de MediaGoblin" -#: mediagoblin/templates/mediagoblin/base.html:52 +#: mediagoblin/templates/mediagoblin/base.html:54 msgid "Submit media" msgstr "Enviar contenido" -#: mediagoblin/templates/mediagoblin/base.html:63 -msgid "verify your email!" -msgstr "¡Verifica tu correo electrónico!" +#: mediagoblin/templates/mediagoblin/base.html:65 +msgid "Verify your email!" +msgstr "¡Verifica tu email!" -#: mediagoblin/templates/mediagoblin/base.html:73 +#: mediagoblin/templates/mediagoblin/base.html:72 +msgid "log out" +msgstr "Cerrar sesión" + +#: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 -#: mediagoblin/templates/mediagoblin/auth/login.html:35 +#: mediagoblin/templates/mediagoblin/auth/login.html:45 msgid "Log in" msgstr "Conectarse" -#: mediagoblin/templates/mediagoblin/base.html:89 +#: mediagoblin/templates/mediagoblin/base.html:91 msgid "" "Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a " "href=\"http://gnu.org/\">GNU</a> project" @@ -210,71 +245,42 @@ msgid "Explore" msgstr "Explorar" #: mediagoblin/templates/mediagoblin/root.html:27 -msgid "Hi there, media lover! MediaGoblin is..." -msgstr "¡Hola, amante de los contenidos! MediaGoblin es ..." +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "Hola, ¡bienvenido a este sitio de MediaGoblin!" -#: mediagoblin/templates/mediagoblin/root.html:29 -msgid "The perfect place for your media!" -msgstr "¡El lugar ideal para tus contenidos!" - -#: mediagoblin/templates/mediagoblin/root.html:30 -msgid "" -"A place for people to collaborate and show off original and derived " -"creations!" -msgstr "" -"¡Un lugar para colaborar y exhibir tus creaciones originales y derivadas!" - -#: mediagoblin/templates/mediagoblin/root.html:31 +#: mediagoblin/templates/mediagoblin/root.html:28 msgid "" -"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project, " -"after all.)" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." msgstr "" -"Libre, como en la libertad. (Somos parte del proyecto <a " -"href=\"http://gnu.org\">GNU</a> después de todo.)" +"Este sitio está montado con <a " +"href=\"http://mediagoblin.org\">MediaGoblin</a>, un programa libre buenÃsimo" +" para gestionar contenido multimedia." -#: mediagoblin/templates/mediagoblin/root.html:32 -msgid "" -"Aiming to make the world a better place through decentralization and " -"(eventually, coming soon!) federation!" -msgstr "" -"Queriendo hacer del mundo un mejor lugar a través de la descentralización y " -"(eventualmente, muy pronto!) la federalización!" - -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "" -"Built for extensibility. (Multiple media types coming soon to the software," -" including video support!)" -msgstr "" -"Pensado para ser extensible. (Prontamente soporte para multiples formatos, " -"incluyendo video!)" - -#: mediagoblin/templates/mediagoblin/root.html:34 +#: mediagoblin/templates/mediagoblin/root.html:29 msgid "" -"Powered by people like you. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve this" -" software!</a>)" +"To add your own media, place comments, save your favourites and more, you " +"can log in with your MediaGoblin account." msgstr "" -"Impulsado por gente como vos. (<a " -"href=\"http://mediagoblin.org/pages/join.html\"> Vos podés ayudarnos a " -"mejorar este programa</a>)" +"Para añadir tus propios contenidos, dejar comentarios, guardar tus favoritos" +" y más, puedes iniciar sesión con tu cuenta de MediaGoblin." -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Excited to join us?" -msgstr "Te gustarÃa unirte a nosotros?" +#: mediagoblin/templates/mediagoblin/root.html:31 +msgid "Don't have one yet? It's easy!" +msgstr "¿Aún no tienes una? ¡Es fácil!" -#: mediagoblin/templates/mediagoblin/root.html:39 +#: mediagoblin/templates/mediagoblin/root.html:32 #, python-format msgid "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n" +"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" " or\n" -" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" msgstr "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Crea una " -"cuenta gratuita</a> o <a class=\"header_submit\" " -"href=\"http://wiki.mediagoblin.org/HackingHowto\">Establece MediaGoblin en " -"tu propio servidor</a>" +"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Crea una cuenta en este sitio</a>\n" +" o\n" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Instala MediaGoblin en tu propio servidor</a>" -#: mediagoblin/templates/mediagoblin/root.html:53 +#: mediagoblin/templates/mediagoblin/root.html:44 msgid "Most recent media" msgstr "El contenido más reciente" @@ -282,9 +288,18 @@ msgstr "El contenido más reciente" msgid "Enter your new password" msgstr "Ingrese su nueva contraseña" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29 -msgid "Enter your username or email" -msgstr "Introduzca su nombre de usuario o correo electrónico" +#: mediagoblin/templates/mediagoblin/auth/change_fp.html:33 +#: mediagoblin/templates/mediagoblin/submit/start.html:30 +msgid "Submit" +msgstr "Enviar" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27 +msgid "Recover password" +msgstr "Recuperar contraseña" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 +msgid "Send instructions" +msgstr "Enviar instrucciones" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 msgid "Your password has been changed. Try to log in now." @@ -310,31 +325,30 @@ msgid "" "If you think this is an error, just ignore this email and continue being\n" "a happy goblin!" msgstr "" -"Hola %(username)s , para cambiar su contraseña de GNU MediaGoblin, abra la " -"siguiente URL en su navegador: %(verification_url)s Si usted piensa que " -"esto es un error, simplemente ignore este mensaje y siga siendo un duende " -"feliz!" +"Hola %(username)s,\n" +"\n" +"Para cambiar tu contraseña de GNU MediaGoblin, abre la siguiente URL en un navegador:\n" +"\n" +"%(verification_url)s \n" +"\n" +"Si piensas que esto es un error, simplemente ignora este mensaje y sigue siendo un trasgo feliz." #: mediagoblin/templates/mediagoblin/auth/login.html:30 msgid "Logging in failed!" msgstr "¡Falló el inicio de sesión!" -#: mediagoblin/templates/mediagoblin/auth/login.html:43 +#: mediagoblin/templates/mediagoblin/auth/login.html:35 msgid "Don't have an account yet?" msgstr "¿No tienes una cuenta?" -#: mediagoblin/templates/mediagoblin/auth/login.html:46 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 msgid "Create one here!" msgstr "¡Crea una aquÃ!" -#: mediagoblin/templates/mediagoblin/auth/login.html:49 +#: mediagoblin/templates/mediagoblin/auth/login.html:42 msgid "Forgot your password?" msgstr "¿Olvidaste tu contraseña?" -#: mediagoblin/templates/mediagoblin/auth/login.html:52 -msgid "Change it!" -msgstr "Cambiarlo!" - #: mediagoblin/templates/mediagoblin/auth/register.html:27 msgid "Create an account!" msgstr "¡Crea una cuenta!" @@ -362,7 +376,7 @@ msgstr "" #: mediagoblin/templates/mediagoblin/edit/edit.html:29 #, python-format msgid "Editing %(media_title)s" -msgstr "Edición %(media_title)s " +msgstr "Editando %(media_title)s " #: mediagoblin/templates/mediagoblin/edit/edit.html:36 #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:49 @@ -379,32 +393,59 @@ msgstr "Guardar cambios" msgid "Editing %(username)s's profile" msgstr "Editando el perfil de %(username)s" -#: mediagoblin/templates/mediagoblin/listings/tag.html:31 -msgid "Media tagged with:" -msgstr "Contenido etiquetado con:" +#: mediagoblin/templates/mediagoblin/listings/tag.html:30 +#: mediagoblin/templates/mediagoblin/listings/tag.html:35 +#, python-format +msgid "Media tagged with: %(tag_name)s" +msgstr "Contenido etiquetado con: %(tag_name)s" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:19 +msgid "Original" +msgstr "Original" #: mediagoblin/templates/mediagoblin/submit/start.html:26 msgid "Submit yer media" msgstr "EnvÃa tu contenido" -#: mediagoblin/templates/mediagoblin/submit/start.html:30 -msgid "Submit" -msgstr "Enviar" +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 +#, python-format +msgid "%(username)s's media" +msgstr "Contenidos de %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32 +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:37 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" msgstr "Contenido de <a href=\"%(user_url)s\">%(username)s</a>'s" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:32 -msgid "Sorry, no such user found." -msgstr "Lo sentimos, no se encontró ese usuario." +#: mediagoblin/templates/mediagoblin/user_pages/media.html:57 +#, python-format +msgid "By <a href=\"%(user_url)s\">%(username)s</a> on %(date)s" +msgstr "Por <a href=\"%(user_url)s\">%(username)s</a> en %(date)s" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:67 +msgid "Post a comment" +msgstr "Pon un comentario." + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:85 +msgid "at" +msgstr "en" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +msgid "Post comment!" +msgstr "¡Pon un comentario!" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:124 +msgid "Edit" +msgstr "Editar" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:130 +msgid "Delete" +msgstr "Borrar" #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format msgid "Really delete %(title)s?" -msgstr "Realmente deseas eliminar %(title)s ?" +msgstr "¿Realmente deseas eliminar %(title)s?" #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:50 msgid "Delete Permanently" @@ -433,31 +474,41 @@ msgstr "No hay contenido siendo procesado." msgid "These uploads failed to process:" msgstr "Estos archivos no pudieron ser procesados:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:39 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 +#, python-format +msgid "%(username)s's profile" +msgstr "Perfil de %(username)s" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 +msgid "Sorry, no such user found." +msgstr "Lo sentimos, no se encontró ese usuario." + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 msgid "Email verification needed" msgstr "Es necesario un correo electrónico de verificación" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:42 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 msgid "Almost done! Your account still needs to be activated." -msgstr "Casi terminas! Solo falta activar la cuenta." +msgstr "¡Casi hemos terminado! Solo falta activar la cuenta." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 msgid "" "An email should arrive in a few moments with instructions on how to do so." msgstr "" "En unos momentos te deberÃa llegar un correo electrónico con las " "instrucciones para hacerlo." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:51 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 msgid "In case it doesn't:" msgstr "En caso de que no:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:54 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 msgid "Resend verification email" msgstr "Reenviar correo electrónico de verificación" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "" "Someone has registered an account with this username, but it still has to be" " activated." @@ -465,7 +516,7 @@ msgstr "" "Alguien ya registró una cuenta con ese nombre de usuario, pero todavÃa no " "fue activada." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:68 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 #, python-format msgid "" "If you are that person but you've lost your verification email, you can <a " @@ -474,41 +525,36 @@ msgstr "" "Si tú eres esa persona, pero has perdido tu correo electrónico de " "verificación, puedes <a href=\"%(login_url)s\">acceder</a> y reenviarlo." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:78 -#, python-format -msgid "%(username)s's profile" -msgstr "Perfil de %(username)s" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:85 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 msgid "Here's a spot to tell others about yourself." msgstr "Aquà hay un lugar para que le cuentes a los demás sobre tÃ." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:108 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:101 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:119 msgid "Edit profile" msgstr "Editar perfil" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:107 msgid "This user hasn't filled in their profile (yet)." msgstr "Este usuario (todavia) no ha completado su perfil." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:122 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:133 #, python-format msgid "View all of %(username)s's media" msgstr "Ver todo el contenido de %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:135 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:146 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "" "Aquà es donde tú contenido estará, pero parece que aún no has agregado nada." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:152 msgid "Add media" msgstr "Añadir contenido" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:147 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:158 msgid "There doesn't seem to be any media here yet..." msgstr "Parece que aún no hay ningún contenido aquÃ..." @@ -528,6 +574,18 @@ msgstr "Recientes" msgid "Older" msgstr "Antiguas" +#: mediagoblin/templates/mediagoblin/utils/pagination.html:50 +msgid "Go to page:" +msgstr "Ir a la página:" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:20 +msgid "Tagged with" +msgstr "Etiquetado con" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:25 +msgid "and" +msgstr "y" + #: mediagoblin/user_pages/forms.py:24 msgid "Comment" msgstr "Comentario" @@ -536,15 +594,23 @@ msgstr "Comentario" msgid "I am sure I want to delete this" msgstr "Estoy seguro de que quiero borrar esto" -#: mediagoblin/user_pages/views.py:142 -msgid "Empty comments are not allowed." -msgstr "" +#: mediagoblin/user_pages/views.py:155 +msgid "Oops, your comment was empty." +msgstr "Ups, tu comentario estaba vacÃo." -#: mediagoblin/user_pages/views.py:148 -msgid "Comment posted!" -msgstr "" +#: mediagoblin/user_pages/views.py:161 +msgid "Your comment has been posted!" +msgstr "¡Tu comentario ha sido publicado!" + +#: mediagoblin/user_pages/views.py:183 +msgid "You deleted the media." +msgstr "Eliminaste el contenido" + +#: mediagoblin/user_pages/views.py:190 +msgid "The media was not deleted because you didn't check that you were sure." +msgstr "El contenido no se eliminó porque no marcaste que estabas seguro." -#: mediagoblin/user_pages/views.py:181 +#: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." msgstr "" "Estás a punto de eliminar un contenido de otro usuario. Proceder con " diff --git a/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.mo Binary files differindex 90e83303..ed1ea35d 100644 --- a/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.po index 0a6a5a40..8d1e2711 100644 --- a/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.po @@ -13,9 +13,9 @@ msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" "Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n" -"POT-Creation-Date: 2011-11-01 23:14-0500\n" -"PO-Revision-Date: 2011-11-04 10:05+0000\n" -"Last-Translator: chesuidayeur <chesuidayeur@yahoo.fr>\n" +"POT-Creation-Date: 2011-12-04 10:24-0600\n" +"PO-Revision-Date: 2011-12-04 16:23+0000\n" +"Last-Translator: cwebber <cwebber@dustycloud.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -24,6 +24,10 @@ msgstr "" "Language: fr\n" "Plural-Forms: nplurals=2; plural=(n > 1)\n" +#: mediagoblin/processing.py:143 +msgid "Invalid file given for media type." +msgstr "Le fichier envoyé ne correspond pas au type de média." + #: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:49 msgid "Username" msgstr "Nom d'utilisateur" @@ -59,8 +63,8 @@ msgid "Sorry, a user with that name already exists." msgstr "Un utilisateur existe déjà avec ce nom, désolé." #: mediagoblin/auth/views.py:77 -msgid "Sorry, that email address has already been taken." -msgstr "Désolé, cette adresse courriel a déjà été prise." +msgid "Sorry, a user with that email address already exists." +msgstr "Désolé, il existe déjà un utilisateur ayant cette adresse e-mail." #: mediagoblin/auth/views.py:179 msgid "" @@ -74,11 +78,20 @@ msgstr "" msgid "The verification key or user id is incorrect" msgstr "La clé de vérification ou le nom d'utilisateur est incorrect." -#: mediagoblin/auth/views.py:207 +#: mediagoblin/auth/views.py:203 +msgid "You must be logged in so we know who to send the email to!" +msgstr "" +"Vous devez être authentifié afin que nous sachions à qui envoyer l'e-mail !" + +#: mediagoblin/auth/views.py:211 +msgid "You've already verified your email address!" +msgstr "Votre adresse e-mail a déjà été vérifiée !" + +#: mediagoblin/auth/views.py:224 msgid "Resent your verification email." msgstr "E-mail de vérification renvoyé." -#: mediagoblin/auth/views.py:248 +#: mediagoblin/auth/views.py:265 msgid "" "Could not send password recovery email as your username is inactive or your " "account's email address has not been verified." @@ -94,48 +107,68 @@ msgstr "Titre" msgid "Tags" msgstr "Tags" -#: mediagoblin/edit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 +msgid "Seperate tags by commas." +msgstr "" + +#: mediagoblin/edit/forms.py:33 msgid "Slug" msgstr "Légende" -#: mediagoblin/edit/forms.py:32 +#: mediagoblin/edit/forms.py:34 msgid "The slug can't be empty" msgstr "La légende ne peut pas être laissée vide." -#: mediagoblin/edit/forms.py:33 +#: mediagoblin/edit/forms.py:35 msgid "" "The title part of this media's URL. You usually don't need to change this." msgstr "" "Le nom de ce media dans l'URL. Vous n'avez normalement pas besoin de le " "changer" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "Bio" msgstr "Bio" -#: mediagoblin/edit/forms.py:43 +#: mediagoblin/edit/forms.py:45 msgid "Website" msgstr "Site web" -#: mediagoblin/edit/views.py:64 +#: mediagoblin/edit/forms.py:49 +msgid "Old password" +msgstr "Ancien mot de passe." + +#: mediagoblin/edit/forms.py:52 +msgid "New Password" +msgstr "Nouveau mot de passe" + +#: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." msgstr "Une entrée existe déjà pour cet utilisateur avec la même légende." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:86 msgid "You are editing another user's media. Proceed with caution." msgstr "" "Vous vous apprêtez à modifier le média d'un autre utilisateur. Veuillez " "prendre garde." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:156 msgid "You are editing a user's profile. Proceed with caution." msgstr "" "Vous vous apprêtez à modifier le profil d'un utilisateur. Veuillez prendre " "garde." -#: mediagoblin/process_media/errors.py:44 -msgid "Invalid file given for media type." -msgstr "Le fichier envoyé ne correspond pas au type de média." +#: mediagoblin/edit/views.py:171 +msgid "Wrong password" +msgstr "Mauvais mot de passe" + +#: mediagoblin/edit/views.py:192 +msgid "Profile edited!" +msgstr "Profile mis à jour !" + +#: mediagoblin/media_types/__init__.py:65 +msgid "Could not find any file extension in \"{filename}\"" +msgstr "Impossible d'extraire une extension de fichier de \"{nomfichier}\"" #: mediagoblin/submit/forms.py:25 msgid "File" @@ -145,21 +178,21 @@ msgstr "Fichier" msgid "Description of this work" msgstr "Descriptif pour ce travail" -#: mediagoblin/submit/views.py:46 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "Il vous faut fournir un fichier." -#: mediagoblin/submit/views.py:49 -msgid "The file doesn't seem to be an image!" -msgstr "Ce fichier ne semble pas être une image !" - -#: mediagoblin/submit/views.py:121 +#: mediagoblin/submit/views.py:127 msgid "Woohoo! Submitted!" msgstr "Youhou, c'est envoyé !" +#: mediagoblin/submit/views.py:133 +msgid "Invalid file type." +msgstr "Type de fichier invalide." + #: mediagoblin/templates/mediagoblin/404.html:21 msgid "Oops!" -msgstr "Zut!" +msgstr "Zut !" #: mediagoblin/templates/mediagoblin/404.html:24 msgid "There doesn't seem to be a page at this address. Sorry!" @@ -177,29 +210,29 @@ msgstr "" msgid "Image of 404 goblin stressing out" msgstr "Image de 404 gobelin angoissé" -#: mediagoblin/templates/mediagoblin/base.html:22 -msgid "GNU MediaGoblin" -msgstr "GNU MediaGoblin" - -#: mediagoblin/templates/mediagoblin/base.html:47 +#: mediagoblin/templates/mediagoblin/base.html:49 msgid "MediaGoblin logo" msgstr "Logo MediaGoblin" -#: mediagoblin/templates/mediagoblin/base.html:52 +#: mediagoblin/templates/mediagoblin/base.html:54 msgid "Submit media" msgstr "Soumettre un média" -#: mediagoblin/templates/mediagoblin/base.html:63 -msgid "verify your email!" -msgstr "vérifiez votre adresse e-mail !" +#: mediagoblin/templates/mediagoblin/base.html:65 +msgid "Verify your email!" +msgstr "Vérifiez votre adresse e-mail !" -#: mediagoblin/templates/mediagoblin/base.html:73 +#: mediagoblin/templates/mediagoblin/base.html:72 +msgid "log out" +msgstr "déconnexion" + +#: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 -#: mediagoblin/templates/mediagoblin/auth/login.html:35 +#: mediagoblin/templates/mediagoblin/auth/login.html:45 msgid "Log in" msgstr "S'identifier" -#: mediagoblin/templates/mediagoblin/base.html:89 +#: mediagoblin/templates/mediagoblin/base.html:91 msgid "" "Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a " "href=\"http://gnu.org/\">GNU</a> project" @@ -212,71 +245,39 @@ msgid "Explore" msgstr "Explorer" #: mediagoblin/templates/mediagoblin/root.html:27 -msgid "Hi there, media lover! MediaGoblin is..." -msgstr "Salut à tous, amateur de médias! MediaGoblin est ..." +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "Bonjour, et bienvenu sur ce site MediaGoblin !" -#: mediagoblin/templates/mediagoblin/root.html:29 -msgid "The perfect place for your media!" -msgstr "L'endroit idéal pour vos médias!" - -#: mediagoblin/templates/mediagoblin/root.html:30 -msgid "" -"A place for people to collaborate and show off original and derived " -"creations!" -msgstr "" -"Un espace de création collaboratif : montrez vos Å“uvres, originales ou " -"dérivées !" - -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "" -"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project, " -"after all.)" -msgstr "" -"Logiciel libre. (Nous sommes un projet <a href=\"http://gnu.org\">GNU</a> " -"après tout.)" - -#: mediagoblin/templates/mediagoblin/root.html:32 -msgid "" -"Aiming to make the world a better place through decentralization and " -"(eventually, coming soon!) federation!" -msgstr "" -"Une tentative de rendre le monde meilleur grâce à la décentralisation et (à " -"terme, et pour bientôt !) la fédération !" - -#: mediagoblin/templates/mediagoblin/root.html:33 +#: mediagoblin/templates/mediagoblin/root.html:28 msgid "" -"Built for extensibility. (Multiple media types coming soon to the software," -" including video support!)" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." msgstr "" -"Construit pour l'extensibilité. (Plusieurs types de médias à venir au " -"logiciel, y compris le support vidéo!)" -#: mediagoblin/templates/mediagoblin/root.html:34 +#: mediagoblin/templates/mediagoblin/root.html:29 msgid "" -"Powered by people like you. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve this" -" software!</a>)" +"To add your own media, place comments, save your favourites and more, you " +"can log in with your MediaGoblin account." msgstr "" -"Propulsé par des gens comme vous. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">Vous pouvez nous aider à " -"améliorer ce logiciel!</a>)" +"Ajoutez vos propres medias, commentez ceux des autres, sauvegardez vos " +"préférés et plus encore ! Faites tout cela depuis votre compte MediaGoblin." -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Excited to join us?" -msgstr "Envi de vous joindre à nous ?" +#: mediagoblin/templates/mediagoblin/root.html:31 +msgid "Don't have one yet? It's easy!" +msgstr "Vous n'en avez pas ? C'est facile !" -#: mediagoblin/templates/mediagoblin/root.html:39 +#: mediagoblin/templates/mediagoblin/root.html:32 #, python-format msgid "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n" +"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" " or\n" -" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" msgstr "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Créez gratuitement en compte</a>\n" +"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Créez un compte sur ce site</a>\n" " ou\n" -" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Installez MediaGoblin sur votre propre serveur</a>" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Déployez MediaGoblin sur votre propre serveur</a>" -#: mediagoblin/templates/mediagoblin/root.html:53 +#: mediagoblin/templates/mediagoblin/root.html:44 msgid "Most recent media" msgstr "Tout derniers media" @@ -284,9 +285,18 @@ msgstr "Tout derniers media" msgid "Enter your new password" msgstr "Entrez un nouveau mot de passe" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29 -msgid "Enter your username or email" -msgstr "Entrez votre nom d'utilisateur ou votre email" +#: mediagoblin/templates/mediagoblin/auth/change_fp.html:33 +#: mediagoblin/templates/mediagoblin/submit/start.html:30 +msgid "Submit" +msgstr "Soumettre" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27 +msgid "Recover password" +msgstr "Récupérer le mot de passe" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 +msgid "Send instructions" +msgstr "Envoyer les instructions" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 msgid "Your password has been changed. Try to log in now." @@ -327,25 +337,21 @@ msgstr "" msgid "Logging in failed!" msgstr "La connexion a échoué!" -#: mediagoblin/templates/mediagoblin/auth/login.html:43 +#: mediagoblin/templates/mediagoblin/auth/login.html:35 msgid "Don't have an account yet?" -msgstr "Pas encore de compte?" +msgstr "Pas encore de compte ?" -#: mediagoblin/templates/mediagoblin/auth/login.html:46 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 msgid "Create one here!" -msgstr "Créez-en un ici!" +msgstr "Créez-en un ici !" -#: mediagoblin/templates/mediagoblin/auth/login.html:49 +#: mediagoblin/templates/mediagoblin/auth/login.html:42 msgid "Forgot your password?" msgstr "Vous avez oublié votre mot de passe ?" -#: mediagoblin/templates/mediagoblin/auth/login.html:52 -msgid "Change it!" -msgstr "Changez-le !" - #: mediagoblin/templates/mediagoblin/auth/register.html:27 msgid "Create an account!" -msgstr "Créer un compte!" +msgstr "Créer un compte !" #: mediagoblin/templates/mediagoblin/auth/register.html:31 msgid "Create" @@ -387,27 +393,54 @@ msgstr "Enregistrer les modifications" msgid "Editing %(username)s's profile" msgstr "Modification du profil de %(username)s" -#: mediagoblin/templates/mediagoblin/listings/tag.html:31 -msgid "Media tagged with:" -msgstr "Média comportant les tags suivants :" +#: mediagoblin/templates/mediagoblin/listings/tag.html:30 +#: mediagoblin/templates/mediagoblin/listings/tag.html:35 +#, python-format +msgid "Media tagged with: %(tag_name)s" +msgstr "Médias taggés avec : %(tag_name)s " + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:19 +msgid "Original" +msgstr "Original" #: mediagoblin/templates/mediagoblin/submit/start.html:26 msgid "Submit yer media" msgstr "Soumettez ce média" -#: mediagoblin/templates/mediagoblin/submit/start.html:30 -msgid "Submit" -msgstr "Soumettre" +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 +#, python-format +msgid "%(username)s's media" +msgstr "Medias de %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32 +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:37 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" msgstr "Médias de <a href=\"%(user_url)s\">%(username)s</a>" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:32 -msgid "Sorry, no such user found." -msgstr "Impossible de trouver cet utilisateur, désolé." +#: mediagoblin/templates/mediagoblin/user_pages/media.html:57 +#, python-format +msgid "By <a href=\"%(user_url)s\">%(username)s</a> on %(date)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:67 +msgid "Post a comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:85 +msgid "at" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +msgid "Post comment!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:124 +msgid "Edit" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:130 +msgid "Delete" +msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -441,31 +474,41 @@ msgstr "Aucun média en transformation" msgid "These uploads failed to process:" msgstr "Le traitement de ces ajouts a échoué :" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:39 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 +#, python-format +msgid "%(username)s's profile" +msgstr "profil de %(username)s" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 +msgid "Sorry, no such user found." +msgstr "Impossible de trouver cet utilisateur, désolé." + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 msgid "Email verification needed" msgstr "Vérification d'email nécessaire" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:42 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 msgid "Almost done! Your account still needs to be activated." msgstr "Presque fini ! Votre compte a encore besoin d'être activé." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 msgid "" "An email should arrive in a few moments with instructions on how to do so." msgstr "" "Un e-mail devrait vous parvenir dans quelques instants ; il vous indiquera " "comment procéder." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:51 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 msgid "In case it doesn't:" msgstr "Si la vérification n'est pas arrivée à bon port :" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:54 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 msgid "Resend verification email" msgstr "Renvoyer l'e-mail de vérification" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "" "Someone has registered an account with this username, but it still has to be" " activated." @@ -473,7 +516,7 @@ msgstr "" "Quelqu'un a enregistré un compte avec ce nom, mais il doit encore être " "activé." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:68 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 #, python-format msgid "" "If you are that person but you've lost your verification email, you can <a " @@ -483,30 +526,25 @@ msgstr "" "vérification, vous pouvez vous <a href=\"%(login_url)s\">identifier</a> et " "le renvoyer." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:78 -#, python-format -msgid "%(username)s's profile" -msgstr "profil de %(username)s" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:85 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 msgid "Here's a spot to tell others about yourself." msgstr "Voici un endroit pour parler aux autres de vous-même." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:108 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:101 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:119 msgid "Edit profile" msgstr "Modifier le profil" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:107 msgid "This user hasn't filled in their profile (yet)." msgstr "Cet utilisateur n'a pas (encore) rempli son profil." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:122 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:133 #, python-format msgid "View all of %(username)s's media" msgstr "Voir tous les médias de %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:135 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:146 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." @@ -514,11 +552,11 @@ msgstr "" "C'est là où vos médias apparaîssent, mais vous ne semblez pas avoir encore " "ajouté quoi que ce soit." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:152 msgid "Add media" msgstr "Ajouter des médias" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:147 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:158 msgid "There doesn't seem to be any media here yet..." msgstr "Il ne semble pas y avoir de média là , pour l'instant ..." @@ -538,6 +576,18 @@ msgstr "Nouveaux" msgid "Older" msgstr "Anciens" +#: mediagoblin/templates/mediagoblin/utils/pagination.html:50 +msgid "Go to page:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:20 +msgid "Tagged with" +msgstr "Taggé avec" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:25 +msgid "and" +msgstr "et" + #: mediagoblin/user_pages/forms.py:24 msgid "Comment" msgstr "Commentaire" @@ -546,15 +596,25 @@ msgstr "Commentaire" msgid "I am sure I want to delete this" msgstr "Je suis sûr de vouloir supprimer cela" -#: mediagoblin/user_pages/views.py:142 -msgid "Empty comments are not allowed." -msgstr "Les commentaires vides ne sont pas autorisés." +#: mediagoblin/user_pages/views.py:155 +msgid "Oops, your comment was empty." +msgstr "" + +#: mediagoblin/user_pages/views.py:161 +msgid "Your comment has been posted!" +msgstr "" -#: mediagoblin/user_pages/views.py:148 -msgid "Comment posted!" -msgstr "Votre commentaire a été posté !" +#: mediagoblin/user_pages/views.py:183 +msgid "You deleted the media." +msgstr "Vous avez supprimé le media." + +#: mediagoblin/user_pages/views.py:190 +msgid "The media was not deleted because you didn't check that you were sure." +msgstr "" +"Ce media n'a pas été supprimé car vous n'avez pas confirmer que vous étiez " +"sur." -#: mediagoblin/user_pages/views.py:181 +#: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." msgstr "" "Vous êtes sur le point de supprimer des médias d'un autre utilisateur. " diff --git a/mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.mo Binary files differindex feb156ff..c0a1ecb6 100644 --- a/mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.po index d9fdf8d6..512635e3 100644 --- a/mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/ia/LC_MESSAGES/mediagoblin.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" "Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n" -"POT-Creation-Date: 2011-11-01 23:14-0500\n" -"PO-Revision-Date: 2011-11-02 04:13+0000\n" +"POT-Creation-Date: 2011-12-04 10:24-0600\n" +"PO-Revision-Date: 2011-12-04 16:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" @@ -19,6 +19,10 @@ msgstr "" "Language: ia\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" +#: mediagoblin/processing.py:143 +msgid "Invalid file given for media type." +msgstr "" + #: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:49 msgid "Username" msgstr "Nomine de usator" @@ -52,7 +56,7 @@ msgid "Sorry, a user with that name already exists." msgstr "" #: mediagoblin/auth/views.py:77 -msgid "Sorry, that email address has already been taken." +msgid "Sorry, a user with that email address already exists." msgstr "" #: mediagoblin/auth/views.py:179 @@ -65,11 +69,19 @@ msgstr "" msgid "The verification key or user id is incorrect" msgstr "" -#: mediagoblin/auth/views.py:207 +#: mediagoblin/auth/views.py:203 +msgid "You must be logged in so we know who to send the email to!" +msgstr "" + +#: mediagoblin/auth/views.py:211 +msgid "You've already verified your email address!" +msgstr "" + +#: mediagoblin/auth/views.py:224 msgid "Resent your verification email." msgstr "" -#: mediagoblin/auth/views.py:248 +#: mediagoblin/auth/views.py:265 msgid "" "Could not send password recovery email as your username is inactive or your " "account's email address has not been verified." @@ -83,41 +95,61 @@ msgstr "Titulo" msgid "Tags" msgstr "" -#: mediagoblin/edit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 +msgid "Seperate tags by commas." +msgstr "" + +#: mediagoblin/edit/forms.py:33 msgid "Slug" msgstr "" -#: mediagoblin/edit/forms.py:32 +#: mediagoblin/edit/forms.py:34 msgid "The slug can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:33 +#: mediagoblin/edit/forms.py:35 msgid "" "The title part of this media's URL. You usually don't need to change this." msgstr "" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "Bio" msgstr "" -#: mediagoblin/edit/forms.py:43 +#: mediagoblin/edit/forms.py:45 msgid "Website" msgstr "Sito web" -#: mediagoblin/edit/views.py:64 +#: mediagoblin/edit/forms.py:49 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:52 +msgid "New Password" +msgstr "" + +#: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:86 msgid "You are editing another user's media. Proceed with caution." msgstr "" -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:156 msgid "You are editing a user's profile. Proceed with caution." msgstr "" -#: mediagoblin/process_media/errors.py:44 -msgid "Invalid file given for media type." +#: mediagoblin/edit/views.py:171 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/edit/views.py:192 +msgid "Profile edited!" +msgstr "" + +#: mediagoblin/media_types/__init__.py:65 +msgid "Could not find any file extension in \"{filename}\"" msgstr "" #: mediagoblin/submit/forms.py:25 @@ -128,16 +160,16 @@ msgstr "" msgid "Description of this work" msgstr "" -#: mediagoblin/submit/views.py:46 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "" -#: mediagoblin/submit/views.py:49 -msgid "The file doesn't seem to be an image!" +#: mediagoblin/submit/views.py:127 +msgid "Woohoo! Submitted!" msgstr "" -#: mediagoblin/submit/views.py:121 -msgid "Woohoo! Submitted!" +#: mediagoblin/submit/views.py:133 +msgid "Invalid file type." msgstr "" #: mediagoblin/templates/mediagoblin/404.html:21 @@ -158,29 +190,29 @@ msgstr "" msgid "Image of 404 goblin stressing out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:22 -msgid "GNU MediaGoblin" -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:47 +#: mediagoblin/templates/mediagoblin/base.html:49 msgid "MediaGoblin logo" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:52 +#: mediagoblin/templates/mediagoblin/base.html:54 msgid "Submit media" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:63 -msgid "verify your email!" +#: mediagoblin/templates/mediagoblin/base.html:65 +msgid "Verify your email!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:72 +msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:73 +#: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 -#: mediagoblin/templates/mediagoblin/auth/login.html:35 +#: mediagoblin/templates/mediagoblin/auth/login.html:45 msgid "Log in" msgstr "Initiar session" -#: mediagoblin/templates/mediagoblin/base.html:89 +#: mediagoblin/templates/mediagoblin/base.html:91 msgid "" "Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a " "href=\"http://gnu.org/\">GNU</a> project" @@ -191,57 +223,34 @@ msgid "Explore" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:27 -msgid "Hi there, media lover! MediaGoblin is..." +msgid "Hi there, welcome to this MediaGoblin site!" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:29 -msgid "The perfect place for your media!" +#: mediagoblin/templates/mediagoblin/root.html:28 +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:30 +#: mediagoblin/templates/mediagoblin/root.html:29 msgid "" -"A place for people to collaborate and show off original and derived " -"creations!" +"To add your own media, place comments, save your favourites and more, you " +"can log in with your MediaGoblin account." msgstr "" #: mediagoblin/templates/mediagoblin/root.html:31 -msgid "" -"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project, " -"after all.)" +msgid "Don't have one yet? It's easy!" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:32 -msgid "" -"Aiming to make the world a better place through decentralization and " -"(eventually, coming soon!) federation!" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "" -"Built for extensibility. (Multiple media types coming soon to the software," -" including video support!)" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:34 -msgid "" -"Powered by people like you. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve this" -" software!</a>)" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Excited to join us?" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:39 #, python-format msgid "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n" +"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" " or\n" -" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:53 +#: mediagoblin/templates/mediagoblin/root.html:44 msgid "Most recent media" msgstr "" @@ -249,8 +258,17 @@ msgstr "" msgid "Enter your new password" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29 -msgid "Enter your username or email" +#: mediagoblin/templates/mediagoblin/auth/change_fp.html:33 +#: mediagoblin/templates/mediagoblin/submit/start.html:30 +msgid "Submit" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27 +msgid "Recover password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 +msgid "Send instructions" msgstr "" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 @@ -280,22 +298,18 @@ msgstr "" msgid "Logging in failed!" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:43 +#: mediagoblin/templates/mediagoblin/auth/login.html:35 msgid "Don't have an account yet?" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:46 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 msgid "Create one here!" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:49 +#: mediagoblin/templates/mediagoblin/auth/login.html:42 msgid "Forgot your password?" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:52 -msgid "Change it!" -msgstr "" - #: mediagoblin/templates/mediagoblin/auth/register.html:27 msgid "Create an account!" msgstr "Crear un conto!" @@ -335,26 +349,53 @@ msgstr "" msgid "Editing %(username)s's profile" msgstr "" -#: mediagoblin/templates/mediagoblin/listings/tag.html:31 -msgid "Media tagged with:" +#: mediagoblin/templates/mediagoblin/listings/tag.html:30 +#: mediagoblin/templates/mediagoblin/listings/tag.html:35 +#, python-format +msgid "Media tagged with: %(tag_name)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:19 +msgid "Original" msgstr "" #: mediagoblin/templates/mediagoblin/submit/start.html:26 msgid "Submit yer media" msgstr "" -#: mediagoblin/templates/mediagoblin/submit/start.html:30 -msgid "Submit" +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 +#, python-format +msgid "%(username)s's media" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32 +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:37 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:32 -msgid "Sorry, no such user found." +#: mediagoblin/templates/mediagoblin/user_pages/media.html:57 +#, python-format +msgid "By <a href=\"%(user_url)s\">%(username)s</a> on %(date)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:67 +msgid "Post a comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:85 +msgid "at" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +msgid "Post comment!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:124 +msgid "Edit" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:130 +msgid "Delete" msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 @@ -387,75 +428,80 @@ msgstr "" msgid "These uploads failed to process:" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:39 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 +#, python-format +msgid "%(username)s's profile" +msgstr "Profilo de %(username)s" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 +msgid "Sorry, no such user found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 msgid "Email verification needed" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:42 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 msgid "Almost done! Your account still needs to be activated." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 msgid "" "An email should arrive in a few moments with instructions on how to do so." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:51 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 msgid "In case it doesn't:" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:54 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 msgid "Resend verification email" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "" "Someone has registered an account with this username, but it still has to be" " activated." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:68 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 #, python-format msgid "" "If you are that person but you've lost your verification email, you can <a " "href=\"%(login_url)s\">log in</a> and resend it." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:78 -#, python-format -msgid "%(username)s's profile" -msgstr "Profilo de %(username)s" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:85 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 msgid "Here's a spot to tell others about yourself." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:108 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:101 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:119 msgid "Edit profile" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:107 msgid "This user hasn't filled in their profile (yet)." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:122 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:133 #, python-format msgid "View all of %(username)s's media" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:135 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:146 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:152 msgid "Add media" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:147 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:158 msgid "There doesn't seem to be any media here yet..." msgstr "" @@ -475,6 +521,18 @@ msgstr "" msgid "Older" msgstr "" +#: mediagoblin/templates/mediagoblin/utils/pagination.html:50 +msgid "Go to page:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:20 +msgid "Tagged with" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:25 +msgid "and" +msgstr "" + #: mediagoblin/user_pages/forms.py:24 msgid "Comment" msgstr "Commento" @@ -483,15 +541,23 @@ msgstr "Commento" msgid "I am sure I want to delete this" msgstr "" -#: mediagoblin/user_pages/views.py:142 -msgid "Empty comments are not allowed." +#: mediagoblin/user_pages/views.py:155 +msgid "Oops, your comment was empty." +msgstr "" + +#: mediagoblin/user_pages/views.py:161 +msgid "Your comment has been posted!" +msgstr "" + +#: mediagoblin/user_pages/views.py:183 +msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:148 -msgid "Comment posted!" +#: mediagoblin/user_pages/views.py:190 +msgid "The media was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:181 +#: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." msgstr "" diff --git a/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.mo Binary files differindex cc0ccbfa..1319a605 100644 --- a/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.po index 183d09ed..96d1f0a2 100644 --- a/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/it/LC_MESSAGES/mediagoblin.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" "Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n" -"POT-Creation-Date: 2011-11-01 23:14-0500\n" -"PO-Revision-Date: 2011-11-02 04:13+0000\n" +"POT-Creation-Date: 2011-12-04 10:24-0600\n" +"PO-Revision-Date: 2011-12-04 16:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" @@ -19,6 +19,10 @@ msgstr "" "Language: it\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" +#: mediagoblin/processing.py:143 +msgid "Invalid file given for media type." +msgstr "documento non valido come tipo multimediale." + #: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:49 msgid "Username" msgstr "Nome utente" @@ -52,8 +56,8 @@ msgid "Sorry, a user with that name already exists." msgstr "Spiacente, esiste già un utente con quel nome" #: mediagoblin/auth/views.py:77 -msgid "Sorry, that email address has already been taken." -msgstr "Spiacente, quell'indirizzo email è già stato preso." +msgid "Sorry, a user with that email address already exists." +msgstr "" #: mediagoblin/auth/views.py:179 msgid "" @@ -67,11 +71,19 @@ msgstr "" msgid "The verification key or user id is incorrect" msgstr "La chiave di verifica o l'id utente è sbagliato" -#: mediagoblin/auth/views.py:207 +#: mediagoblin/auth/views.py:203 +msgid "You must be logged in so we know who to send the email to!" +msgstr "" + +#: mediagoblin/auth/views.py:211 +msgid "You've already verified your email address!" +msgstr "" + +#: mediagoblin/auth/views.py:224 msgid "Resent your verification email." msgstr "Rispedisci email di verifica" -#: mediagoblin/auth/views.py:248 +#: mediagoblin/auth/views.py:265 msgid "" "Could not send password recovery email as your username is inactive or your " "account's email address has not been verified." @@ -85,44 +97,64 @@ msgstr "Titolo" msgid "Tags" msgstr "Tags" -#: mediagoblin/edit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 +msgid "Seperate tags by commas." +msgstr "" + +#: mediagoblin/edit/forms.py:33 msgid "Slug" msgstr "" -#: mediagoblin/edit/forms.py:32 +#: mediagoblin/edit/forms.py:34 msgid "The slug can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:33 +#: mediagoblin/edit/forms.py:35 msgid "" "The title part of this media's URL. You usually don't need to change this." msgstr "" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "Bio" msgstr "Bio" -#: mediagoblin/edit/forms.py:43 +#: mediagoblin/edit/forms.py:45 msgid "Website" msgstr "Sito web" -#: mediagoblin/edit/views.py:64 +#: mediagoblin/edit/forms.py:49 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:52 +msgid "New Password" +msgstr "" + +#: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:86 msgid "You are editing another user's media. Proceed with caution." msgstr "" "Stai modificando documenti multimediale di un altro utente. Procedi con " "attenzione." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:156 msgid "You are editing a user's profile. Proceed with caution." msgstr "Stai modificando il profilo di un utente. Procedi con attenzione." -#: mediagoblin/process_media/errors.py:44 -msgid "Invalid file given for media type." -msgstr "documento non valido come tipo multimediale." +#: mediagoblin/edit/views.py:171 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/edit/views.py:192 +msgid "Profile edited!" +msgstr "" + +#: mediagoblin/media_types/__init__.py:65 +msgid "Could not find any file extension in \"{filename}\"" +msgstr "" #: mediagoblin/submit/forms.py:25 msgid "File" @@ -132,18 +164,18 @@ msgstr "Documento" msgid "Description of this work" msgstr "Descrizione di questo lavoro" -#: mediagoblin/submit/views.py:46 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "Devi specificare un documento." -#: mediagoblin/submit/views.py:49 -msgid "The file doesn't seem to be an image!" -msgstr "Il documento non sembra essere un'immagine!" - -#: mediagoblin/submit/views.py:121 +#: mediagoblin/submit/views.py:127 msgid "Woohoo! Submitted!" msgstr "Evviva! " +#: mediagoblin/submit/views.py:133 +msgid "Invalid file type." +msgstr "" + #: mediagoblin/templates/mediagoblin/404.html:21 msgid "Oops!" msgstr "Oops!" @@ -164,29 +196,29 @@ msgstr "" msgid "Image of 404 goblin stressing out" msgstr "Immagine di 404 folletti che stressano" -#: mediagoblin/templates/mediagoblin/base.html:22 -msgid "GNU MediaGoblin" -msgstr "GNU MediaGoblin" - -#: mediagoblin/templates/mediagoblin/base.html:47 +#: mediagoblin/templates/mediagoblin/base.html:49 msgid "MediaGoblin logo" msgstr "MediaGoblin logo" -#: mediagoblin/templates/mediagoblin/base.html:52 +#: mediagoblin/templates/mediagoblin/base.html:54 msgid "Submit media" msgstr "Inoltra file multimediale" -#: mediagoblin/templates/mediagoblin/base.html:63 -msgid "verify your email!" -msgstr "verifica il tuo indirizzo email!" +#: mediagoblin/templates/mediagoblin/base.html:65 +msgid "Verify your email!" +msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:73 +#: mediagoblin/templates/mediagoblin/base.html:72 +msgid "log out" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 -#: mediagoblin/templates/mediagoblin/auth/login.html:35 +#: mediagoblin/templates/mediagoblin/auth/login.html:45 msgid "Log in" msgstr "Accedi" -#: mediagoblin/templates/mediagoblin/base.html:89 +#: mediagoblin/templates/mediagoblin/base.html:91 msgid "" "Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a " "href=\"http://gnu.org/\">GNU</a> project" @@ -199,65 +231,34 @@ msgid "Explore" msgstr "Esplora" #: mediagoblin/templates/mediagoblin/root.html:27 -msgid "Hi there, media lover! MediaGoblin is..." -msgstr "Ciao, amante del multimedia! MediaGoblin è..." - -#: mediagoblin/templates/mediagoblin/root.html:29 -msgid "The perfect place for your media!" -msgstr "Il posto perfetto per i tuoi documenti multimediali!" - -#: mediagoblin/templates/mediagoblin/root.html:30 -msgid "" -"A place for people to collaborate and show off original and derived " -"creations!" -msgstr "" -"Un posto per collaborare con altri e mostrare le proprie creazioni originali" -" e derivate!" - -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "" -"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project, " -"after all.)" +msgid "Hi there, welcome to this MediaGoblin site!" msgstr "" -"Libero, come in libertà . (Siamo un progetto <a " -"href=\"http://gnu.org\">GNU</a>, dopotutto.)" -#: mediagoblin/templates/mediagoblin/root.html:32 +#: mediagoblin/templates/mediagoblin/root.html:28 msgid "" -"Aiming to make the world a better place through decentralization and " -"(eventually, coming soon!) federation!" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." msgstr "" -"Con l'obbiettivo di rendere il mondo un posto migliore attraverso la " -"decentrelizzazione e (finalmente, presto!) federazione!" -#: mediagoblin/templates/mediagoblin/root.html:33 +#: mediagoblin/templates/mediagoblin/root.html:29 msgid "" -"Built for extensibility. (Multiple media types coming soon to the software," -" including video support!)" +"To add your own media, place comments, save your favourites and more, you " +"can log in with your MediaGoblin account." msgstr "" -"Fatto per estensibilità . (Numerosi tipi multimediali saranno presto aggiunti" -" al programma, incluso il supporto video!)" -#: mediagoblin/templates/mediagoblin/root.html:34 -msgid "" -"Powered by people like you. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve this" -" software!</a>)" +#: mediagoblin/templates/mediagoblin/root.html:31 +msgid "Don't have one yet? It's easy!" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Excited to join us?" -msgstr "Eccitato di unirti a noi?" - -#: mediagoblin/templates/mediagoblin/root.html:39 +#: mediagoblin/templates/mediagoblin/root.html:32 #, python-format msgid "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n" +"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" " or\n" -" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:53 +#: mediagoblin/templates/mediagoblin/root.html:44 msgid "Most recent media" msgstr "Documenti multimediali più recenti" @@ -265,9 +266,18 @@ msgstr "Documenti multimediali più recenti" msgid "Enter your new password" msgstr "Inserisci la tua nuova password" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29 -msgid "Enter your username or email" -msgstr "Inserisci il tuo nome utente o email" +#: mediagoblin/templates/mediagoblin/auth/change_fp.html:33 +#: mediagoblin/templates/mediagoblin/submit/start.html:30 +msgid "Submit" +msgstr "Conferma" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27 +msgid "Recover password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 +msgid "Send instructions" +msgstr "" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 msgid "Your password has been changed. Try to log in now." @@ -296,22 +306,18 @@ msgstr "" msgid "Logging in failed!" msgstr "Accesso fallito!" -#: mediagoblin/templates/mediagoblin/auth/login.html:43 +#: mediagoblin/templates/mediagoblin/auth/login.html:35 msgid "Don't have an account yet?" msgstr "Non hai ancora un account?" -#: mediagoblin/templates/mediagoblin/auth/login.html:46 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 msgid "Create one here!" msgstr "Creane uno qui!" -#: mediagoblin/templates/mediagoblin/auth/login.html:49 +#: mediagoblin/templates/mediagoblin/auth/login.html:42 msgid "Forgot your password?" msgstr "Hai dimenticato la password?" -#: mediagoblin/templates/mediagoblin/auth/login.html:52 -msgid "Change it!" -msgstr "" - #: mediagoblin/templates/mediagoblin/auth/register.html:27 msgid "Create an account!" msgstr "Crea un account!" @@ -356,27 +362,54 @@ msgstr "Salva i cambiamenti" msgid "Editing %(username)s's profile" msgstr "Stai modificando il profilo di %(username)s" -#: mediagoblin/templates/mediagoblin/listings/tag.html:31 -msgid "Media tagged with:" -msgstr "Media taggata con:" +#: mediagoblin/templates/mediagoblin/listings/tag.html:30 +#: mediagoblin/templates/mediagoblin/listings/tag.html:35 +#, python-format +msgid "Media tagged with: %(tag_name)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:19 +msgid "Original" +msgstr "" #: mediagoblin/templates/mediagoblin/submit/start.html:26 msgid "Submit yer media" msgstr "Inoltra documento multimediale" -#: mediagoblin/templates/mediagoblin/submit/start.html:30 -msgid "Submit" -msgstr "Conferma" +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 +#, python-format +msgid "%(username)s's media" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32 +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:37 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" msgstr "Documenti multimediali di <a href=\"%(user_url)s\">%(username)s</a>" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:32 -msgid "Sorry, no such user found." -msgstr "Mi dispiace, utente non trovato" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:57 +#, python-format +msgid "By <a href=\"%(user_url)s\">%(username)s</a> on %(date)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:67 +msgid "Post a comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:85 +msgid "at" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +msgid "Post comment!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:124 +msgid "Edit" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:130 +msgid "Delete" +msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -408,30 +441,40 @@ msgstr "Nessun documento multimediale in elaborazione" msgid "These uploads failed to process:" msgstr "L'elaborazione di questi upload è fallita:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:39 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 +#, python-format +msgid "%(username)s's profile" +msgstr "profilo di %(username)s" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 +msgid "Sorry, no such user found." +msgstr "Mi dispiace, utente non trovato" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 msgid "Email verification needed" msgstr "è necessario verificare email" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:42 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 msgid "Almost done! Your account still needs to be activated." msgstr "Quasi finito! Il tuo account deve ancora essere attivato." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 msgid "" "An email should arrive in a few moments with instructions on how to do so." msgstr "" "In breve dovresti ricevere un email contenente istruzioni su come fare." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:51 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 msgid "In case it doesn't:" msgstr "Nel caso non fosse:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:54 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 msgid "Resend verification email" msgstr "Rispedisci email di verifica" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "" "Someone has registered an account with this username, but it still has to be" " activated." @@ -439,7 +482,7 @@ msgstr "" "Qualcuno ha registrato un account con questo nome utente, ma deve ancora " "essere attivato." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:68 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 #, python-format msgid "" "If you are that person but you've lost your verification email, you can <a " @@ -448,30 +491,25 @@ msgstr "" "Se sei quella persona ma hai perso l'email di verifica, puoi <a " "href=\"%(login_url)s\">accedere</a> e rispedirlo." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:78 -#, python-format -msgid "%(username)s's profile" -msgstr "profilo di %(username)s" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:85 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 msgid "Here's a spot to tell others about yourself." msgstr "Ecco un posto dove raccontare agli altri di te." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:108 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:101 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:119 msgid "Edit profile" msgstr "Modifica profilo" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:107 msgid "This user hasn't filled in their profile (yet)." msgstr "Questo utente non ha (ancora) compilato il proprio profilo." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:122 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:133 #, python-format msgid "View all of %(username)s's media" msgstr "Visualizza tutti i file multimediali di %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:135 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:146 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." @@ -479,11 +517,11 @@ msgstr "" "Questo è dove i tuoi documenti multimediali appariranno, ma sembra che tu " "non abbia ancora aggiunto niente." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:152 msgid "Add media" msgstr "Aggiungi documenti multimediali" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:147 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:158 msgid "There doesn't seem to be any media here yet..." msgstr "Non sembra ci sia ancora nessun documento multimediali qui.." @@ -503,6 +541,18 @@ msgstr "Più nuovo" msgid "Older" msgstr "Più vecchio" +#: mediagoblin/templates/mediagoblin/utils/pagination.html:50 +msgid "Go to page:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:20 +msgid "Tagged with" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:25 +msgid "and" +msgstr "" + #: mediagoblin/user_pages/forms.py:24 msgid "Comment" msgstr "Commento" @@ -511,15 +561,23 @@ msgstr "Commento" msgid "I am sure I want to delete this" msgstr "Sono sicuro di volerlo cancellare" -#: mediagoblin/user_pages/views.py:142 -msgid "Empty comments are not allowed." +#: mediagoblin/user_pages/views.py:155 +msgid "Oops, your comment was empty." +msgstr "" + +#: mediagoblin/user_pages/views.py:161 +msgid "Your comment has been posted!" +msgstr "" + +#: mediagoblin/user_pages/views.py:183 +msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:148 -msgid "Comment posted!" +#: mediagoblin/user_pages/views.py:190 +msgid "The media was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:181 +#: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." msgstr "" "Stai cancellando un documento multimediale di un altro utente. Procedi con " diff --git a/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.mo Binary files differindex 5267eddc..39f3595b 100644 --- a/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.po index 59262d82..3198eed9 100644 --- a/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/ja/LC_MESSAGES/mediagoblin.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" "Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n" -"POT-Creation-Date: 2011-11-01 23:14-0500\n" -"PO-Revision-Date: 2011-11-02 04:13+0000\n" +"POT-Creation-Date: 2011-12-04 10:24-0600\n" +"PO-Revision-Date: 2011-12-04 16:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" @@ -19,6 +19,10 @@ msgstr "" "Language: ja\n" "Plural-Forms: nplurals=1; plural=0\n" +#: mediagoblin/processing.py:143 +msgid "Invalid file given for media type." +msgstr "" + #: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:49 msgid "Username" msgstr "ユーザãƒãƒ¼ãƒ " @@ -52,7 +56,7 @@ msgid "Sorry, a user with that name already exists." msgstr "申ã—訳ã‚りã¾ã›ã‚“ãŒã€ãã®åå‰ã‚’æŒã¤ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒã™ã§ã«å˜åœ¨ã—ã¦ã„ã¾ã™ã€‚" #: mediagoblin/auth/views.py:77 -msgid "Sorry, that email address has already been taken." +msgid "Sorry, a user with that email address already exists." msgstr "" #: mediagoblin/auth/views.py:179 @@ -65,11 +69,19 @@ msgstr "メアドãŒç¢ºèªã•れã¦ã„ã¾ã™ã€‚ã“れã§ã€ãƒã‚°ã‚¤ãƒ³ã—ã¦ãƒ— msgid "The verification key or user id is incorrect" msgstr "検証ã‚ーã¾ãŸã¯ãƒ¦ãƒ¼ã‚¶ãƒ¼IDãŒé–“é•ã£ã¦ã„ã¾ã™" -#: mediagoblin/auth/views.py:207 +#: mediagoblin/auth/views.py:203 +msgid "You must be logged in so we know who to send the email to!" +msgstr "" + +#: mediagoblin/auth/views.py:211 +msgid "You've already verified your email address!" +msgstr "" + +#: mediagoblin/auth/views.py:224 msgid "Resent your verification email." msgstr "検証メールをå†é€ã—ã¾ã—ãŸã€‚" -#: mediagoblin/auth/views.py:248 +#: mediagoblin/auth/views.py:265 msgid "" "Could not send password recovery email as your username is inactive or your " "account's email address has not been verified." @@ -83,41 +95,61 @@ msgstr "タイトル" msgid "Tags" msgstr "ã‚¿ã‚°" -#: mediagoblin/edit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 +msgid "Seperate tags by commas." +msgstr "" + +#: mediagoblin/edit/forms.py:33 msgid "Slug" msgstr "スラグ" -#: mediagoblin/edit/forms.py:32 +#: mediagoblin/edit/forms.py:34 msgid "The slug can't be empty" msgstr "スラグã¯å¿…è¦ã§ã™ã€‚" -#: mediagoblin/edit/forms.py:33 +#: mediagoblin/edit/forms.py:35 msgid "" "The title part of this media's URL. You usually don't need to change this." msgstr "" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "Bio" msgstr "自己紹介" -#: mediagoblin/edit/forms.py:43 +#: mediagoblin/edit/forms.py:45 msgid "Website" msgstr "URL" -#: mediagoblin/edit/views.py:64 +#: mediagoblin/edit/forms.py:49 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:52 +msgid "New Password" +msgstr "" + +#: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." msgstr "ãã®ã‚¹ãƒ©ã‚°ã‚’æŒã¤ã‚¨ãƒ³ãƒˆãƒªã¯ã€ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯æ—¢ã«å˜åœ¨ã—ã¾ã™ã€‚" -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:86 msgid "You are editing another user's media. Proceed with caution." msgstr "ã‚ãªãŸã¯ã€ä»–ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ¡ãƒ‡ã‚£ã‚¢ã‚’編集ã—ã¦ã„ã¾ã™ã€‚ã”æ³¨æ„ãã ã•ã„。" -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:156 msgid "You are editing a user's profile. Proceed with caution." msgstr "ã‚ãªãŸã¯ã€ä»–ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ—ãƒãƒ•ァイルを編集ã—ã¦ã„ã¾ã™ã€‚ã”æ³¨æ„ãã ã•ã„。" -#: mediagoblin/process_media/errors.py:44 -msgid "Invalid file given for media type." +#: mediagoblin/edit/views.py:171 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/edit/views.py:192 +msgid "Profile edited!" +msgstr "" + +#: mediagoblin/media_types/__init__.py:65 +msgid "Could not find any file extension in \"{filename}\"" msgstr "" #: mediagoblin/submit/forms.py:25 @@ -128,18 +160,18 @@ msgstr "ファイル" msgid "Description of this work" msgstr "" -#: mediagoblin/submit/views.py:46 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "ファイルをæä¾›ã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚" -#: mediagoblin/submit/views.py:49 -msgid "The file doesn't seem to be an image!" -msgstr "ファイルãŒç”»åƒã§ã¯ãªã„よã†ã§ã™ï¼" - -#: mediagoblin/submit/views.py:121 +#: mediagoblin/submit/views.py:127 msgid "Woohoo! Submitted!" msgstr "投稿終了ï¼" +#: mediagoblin/submit/views.py:133 +msgid "Invalid file type." +msgstr "" + #: mediagoblin/templates/mediagoblin/404.html:21 msgid "Oops!" msgstr "" @@ -158,29 +190,29 @@ msgstr "" msgid "Image of 404 goblin stressing out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:22 -msgid "GNU MediaGoblin" -msgstr "GNU MediaGoblin" - -#: mediagoblin/templates/mediagoblin/base.html:47 +#: mediagoblin/templates/mediagoblin/base.html:49 msgid "MediaGoblin logo" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:52 +#: mediagoblin/templates/mediagoblin/base.html:54 msgid "Submit media" msgstr "コンテンツを投稿" -#: mediagoblin/templates/mediagoblin/base.html:63 -msgid "verify your email!" -msgstr "メアドを確èªã—ã¦ãã ã•ã„ï¼" +#: mediagoblin/templates/mediagoblin/base.html:65 +msgid "Verify your email!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:72 +msgid "log out" +msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:73 +#: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 -#: mediagoblin/templates/mediagoblin/auth/login.html:35 +#: mediagoblin/templates/mediagoblin/auth/login.html:45 msgid "Log in" msgstr "ãƒã‚°ã‚¤ãƒ³" -#: mediagoblin/templates/mediagoblin/base.html:89 +#: mediagoblin/templates/mediagoblin/base.html:91 msgid "" "Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a " "href=\"http://gnu.org/\">GNU</a> project" @@ -191,57 +223,34 @@ msgid "Explore" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:27 -msgid "Hi there, media lover! MediaGoblin is..." +msgid "Hi there, welcome to this MediaGoblin site!" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:29 -msgid "The perfect place for your media!" +#: mediagoblin/templates/mediagoblin/root.html:28 +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:30 +#: mediagoblin/templates/mediagoblin/root.html:29 msgid "" -"A place for people to collaborate and show off original and derived " -"creations!" +"To add your own media, place comments, save your favourites and more, you " +"can log in with your MediaGoblin account." msgstr "" #: mediagoblin/templates/mediagoblin/root.html:31 -msgid "" -"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project, " -"after all.)" +msgid "Don't have one yet? It's easy!" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:32 -msgid "" -"Aiming to make the world a better place through decentralization and " -"(eventually, coming soon!) federation!" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "" -"Built for extensibility. (Multiple media types coming soon to the software," -" including video support!)" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:34 -msgid "" -"Powered by people like you. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve this" -" software!</a>)" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Excited to join us?" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:39 #, python-format msgid "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n" +"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" " or\n" -" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:53 +#: mediagoblin/templates/mediagoblin/root.html:44 msgid "Most recent media" msgstr "" @@ -249,8 +258,17 @@ msgstr "" msgid "Enter your new password" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29 -msgid "Enter your username or email" +#: mediagoblin/templates/mediagoblin/auth/change_fp.html:33 +#: mediagoblin/templates/mediagoblin/submit/start.html:30 +msgid "Submit" +msgstr "é€ä¿¡" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27 +msgid "Recover password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 +msgid "Send instructions" msgstr "" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 @@ -280,22 +298,18 @@ msgstr "" msgid "Logging in failed!" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:43 +#: mediagoblin/templates/mediagoblin/auth/login.html:35 msgid "Don't have an account yet?" msgstr "ã¾ã アカウントをæŒã£ã¦ã„ã¾ã›ã‚“ã‹ï¼Ÿ" -#: mediagoblin/templates/mediagoblin/auth/login.html:46 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 msgid "Create one here!" msgstr "ã“ã“ã§ä½œæˆï¼" -#: mediagoblin/templates/mediagoblin/auth/login.html:49 +#: mediagoblin/templates/mediagoblin/auth/login.html:42 msgid "Forgot your password?" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:52 -msgid "Change it!" -msgstr "" - #: mediagoblin/templates/mediagoblin/auth/register.html:27 msgid "Create an account!" msgstr "アカウントを作æˆï¼" @@ -340,27 +354,54 @@ msgstr "投稿ã™ã‚‹" msgid "Editing %(username)s's profile" msgstr "%(username)sã•ã‚“ã®ãƒ—ãƒãƒ•ィールを編集ä¸" -#: mediagoblin/templates/mediagoblin/listings/tag.html:31 -msgid "Media tagged with:" -msgstr "タグ付ã‘ã•れãŸã‚³ãƒ³ãƒ†ãƒ³ãƒ„:" +#: mediagoblin/templates/mediagoblin/listings/tag.html:30 +#: mediagoblin/templates/mediagoblin/listings/tag.html:35 +#, python-format +msgid "Media tagged with: %(tag_name)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:19 +msgid "Original" +msgstr "" #: mediagoblin/templates/mediagoblin/submit/start.html:26 msgid "Submit yer media" msgstr "コンテンツを投稿" -#: mediagoblin/templates/mediagoblin/submit/start.html:30 -msgid "Submit" -msgstr "é€ä¿¡" +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 +#, python-format +msgid "%(username)s's media" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32 +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:37 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" msgstr "<a href=\"%(user_url)s\">%(username)s</a>ã•ã‚“ã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:32 -msgid "Sorry, no such user found." -msgstr "申ã—訳ã‚りã¾ã›ã‚“ãŒã€ãã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:57 +#, python-format +msgid "By <a href=\"%(user_url)s\">%(username)s</a> on %(date)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:67 +msgid "Post a comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:85 +msgid "at" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +msgid "Post comment!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:124 +msgid "Edit" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:130 +msgid "Delete" +msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -392,75 +433,80 @@ msgstr "" msgid "These uploads failed to process:" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:39 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 +#, python-format +msgid "%(username)s's profile" +msgstr "%(username)sã•ã‚“ã®ãƒ—ãƒãƒ•ィール" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 +msgid "Sorry, no such user found." +msgstr "申ã—訳ã‚りã¾ã›ã‚“ãŒã€ãã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 msgid "Email verification needed" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:42 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 msgid "Almost done! Your account still needs to be activated." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 msgid "" "An email should arrive in a few moments with instructions on how to do so." msgstr "メールã¯ã€ãã®æ–¹æ³•ã®æŒ‡ç¤ºã§ã„ãã¤ã‹ã®çž¬é–“ã«åˆ°ç€ã—ã¾ã™ã€‚" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:51 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 msgid "In case it doesn't:" msgstr "到ç€ã—ãªã„å ´åˆã¯ã€" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:54 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 msgid "Resend verification email" msgstr "確èªãƒ¡ãƒ¼ãƒ«ã‚’å†é€ä¿¡" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "" "Someone has registered an account with this username, but it still has to be" " activated." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:68 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 #, python-format msgid "" "If you are that person but you've lost your verification email, you can <a " "href=\"%(login_url)s\">log in</a> and resend it." msgstr "ã‚ãªãŸã®ç¢ºèªãƒ¡ãƒ¼ãƒ«ã‚’紛失ã—ãŸå ´åˆã€<a href=\"%(login_url)s\">ãƒã‚°ã‚¤ãƒ³</a>ã—ã¦å†é€ã§ãã¾ã™ã€‚" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:78 -#, python-format -msgid "%(username)s's profile" -msgstr "%(username)sã•ã‚“ã®ãƒ—ãƒãƒ•ィール" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:85 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 msgid "Here's a spot to tell others about yourself." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:108 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:101 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:119 msgid "Edit profile" msgstr "プãƒãƒ•ィールを編集" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:107 msgid "This user hasn't filled in their profile (yet)." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:122 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:133 #, python-format msgid "View all of %(username)s's media" msgstr "%(username)sã•ã‚“ã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã‚’ã™ã¹ã¦è¦‹ã‚‹" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:135 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:146 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:152 msgid "Add media" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:147 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:158 msgid "There doesn't seem to be any media here yet..." msgstr "" @@ -480,6 +526,18 @@ msgstr "" msgid "Older" msgstr "" +#: mediagoblin/templates/mediagoblin/utils/pagination.html:50 +msgid "Go to page:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:20 +msgid "Tagged with" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:25 +msgid "and" +msgstr "" + #: mediagoblin/user_pages/forms.py:24 msgid "Comment" msgstr "" @@ -488,15 +546,23 @@ msgstr "" msgid "I am sure I want to delete this" msgstr "" -#: mediagoblin/user_pages/views.py:142 -msgid "Empty comments are not allowed." +#: mediagoblin/user_pages/views.py:155 +msgid "Oops, your comment was empty." +msgstr "" + +#: mediagoblin/user_pages/views.py:161 +msgid "Your comment has been posted!" +msgstr "" + +#: mediagoblin/user_pages/views.py:183 +msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:148 -msgid "Comment posted!" +#: mediagoblin/user_pages/views.py:190 +msgid "The media was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:181 +#: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." msgstr "" diff --git a/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.mo Binary files differindex e6d1976b..842bfb9b 100644 --- a/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.po index 618daf6f..c1778676 100644 --- a/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/nl/LC_MESSAGES/mediagoblin.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" "Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n" -"POT-Creation-Date: 2011-11-01 23:14-0500\n" -"PO-Revision-Date: 2011-11-02 04:13+0000\n" +"POT-Creation-Date: 2011-12-04 10:24-0600\n" +"PO-Revision-Date: 2011-12-04 16:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" @@ -19,6 +19,10 @@ msgstr "" "Language: nl\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" +#: mediagoblin/processing.py:143 +msgid "Invalid file given for media type." +msgstr "" + #: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:49 msgid "Username" msgstr "Gebruikersnaam" @@ -52,8 +56,8 @@ msgid "Sorry, a user with that name already exists." msgstr "Sorry, er bestaat al een gebruiker met die naam." #: mediagoblin/auth/views.py:77 -msgid "Sorry, that email address has already been taken." -msgstr "Sorry, dat e-mailadres is al ingenomen." +msgid "Sorry, a user with that email address already exists." +msgstr "" #: mediagoblin/auth/views.py:179 msgid "" @@ -67,11 +71,19 @@ msgstr "" msgid "The verification key or user id is incorrect" msgstr "De verificatie sleutel of gebruikers-ID is onjuist" -#: mediagoblin/auth/views.py:207 +#: mediagoblin/auth/views.py:203 +msgid "You must be logged in so we know who to send the email to!" +msgstr "" + +#: mediagoblin/auth/views.py:211 +msgid "You've already verified your email address!" +msgstr "" + +#: mediagoblin/auth/views.py:224 msgid "Resent your verification email." msgstr "Verificatie e-mail opnieuw opgestuurd." -#: mediagoblin/auth/views.py:248 +#: mediagoblin/auth/views.py:265 msgid "" "Could not send password recovery email as your username is inactive or your " "account's email address has not been verified." @@ -85,44 +97,64 @@ msgstr "Titel" msgid "Tags" msgstr "Etiket" -#: mediagoblin/edit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 +msgid "Seperate tags by commas." +msgstr "" + +#: mediagoblin/edit/forms.py:33 msgid "Slug" msgstr "" -#: mediagoblin/edit/forms.py:32 +#: mediagoblin/edit/forms.py:34 msgid "The slug can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:33 +#: mediagoblin/edit/forms.py:35 msgid "" "The title part of this media's URL. You usually don't need to change this." msgstr "" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "Bio" msgstr "Bio" -#: mediagoblin/edit/forms.py:43 +#: mediagoblin/edit/forms.py:45 msgid "Website" msgstr "Website" -#: mediagoblin/edit/views.py:64 +#: mediagoblin/edit/forms.py:49 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:52 +msgid "New Password" +msgstr "" + +#: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:86 msgid "You are editing another user's media. Proceed with caution." msgstr "" "U bent de media van een andere gebruiker aan het aanpassen. Ga voorzichtig " "te werk." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:156 msgid "You are editing a user's profile. Proceed with caution." msgstr "" "U bent een gebruikersprofiel aan het aanpassen. Ga voorzichtig te werk." -#: mediagoblin/process_media/errors.py:44 -msgid "Invalid file given for media type." +#: mediagoblin/edit/views.py:171 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/edit/views.py:192 +msgid "Profile edited!" +msgstr "" + +#: mediagoblin/media_types/__init__.py:65 +msgid "Could not find any file extension in \"{filename}\"" msgstr "" #: mediagoblin/submit/forms.py:25 @@ -133,18 +165,18 @@ msgstr "Bestand" msgid "Description of this work" msgstr "" -#: mediagoblin/submit/views.py:46 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "U moet een bestand aangeven." -#: mediagoblin/submit/views.py:49 -msgid "The file doesn't seem to be an image!" -msgstr "Het lijkt erop dat dit bestand geen afbeelding is!" - -#: mediagoblin/submit/views.py:121 +#: mediagoblin/submit/views.py:127 msgid "Woohoo! Submitted!" msgstr "Mooizo! Toegevoegd!" +#: mediagoblin/submit/views.py:133 +msgid "Invalid file type." +msgstr "" + #: mediagoblin/templates/mediagoblin/404.html:21 msgid "Oops!" msgstr "" @@ -163,29 +195,29 @@ msgstr "" msgid "Image of 404 goblin stressing out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:22 -msgid "GNU MediaGoblin" -msgstr "GNU MediaGoblin" - -#: mediagoblin/templates/mediagoblin/base.html:47 +#: mediagoblin/templates/mediagoblin/base.html:49 msgid "MediaGoblin logo" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:52 +#: mediagoblin/templates/mediagoblin/base.html:54 msgid "Submit media" msgstr "Voeg media toe" -#: mediagoblin/templates/mediagoblin/base.html:63 -msgid "verify your email!" -msgstr "Controleer uw e-mail!" +#: mediagoblin/templates/mediagoblin/base.html:65 +msgid "Verify your email!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:72 +msgid "log out" +msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:73 +#: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 -#: mediagoblin/templates/mediagoblin/auth/login.html:35 +#: mediagoblin/templates/mediagoblin/auth/login.html:45 msgid "Log in" msgstr "Inloggen" -#: mediagoblin/templates/mediagoblin/base.html:89 +#: mediagoblin/templates/mediagoblin/base.html:91 msgid "" "Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a " "href=\"http://gnu.org/\">GNU</a> project" @@ -196,57 +228,34 @@ msgid "Explore" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:27 -msgid "Hi there, media lover! MediaGoblin is..." +msgid "Hi there, welcome to this MediaGoblin site!" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:29 -msgid "The perfect place for your media!" +#: mediagoblin/templates/mediagoblin/root.html:28 +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:30 +#: mediagoblin/templates/mediagoblin/root.html:29 msgid "" -"A place for people to collaborate and show off original and derived " -"creations!" +"To add your own media, place comments, save your favourites and more, you " +"can log in with your MediaGoblin account." msgstr "" #: mediagoblin/templates/mediagoblin/root.html:31 -msgid "" -"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project, " -"after all.)" +msgid "Don't have one yet? It's easy!" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:32 -msgid "" -"Aiming to make the world a better place through decentralization and " -"(eventually, coming soon!) federation!" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "" -"Built for extensibility. (Multiple media types coming soon to the software," -" including video support!)" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:34 -msgid "" -"Powered by people like you. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve this" -" software!</a>)" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Excited to join us?" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:39 #, python-format msgid "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n" +"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" " or\n" -" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:53 +#: mediagoblin/templates/mediagoblin/root.html:44 msgid "Most recent media" msgstr "" @@ -254,8 +263,17 @@ msgstr "" msgid "Enter your new password" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29 -msgid "Enter your username or email" +#: mediagoblin/templates/mediagoblin/auth/change_fp.html:33 +#: mediagoblin/templates/mediagoblin/submit/start.html:30 +msgid "Submit" +msgstr "Voeg toe" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27 +msgid "Recover password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 +msgid "Send instructions" msgstr "" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 @@ -285,22 +303,18 @@ msgstr "" msgid "Logging in failed!" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:43 +#: mediagoblin/templates/mediagoblin/auth/login.html:35 msgid "Don't have an account yet?" msgstr "Heeft u nog geen account?" -#: mediagoblin/templates/mediagoblin/auth/login.html:46 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 msgid "Create one here!" msgstr "Maak er hier een!" -#: mediagoblin/templates/mediagoblin/auth/login.html:49 +#: mediagoblin/templates/mediagoblin/auth/login.html:42 msgid "Forgot your password?" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:52 -msgid "Change it!" -msgstr "" - #: mediagoblin/templates/mediagoblin/auth/register.html:27 msgid "Create an account!" msgstr "Maak een account aan!" @@ -342,27 +356,54 @@ msgstr "Wijzigingen opslaan" msgid "Editing %(username)s's profile" msgstr "Het profiel aanpassen van %(username)s" -#: mediagoblin/templates/mediagoblin/listings/tag.html:31 -msgid "Media tagged with:" -msgstr "Media met het etiket:" +#: mediagoblin/templates/mediagoblin/listings/tag.html:30 +#: mediagoblin/templates/mediagoblin/listings/tag.html:35 +#, python-format +msgid "Media tagged with: %(tag_name)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:19 +msgid "Original" +msgstr "" #: mediagoblin/templates/mediagoblin/submit/start.html:26 msgid "Submit yer media" msgstr "Voeg media toe" -#: mediagoblin/templates/mediagoblin/submit/start.html:30 -msgid "Submit" -msgstr "Voeg toe" +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 +#, python-format +msgid "%(username)s's media" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32 +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:37 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" msgstr "Media van <a href=\"%(user_url)s\"> %(username)s </a>" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:32 -msgid "Sorry, no such user found." -msgstr "Sorry, die gebruiker kon niet worden gevonden." +#: mediagoblin/templates/mediagoblin/user_pages/media.html:57 +#, python-format +msgid "By <a href=\"%(user_url)s\">%(username)s</a> on %(date)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:67 +msgid "Post a comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:85 +msgid "at" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +msgid "Post comment!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:124 +msgid "Edit" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:130 +msgid "Delete" +msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -394,37 +435,47 @@ msgstr "" msgid "These uploads failed to process:" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:39 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 +#, python-format +msgid "%(username)s's profile" +msgstr "Profiel van %(username)s" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 +msgid "Sorry, no such user found." +msgstr "Sorry, die gebruiker kon niet worden gevonden." + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 msgid "Email verification needed" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:42 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 msgid "Almost done! Your account still needs to be activated." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 msgid "" "An email should arrive in a few moments with instructions on how to do so." msgstr "" "Een e-mail zou in een paar ogenblikken aan moeten komen met instructies " "hiertoe." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:51 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 msgid "In case it doesn't:" msgstr "Zoniet:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:54 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 msgid "Resend verification email" msgstr "Stuur de verificatie e-mail opnieuw op." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "" "Someone has registered an account with this username, but it still has to be" " activated." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:68 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 #, python-format msgid "" "If you are that person but you've lost your verification email, you can <a " @@ -433,40 +484,35 @@ msgstr "" "Als u die persoon bent, maar de verificatie e-mail verloren hebt, kunt u <a " "href=\"%(login_url)s\">inloggen</a> en hem nogmaals verzenden." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:78 -#, python-format -msgid "%(username)s's profile" -msgstr "Profiel van %(username)s" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:85 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 msgid "Here's a spot to tell others about yourself." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:108 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:101 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:119 msgid "Edit profile" msgstr "Profiel aanpassen." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:107 msgid "This user hasn't filled in their profile (yet)." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:122 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:133 #, python-format msgid "View all of %(username)s's media" msgstr "Bekijk alle media van %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:135 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:146 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:152 msgid "Add media" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:147 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:158 msgid "There doesn't seem to be any media here yet..." msgstr "" @@ -486,6 +532,18 @@ msgstr "" msgid "Older" msgstr "" +#: mediagoblin/templates/mediagoblin/utils/pagination.html:50 +msgid "Go to page:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:20 +msgid "Tagged with" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:25 +msgid "and" +msgstr "" + #: mediagoblin/user_pages/forms.py:24 msgid "Comment" msgstr "Commentaar" @@ -494,15 +552,23 @@ msgstr "Commentaar" msgid "I am sure I want to delete this" msgstr "" -#: mediagoblin/user_pages/views.py:142 -msgid "Empty comments are not allowed." +#: mediagoblin/user_pages/views.py:155 +msgid "Oops, your comment was empty." +msgstr "" + +#: mediagoblin/user_pages/views.py:161 +msgid "Your comment has been posted!" +msgstr "" + +#: mediagoblin/user_pages/views.py:183 +msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:148 -msgid "Comment posted!" +#: mediagoblin/user_pages/views.py:190 +msgid "The media was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:181 +#: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." msgstr "" diff --git a/mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.mo Binary files differindex ba427c29..c07f42be 100644 --- a/mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.po index c74e1dd0..0b0c2a27 100644 --- a/mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/nn_NO/LC_MESSAGES/mediagoblin.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" "Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n" -"POT-Creation-Date: 2011-11-01 23:14-0500\n" -"PO-Revision-Date: 2011-11-02 04:13+0000\n" +"POT-Creation-Date: 2011-12-04 10:24-0600\n" +"PO-Revision-Date: 2011-12-04 16:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" @@ -19,6 +19,10 @@ msgstr "" "Language: nn_NO\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" +#: mediagoblin/processing.py:143 +msgid "Invalid file given for media type." +msgstr "Ugyldig fil for mediatypen." + #: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:49 msgid "Username" msgstr "Brukarnamn" @@ -52,8 +56,8 @@ msgid "Sorry, a user with that name already exists." msgstr "Ein konto med dette brukarnamnet finst allereide." #: mediagoblin/auth/views.py:77 -msgid "Sorry, that email address has already been taken." -msgstr "Den epostadressa er allereide teken." +msgid "Sorry, a user with that email address already exists." +msgstr "" #: mediagoblin/auth/views.py:179 msgid "" @@ -67,11 +71,19 @@ msgstr "" msgid "The verification key or user id is incorrect" msgstr "Stadfestingsnykelen eller brukar-ID-en din er feil." -#: mediagoblin/auth/views.py:207 +#: mediagoblin/auth/views.py:203 +msgid "You must be logged in so we know who to send the email to!" +msgstr "" + +#: mediagoblin/auth/views.py:211 +msgid "You've already verified your email address!" +msgstr "" + +#: mediagoblin/auth/views.py:224 msgid "Resent your verification email." msgstr "Send ein ny stadfestingsepost." -#: mediagoblin/auth/views.py:248 +#: mediagoblin/auth/views.py:265 msgid "" "Could not send password recovery email as your username is inactive or your " "account's email address has not been verified." @@ -86,42 +98,62 @@ msgstr "Tittel" msgid "Tags" msgstr "Merkelappar" -#: mediagoblin/edit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 +msgid "Seperate tags by commas." +msgstr "" + +#: mediagoblin/edit/forms.py:33 msgid "Slug" msgstr "Nettnamn" -#: mediagoblin/edit/forms.py:32 +#: mediagoblin/edit/forms.py:34 msgid "The slug can't be empty" msgstr "Nettnamnet kan ikkje vera tomt" -#: mediagoblin/edit/forms.py:33 +#: mediagoblin/edit/forms.py:35 msgid "" "The title part of this media's URL. You usually don't need to change this." msgstr "Nettnamnet (adressetittel) for mediefila di. Trengst ikkje endrast." -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "Bio" msgstr "Presentasjon" -#: mediagoblin/edit/forms.py:43 +#: mediagoblin/edit/forms.py:45 msgid "Website" msgstr "Heimeside" -#: mediagoblin/edit/views.py:64 +#: mediagoblin/edit/forms.py:49 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:52 +msgid "New Password" +msgstr "" + +#: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." msgstr "Eit innlegg med denne adressetittelen finst allereie." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:86 msgid "You are editing another user's media. Proceed with caution." msgstr "TrÃ¥ varsamt, du endrar nokon andre sine mediefiler." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:156 msgid "You are editing a user's profile. Proceed with caution." msgstr "TrÃ¥ varsamt, du endrar nokon andre sin profil." -#: mediagoblin/process_media/errors.py:44 -msgid "Invalid file given for media type." -msgstr "Ugyldig fil for mediatypen." +#: mediagoblin/edit/views.py:171 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/edit/views.py:192 +msgid "Profile edited!" +msgstr "" + +#: mediagoblin/media_types/__init__.py:65 +msgid "Could not find any file extension in \"{filename}\"" +msgstr "" #: mediagoblin/submit/forms.py:25 msgid "File" @@ -131,18 +163,18 @@ msgstr "Fil" msgid "Description of this work" msgstr "Skildring av mediefila" -#: mediagoblin/submit/views.py:46 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "Du mÃ¥ velja ei fil." -#: mediagoblin/submit/views.py:49 -msgid "The file doesn't seem to be an image!" -msgstr "Fila verkar ikkje Ã¥ vera ei gyldig biletefil." - -#: mediagoblin/submit/views.py:121 +#: mediagoblin/submit/views.py:127 msgid "Woohoo! Submitted!" msgstr "Johoo! Opplasta!" +#: mediagoblin/submit/views.py:133 +msgid "Invalid file type." +msgstr "" + #: mediagoblin/templates/mediagoblin/404.html:21 msgid "Oops!" msgstr "Oops." @@ -163,29 +195,29 @@ msgstr "" msgid "Image of 404 goblin stressing out" msgstr "Bilete av stressa 404-tusse." -#: mediagoblin/templates/mediagoblin/base.html:22 -msgid "GNU MediaGoblin" -msgstr "GNU MediaGoblin" - -#: mediagoblin/templates/mediagoblin/base.html:47 +#: mediagoblin/templates/mediagoblin/base.html:49 msgid "MediaGoblin logo" msgstr "MediaGoblin" -#: mediagoblin/templates/mediagoblin/base.html:52 +#: mediagoblin/templates/mediagoblin/base.html:54 msgid "Submit media" msgstr "Last opp" -#: mediagoblin/templates/mediagoblin/base.html:63 -msgid "verify your email!" -msgstr "Stadfest epostadressa di" +#: mediagoblin/templates/mediagoblin/base.html:65 +msgid "Verify your email!" +msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:73 +#: mediagoblin/templates/mediagoblin/base.html:72 +msgid "log out" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 -#: mediagoblin/templates/mediagoblin/auth/login.html:35 +#: mediagoblin/templates/mediagoblin/auth/login.html:45 msgid "Log in" msgstr "Logg inn" -#: mediagoblin/templates/mediagoblin/base.html:89 +#: mediagoblin/templates/mediagoblin/base.html:91 msgid "" "Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a " "href=\"http://gnu.org/\">GNU</a> project" @@ -198,69 +230,34 @@ msgid "Explore" msgstr "Utforsk" #: mediagoblin/templates/mediagoblin/root.html:27 -msgid "Hi there, media lover! MediaGoblin is..." -msgstr "Hei der mediaentusiast, MediaGoblin..." - -#: mediagoblin/templates/mediagoblin/root.html:29 -msgid "The perfect place for your media!" -msgstr "Er ein perfekt plass for mediet ditt!" - -#: mediagoblin/templates/mediagoblin/root.html:30 -msgid "" -"A place for people to collaborate and show off original and derived " -"creations!" +msgid "Hi there, welcome to this MediaGoblin site!" msgstr "" -"Er ein plass for folk Ã¥ samarbeida og visa fram sjølvlaga og vidarebygde " -"verk." - -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "" -"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project, " -"after all.)" -msgstr "Fri som i fridom (me er eit <a href=\"http://gnu.org\">GNU</a>-prosjekt)." -#: mediagoblin/templates/mediagoblin/root.html:32 +#: mediagoblin/templates/mediagoblin/root.html:28 msgid "" -"Aiming to make the world a better place through decentralization and " -"(eventually, coming soon!) federation!" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." msgstr "" -"Arbeidar for Ã¥ gjera verda ein betre stad gjennom desentralisering og (til " -"slutt, kjem snart!) federering, enkelt forklart deling og sending av " -"mediefiler og kommentarar over fleire nettstader." - -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "" -"Built for extensibility. (Multiple media types coming soon to the software," -" including video support!)" -msgstr "Bygd for utviding (fleire medietypar kjem snart, m.a. video)." -#: mediagoblin/templates/mediagoblin/root.html:34 +#: mediagoblin/templates/mediagoblin/root.html:29 msgid "" -"Powered by people like you. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve this" -" software!</a>)" +"To add your own media, place comments, save your favourites and more, you " +"can log in with your MediaGoblin account." msgstr "" -"Driven av folk som deg. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">Du kan hjelpa med Ã¥ forbetra" -" MediaGoblin</a>)" -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Excited to join us?" -msgstr "Lyst til Ã¥ bli med oss?" +#: mediagoblin/templates/mediagoblin/root.html:31 +msgid "Don't have one yet? It's easy!" +msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:39 +#: mediagoblin/templates/mediagoblin/root.html:32 #, python-format msgid "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n" +"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" " or\n" -" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" msgstr "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Opprett ein " -"gratis konto</a> eller <a class=\"header_submit\" " -"href=\"http://wiki.mediagoblin.org/HackingHowto\">installer MediaGoblin pÃ¥ " -"eigen tenar</a>" -#: mediagoblin/templates/mediagoblin/root.html:53 +#: mediagoblin/templates/mediagoblin/root.html:44 msgid "Most recent media" msgstr "Nyaste mediefiler" @@ -268,9 +265,18 @@ msgstr "Nyaste mediefiler" msgid "Enter your new password" msgstr "Fyll inn passord" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29 -msgid "Enter your username or email" -msgstr "Fyll inn brukarnamn eller epost" +#: mediagoblin/templates/mediagoblin/auth/change_fp.html:33 +#: mediagoblin/templates/mediagoblin/submit/start.html:30 +msgid "Submit" +msgstr "Send" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27 +msgid "Recover password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 +msgid "Send instructions" +msgstr "" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 msgid "Your password has been changed. Try to log in now." @@ -308,22 +314,18 @@ msgstr "" msgid "Logging in failed!" msgstr "Innlogging feila" -#: mediagoblin/templates/mediagoblin/auth/login.html:43 +#: mediagoblin/templates/mediagoblin/auth/login.html:35 msgid "Don't have an account yet?" msgstr "Har du ingen konto?" -#: mediagoblin/templates/mediagoblin/auth/login.html:46 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 msgid "Create one here!" msgstr "Lag ein!" -#: mediagoblin/templates/mediagoblin/auth/login.html:49 +#: mediagoblin/templates/mediagoblin/auth/login.html:42 msgid "Forgot your password?" msgstr "Gløymd passordet?" -#: mediagoblin/templates/mediagoblin/auth/login.html:52 -msgid "Change it!" -msgstr "Endra" - #: mediagoblin/templates/mediagoblin/auth/register.html:27 msgid "Create an account!" msgstr "Lag ein konto." @@ -368,27 +370,54 @@ msgstr "Lagra" msgid "Editing %(username)s's profile" msgstr "Endrar profilen til %(username)s" -#: mediagoblin/templates/mediagoblin/listings/tag.html:31 -msgid "Media tagged with:" -msgstr "Merkelappar:" +#: mediagoblin/templates/mediagoblin/listings/tag.html:30 +#: mediagoblin/templates/mediagoblin/listings/tag.html:35 +#, python-format +msgid "Media tagged with: %(tag_name)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:19 +msgid "Original" +msgstr "" #: mediagoblin/templates/mediagoblin/submit/start.html:26 msgid "Submit yer media" msgstr "Last opp" -#: mediagoblin/templates/mediagoblin/submit/start.html:30 -msgid "Submit" -msgstr "Send" +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 +#, python-format +msgid "%(username)s's media" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32 +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:37 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" msgstr "<a href=\"%(user_url)s\">%(username)s</a> sine mediefiler" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:32 -msgid "Sorry, no such user found." -msgstr "Fann ingen slik brukar" +#: mediagoblin/templates/mediagoblin/user_pages/media.html:57 +#, python-format +msgid "By <a href=\"%(user_url)s\">%(username)s</a> on %(date)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:67 +msgid "Post a comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:85 +msgid "at" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +msgid "Post comment!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:124 +msgid "Edit" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:130 +msgid "Delete" +msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -420,35 +449,45 @@ msgstr "Ingen media under handsaming" msgid "These uploads failed to process:" msgstr "Klarte ikkje handsama desse opplasta filene:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:39 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 +#, python-format +msgid "%(username)s's profile" +msgstr "%(username)s sin profil" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 +msgid "Sorry, no such user found." +msgstr "Fann ingen slik brukar" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 msgid "Email verification needed" msgstr "Epostverifisering trengst." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:42 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 msgid "Almost done! Your account still needs to be activated." msgstr "Nesten ferdig. Du treng berre aktivera kontoen." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 msgid "" "An email should arrive in a few moments with instructions on how to do so." msgstr "Ein epost med instruksjonar kjem straks." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:51 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 msgid "In case it doesn't:" msgstr "I tilfelle det ikkje skjer:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:54 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 msgid "Resend verification email" msgstr "Send ein ny epost" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "" "Someone has registered an account with this username, but it still has to be" " activated." msgstr "Dette brukarnamnet finst allereie, men det er ikkje aktivert." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:68 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 #, python-format msgid "" "If you are that person but you've lost your verification email, you can <a " @@ -457,40 +496,35 @@ msgstr "" "Viss dette er deg, kan du <a href=\"%(login_url)s\">logga inn</a> for Ã¥ fÃ¥ " "tilsendt ny epost med stadfestingslenkje." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:78 -#, python-format -msgid "%(username)s's profile" -msgstr "%(username)s sin profil" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:85 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 msgid "Here's a spot to tell others about yourself." msgstr "Her kan du fortelja om deg sjølv." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:108 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:101 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:119 msgid "Edit profile" msgstr "Endra profil" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:107 msgid "This user hasn't filled in their profile (yet)." msgstr "Brukaren har ikkje fylt ut profilen sin (enno)." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:122 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:133 #, python-format msgid "View all of %(username)s's media" msgstr "SjÃ¥ alle %(username)s sine mediefiler" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:135 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:146 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." -msgstr "Her kjem mediefilene dine. Ser ikkje ut til at du har lagt til noko." +msgstr "Her kjem mediefilene dine." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:152 msgid "Add media" msgstr "Legg til mediefiler" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:147 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:158 msgid "There doesn't seem to be any media here yet..." msgstr "Ser ikkje ut til at det finst nokon mediefiler her nett no." @@ -510,6 +544,18 @@ msgstr "Nyare" msgid "Older" msgstr "Eldre" +#: mediagoblin/templates/mediagoblin/utils/pagination.html:50 +msgid "Go to page:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:20 +msgid "Tagged with" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:25 +msgid "and" +msgstr "" + #: mediagoblin/user_pages/forms.py:24 msgid "Comment" msgstr "Innspel" @@ -518,15 +564,23 @@ msgstr "Innspel" msgid "I am sure I want to delete this" msgstr "Eg er sikker eg vil sletta dette" -#: mediagoblin/user_pages/views.py:142 -msgid "Empty comments are not allowed." +#: mediagoblin/user_pages/views.py:155 +msgid "Oops, your comment was empty." +msgstr "" + +#: mediagoblin/user_pages/views.py:161 +msgid "Your comment has been posted!" +msgstr "" + +#: mediagoblin/user_pages/views.py:183 +msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:148 -msgid "Comment posted!" +#: mediagoblin/user_pages/views.py:190 +msgid "The media was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:181 +#: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." msgstr "" "Du er i ferd med Ã¥ sletta ein annan brukar sine mediefiler. TrÃ¥ varsamt." diff --git a/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.mo Binary files differindex 31cb860c..87e62764 100644 --- a/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.po index 047e598b..f1c044d2 100644 --- a/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/pt_BR/LC_MESSAGES/mediagoblin.po @@ -9,9 +9,9 @@ msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" "Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n" -"POT-Creation-Date: 2011-11-01 23:14-0500\n" -"PO-Revision-Date: 2011-11-02 04:13+0000\n" -"Last-Translator: cwebber <cwebber@dustycloud.org>\n" +"POT-Creation-Date: 2011-12-04 10:24-0600\n" +"PO-Revision-Date: 2011-12-04 23:32+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" @@ -20,6 +20,10 @@ msgstr "" "Language: pt_BR\n" "Plural-Forms: nplurals=2; plural=(n > 1)\n" +#: mediagoblin/processing.py:143 +msgid "Invalid file given for media type." +msgstr "Arquivo inválido para esse tipo de mÃdia" + #: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:49 msgid "Username" msgstr "Nome de Usuário" @@ -54,8 +58,8 @@ msgid "Sorry, a user with that name already exists." msgstr "Desculpe, um usuário com este nome já existe." #: mediagoblin/auth/views.py:77 -msgid "Sorry, that email address has already been taken." -msgstr "Desculpe, esse endereço de email já está em uso." +msgid "Sorry, a user with that email address already exists." +msgstr "Desculpe, um usuário com esse email já esta cadastrado" #: mediagoblin/auth/views.py:179 msgid "" @@ -69,11 +73,19 @@ msgstr "" 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:207 +#: mediagoblin/auth/views.py:203 +msgid "You must be logged in so we know who to send the email to!" +msgstr " " + +#: mediagoblin/auth/views.py:211 +msgid "You've already verified your email address!" +msgstr "Você já verifico seu email!" + +#: mediagoblin/auth/views.py:224 msgid "Resent your verification email." msgstr "O email de verificação foi reenviado." -#: mediagoblin/auth/views.py:248 +#: mediagoblin/auth/views.py:265 msgid "" "Could not send password recovery email as your username is inactive or your " "account's email address has not been verified." @@ -89,43 +101,63 @@ msgstr "TÃtulo" msgid "Tags" msgstr "Etiquetas" -#: mediagoblin/edit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 +msgid "Seperate tags by commas." +msgstr "Separar tags por virgulas." + +#: mediagoblin/edit/forms.py:33 msgid "Slug" msgstr "Arquivo" -#: mediagoblin/edit/forms.py:32 +#: mediagoblin/edit/forms.py:34 msgid "The slug can't be empty" msgstr "O arquivo não pode estar vazio" -#: mediagoblin/edit/forms.py:33 +#: mediagoblin/edit/forms.py:35 msgid "" "The title part of this media's URL. You usually don't need to change this." msgstr "" "A parte tÃtulo da URL dessa mÃdia. Geralmente não é necessário alterar isso." -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "Bio" msgstr "Biografia" -#: mediagoblin/edit/forms.py:43 +#: mediagoblin/edit/forms.py:45 msgid "Website" msgstr "Website" -#: mediagoblin/edit/views.py:64 +#: mediagoblin/edit/forms.py:49 +msgid "Old password" +msgstr "Senha antiga" + +#: mediagoblin/edit/forms.py:52 +msgid "New Password" +msgstr "Nova Senha" + +#: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." msgstr "Uma entrada com esse arquivo já existe para esse usuário" -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:86 msgid "You are editing another user's media. Proceed with caution." msgstr "Você está editando a mÃdia de outro usuário. Tenha cuidado." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:156 msgid "You are editing a user's profile. Proceed with caution." msgstr "Você está editando um perfil de usuário. Tenha cuidado." -#: mediagoblin/process_media/errors.py:44 -msgid "Invalid file given for media type." -msgstr "Arquivo inválido para esse tipo de mÃdia" +#: mediagoblin/edit/views.py:171 +msgid "Wrong password" +msgstr "Senha errada" + +#: mediagoblin/edit/views.py:192 +msgid "Profile edited!" +msgstr "Perfil editado!" + +#: mediagoblin/media_types/__init__.py:65 +msgid "Could not find any file extension in \"{filename}\"" +msgstr " " #: mediagoblin/submit/forms.py:25 msgid "File" @@ -135,18 +167,18 @@ msgstr "Arquivo" msgid "Description of this work" msgstr "Descrição desse trabalho" -#: mediagoblin/submit/views.py:46 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "Você deve fornecer um arquivo." -#: mediagoblin/submit/views.py:49 -msgid "The file doesn't seem to be an image!" -msgstr "O arquivo não parece ser uma imagem!" - -#: mediagoblin/submit/views.py:121 +#: mediagoblin/submit/views.py:127 msgid "Woohoo! Submitted!" msgstr "Eba! Enviado!" +#: mediagoblin/submit/views.py:133 +msgid "Invalid file type." +msgstr "Tipo de arquivo inválido." + #: mediagoblin/templates/mediagoblin/404.html:21 msgid "Oops!" msgstr "Oops" @@ -167,29 +199,29 @@ msgstr "" msgid "Image of 404 goblin stressing out" msgstr "Imagem do goblin 404 aparecendo" -#: mediagoblin/templates/mediagoblin/base.html:22 -msgid "GNU MediaGoblin" -msgstr "GNU MediaGoblin" - -#: mediagoblin/templates/mediagoblin/base.html:47 +#: mediagoblin/templates/mediagoblin/base.html:49 msgid "MediaGoblin logo" msgstr "Logo MediaGoblin" -#: mediagoblin/templates/mediagoblin/base.html:52 +#: mediagoblin/templates/mediagoblin/base.html:54 msgid "Submit media" msgstr "Enviar mÃdia" -#: mediagoblin/templates/mediagoblin/base.html:63 -msgid "verify your email!" +#: mediagoblin/templates/mediagoblin/base.html:65 +msgid "Verify your email!" msgstr "Verifique seu email!" -#: mediagoblin/templates/mediagoblin/base.html:73 +#: mediagoblin/templates/mediagoblin/base.html:72 +msgid "log out" +msgstr "Sair" + +#: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 -#: mediagoblin/templates/mediagoblin/auth/login.html:35 +#: mediagoblin/templates/mediagoblin/auth/login.html:45 msgid "Log in" msgstr "Entrar" -#: mediagoblin/templates/mediagoblin/base.html:89 +#: mediagoblin/templates/mediagoblin/base.html:91 msgid "" "Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a " "href=\"http://gnu.org/\">GNU</a> project" @@ -202,71 +234,34 @@ msgid "Explore" msgstr "Explorar" #: mediagoblin/templates/mediagoblin/root.html:27 -msgid "Hi there, media lover! MediaGoblin is..." -msgstr "Olá amante de mÃdias. MediaGoblin é..." +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "Olá, bemvindo ao site de MediaGoblin." -#: mediagoblin/templates/mediagoblin/root.html:29 -msgid "The perfect place for your media!" -msgstr "O lugar perfeito para sua mÃdia!" - -#: mediagoblin/templates/mediagoblin/root.html:30 -msgid "" -"A place for people to collaborate and show off original and derived " -"creations!" -msgstr "" -"Um lugar para as pessoas colaborarem e mostrarem suas criações originais e " -"derivadas!" - -#: mediagoblin/templates/mediagoblin/root.html:31 +#: mediagoblin/templates/mediagoblin/root.html:28 msgid "" -"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project, " -"after all.)" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." msgstr "" -"Livre como a liberdade. (Afinal, somos um projeto <a " -"href=\"http://gnu.org\">GNU</a>)" -#: mediagoblin/templates/mediagoblin/root.html:32 -msgid "" -"Aiming to make the world a better place through decentralization and " -"(eventually, coming soon!) federation!" -msgstr "" -"Com o objetivo de fazer um mundo melhor através da descentralização e " -"(eventualmente, em breve) federação!" - -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "" -"Built for extensibility. (Multiple media types coming soon to the software," -" including video support!)" -msgstr "" -"ConstruÃdo para extensibilidade. (Múltiplos tipos de mÃdia em breve, " -"incluindo suporte a vÃdeo) " - -#: mediagoblin/templates/mediagoblin/root.html:34 +#: mediagoblin/templates/mediagoblin/root.html:29 msgid "" -"Powered by people like you. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve this" -" software!</a>)" -msgstr "" -"Desenvolvido por pessoas como você. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">Você pode ajudar a melhorar " -"esse software</a>)" +"To add your own media, place comments, save your favourites and more, you " +"can log in with your MediaGoblin account." +msgstr " " -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Excited to join us?" -msgstr "Animado para juntar-se a nós?" +#: mediagoblin/templates/mediagoblin/root.html:31 +msgid "Don't have one yet? It's easy!" +msgstr " " -#: mediagoblin/templates/mediagoblin/root.html:39 +#: mediagoblin/templates/mediagoblin/root.html:32 #, python-format msgid "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n" +"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" " or\n" -" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" msgstr "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\"> Crie uma conta grátis </a>\n" -" ou <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Configure seu próprio servidor MediaGoblin</a>\n" -" " -#: mediagoblin/templates/mediagoblin/root.html:53 +#: mediagoblin/templates/mediagoblin/root.html:44 msgid "Most recent media" msgstr "MÃdia mais recente" @@ -274,9 +269,18 @@ msgstr "MÃdia mais recente" msgid "Enter your new password" msgstr "Digite sua nova senha" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29 -msgid "Enter your username or email" -msgstr "Digite seu nome de usuário ou email" +#: mediagoblin/templates/mediagoblin/auth/change_fp.html:33 +#: mediagoblin/templates/mediagoblin/submit/start.html:30 +msgid "Submit" +msgstr "Enviar" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27 +msgid "Recover password" +msgstr "Recuperar senha" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 +msgid "Send instructions" +msgstr "Mandar instruções" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 msgid "Your password has been changed. Try to log in now." @@ -315,22 +319,18 @@ msgstr "" msgid "Logging in failed!" msgstr "Autenticação falhou" -#: mediagoblin/templates/mediagoblin/auth/login.html:43 +#: mediagoblin/templates/mediagoblin/auth/login.html:35 msgid "Don't have an account yet?" msgstr "Ainda não tem conta?" -#: mediagoblin/templates/mediagoblin/auth/login.html:46 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 msgid "Create one here!" msgstr "Crie uma aqui!" -#: mediagoblin/templates/mediagoblin/auth/login.html:49 +#: mediagoblin/templates/mediagoblin/auth/login.html:42 msgid "Forgot your password?" msgstr "Esqueceu sua senha?" -#: mediagoblin/templates/mediagoblin/auth/login.html:52 -msgid "Change it!" -msgstr "Altere-a" - #: mediagoblin/templates/mediagoblin/auth/register.html:27 msgid "Create an account!" msgstr "Criar uma conta!" @@ -375,27 +375,54 @@ msgstr "Salvar mudanças" msgid "Editing %(username)s's profile" msgstr "Editando perfil de %(username)s" -#: mediagoblin/templates/mediagoblin/listings/tag.html:31 -msgid "Media tagged with:" -msgstr "MÃdia marcada como:" +#: mediagoblin/templates/mediagoblin/listings/tag.html:30 +#: mediagoblin/templates/mediagoblin/listings/tag.html:35 +#, python-format +msgid "Media tagged with: %(tag_name)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:19 +msgid "Original" +msgstr "Original" #: mediagoblin/templates/mediagoblin/submit/start.html:26 msgid "Submit yer media" msgstr "Envie sua mÃdia" -#: mediagoblin/templates/mediagoblin/submit/start.html:30 -msgid "Submit" -msgstr "Enviar" +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 +#, python-format +msgid "%(username)s's media" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32 +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:37 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" msgstr "MÃdia de <a href=\"%(user_url)s\"> %(username)s </a> " -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:32 -msgid "Sorry, no such user found." -msgstr "Desculpe, esse usuário não foi encontrado." +#: mediagoblin/templates/mediagoblin/user_pages/media.html:57 +#, python-format +msgid "By <a href=\"%(user_url)s\">%(username)s</a> on %(date)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:67 +msgid "Post a comment" +msgstr "Postar um comentário" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:85 +msgid "at" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +msgid "Post comment!" +msgstr "Postar comentário!" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:124 +msgid "Edit" +msgstr "Editar" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:130 +msgid "Delete" +msgstr "Apagar" #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -428,29 +455,39 @@ msgstr "Nenhuma mÃdia em processo" msgid "These uploads failed to process:" msgstr "Esses envios não foram processados:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:39 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 +#, python-format +msgid "%(username)s's profile" +msgstr "Perfil de %(username)s" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 +msgid "Sorry, no such user found." +msgstr "Desculpe, esse usuário não foi encontrado." + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 msgid "Email verification needed" msgstr "Verificação de email necessária" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:42 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 msgid "Almost done! Your account still needs to be activated." msgstr "Quase pronto! Sua conta ainda precisa ser ativada" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 msgid "" "An email should arrive in a few moments with instructions on how to do so." msgstr "Um email deve chegar em instantes com instruções de como fazê-lo." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:51 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 msgid "In case it doesn't:" msgstr "Caso contrário:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:54 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 msgid "Resend verification email" msgstr "Reenviar email de verificação" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "" "Someone has registered an account with this username, but it still has to be" " activated." @@ -458,7 +495,7 @@ msgstr "" "Alguém registrou uma conta com esse nome de usuário, mas ainda precisa ser " "ativada." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:68 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 #, python-format msgid "" "If you are that person but you've lost your verification email, you can <a " @@ -467,30 +504,25 @@ msgstr "" "Se você é essa pessoa, mas você perdeu seu e-mail de verificação, você pode " "<a href=\"%(login_url)s\">efetuar login</a> e reenviá-la." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:78 -#, python-format -msgid "%(username)s's profile" -msgstr "Perfil de %(username)s" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:85 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 msgid "Here's a spot to tell others about yourself." msgstr "Aqui é o lugar onde você fala de si para os outros." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:108 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:101 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:119 msgid "Edit profile" msgstr "Editar perfil" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:107 msgid "This user hasn't filled in their profile (yet)." msgstr "Esse usuário não preencheu seu perfil (ainda)." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:122 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:133 #, python-format msgid "View all of %(username)s's media" msgstr "Ver todas as mÃdias de %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:135 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:146 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." @@ -498,11 +530,11 @@ msgstr "" "Aqui é onde sua mÃdia vai aparecer, mas parece que você não adicionou nada " "ainda." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:152 msgid "Add media" msgstr "Adicionar mÃdia" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:147 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:158 msgid "There doesn't seem to be any media here yet..." msgstr "Aparentemente não há nenhuma mÃdia aqui ainda..." @@ -522,6 +554,18 @@ msgstr "Mais novo" msgid "Older" msgstr "Mais velho" +#: mediagoblin/templates/mediagoblin/utils/pagination.html:50 +msgid "Go to page:" +msgstr "Ir a página:" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:20 +msgid "Tagged with" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:25 +msgid "and" +msgstr "e" + #: mediagoblin/user_pages/forms.py:24 msgid "Comment" msgstr "Comentário" @@ -530,15 +574,23 @@ msgstr "Comentário" msgid "I am sure I want to delete this" msgstr "Eu tenho certeza de que quero pagar isso" -#: mediagoblin/user_pages/views.py:142 -msgid "Empty comments are not allowed." -msgstr "" +#: mediagoblin/user_pages/views.py:155 +msgid "Oops, your comment was empty." +msgstr "Opa, seu comentáio estava vazio." + +#: mediagoblin/user_pages/views.py:161 +msgid "Your comment has been posted!" +msgstr "Seu comentário foi postado!" + +#: mediagoblin/user_pages/views.py:183 +msgid "You deleted the media." +msgstr "Você deletou a mÃdia." -#: mediagoblin/user_pages/views.py:148 -msgid "Comment posted!" +#: mediagoblin/user_pages/views.py:190 +msgid "The media was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:181 +#: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." msgstr "Você vai apagar uma mÃdia de outro usuário. Tenha cuidado." diff --git a/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.mo Binary files differindex 2ab9cf8b..e0a70ea9 100644 --- a/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.po index 01fe5c48..b747fc3a 100644 --- a/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.po @@ -4,12 +4,13 @@ # # Translators: # <gapop@hotmail.com>, 2011. +# George Pop <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-11-01 23:14-0500\n" -"PO-Revision-Date: 2011-11-02 20:49+0000\n" +"POT-Creation-Date: 2011-12-04 10:24-0600\n" +"PO-Revision-Date: 2011-12-04 18:41+0000\n" "Last-Translator: gap <gapop@hotmail.com>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" @@ -19,6 +20,10 @@ msgstr "" "Language: ro\n" "Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1))\n" +#: mediagoblin/processing.py:143 +msgid "Invalid file given for media type." +msgstr "Formatul fiÈ™ierului nu corespunde cu tipul de media selectat." + #: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:49 msgid "Username" msgstr "Nume de utilizator" @@ -52,32 +57,40 @@ 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:77 -msgid "Sorry, that email address has already been taken." -msgstr "Ne pare rău, această adresă de e-mail este deja rezervată." +msgid "Sorry, a user with that email address already exists." +msgstr "Există deja un utilizator înregistrat cu această adresă de e-mail." #: mediagoblin/auth/views.py:179 msgid "" "Your email address has been verified. You may now login, edit your profile, " "and submit images!" msgstr "" -"Adresa ta de e-mail a fost confirmată. PoÈ›i să te autentifici, să îți " +"Adresa ta de e-mail a fost verificată. PoÈ›i să te autentifici, să îți " "completezi profilul È™i să trimiÈ›i imagini!" #: mediagoblin/auth/views.py:185 msgid "The verification key or user id is incorrect" msgstr "Cheie de verificare sau user ID incorect." -#: mediagoblin/auth/views.py:207 +#: mediagoblin/auth/views.py:203 +msgid "You must be logged in so we know who to send the email to!" +msgstr "Trebuie să fii autentificat ca să È™tim cui să trimitem mesajul!" + +#: mediagoblin/auth/views.py:211 +msgid "You've already verified your email address!" +msgstr "Adresa ta de e-mail a fost deja verificată!" + +#: mediagoblin/auth/views.py:224 msgid "Resent your verification email." msgstr "E-mail-ul de verificare a fost retrimis." -#: mediagoblin/auth/views.py:248 +#: mediagoblin/auth/views.py:265 msgid "" "Could not send password recovery email as your username is inactive or your " "account's email address has not been verified." msgstr "" "E-mailul pentru recuperarea parolei nu a putut fi trimis deoarece contul tău" -" e inactiv sau adresa ta de e-mail nu a fost confirmată." +" e inactiv sau adresa ta de e-mail nu a fost verificată." #: mediagoblin/edit/forms.py:24 mediagoblin/submit/forms.py:27 msgid "Title" @@ -85,47 +98,67 @@ msgstr "Titlu" #: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:32 msgid "Tags" -msgstr "Etichete" +msgstr "Tag-uri" -#: mediagoblin/edit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 +msgid "Seperate tags by commas." +msgstr "Desparte tag-urile prin virgulă." + +#: mediagoblin/edit/forms.py:33 msgid "Slug" msgstr "Identificator" -#: mediagoblin/edit/forms.py:32 +#: mediagoblin/edit/forms.py:34 msgid "The slug can't be empty" msgstr "Identificatorul nu poate să lipsească" -#: mediagoblin/edit/forms.py:33 +#: mediagoblin/edit/forms.py:35 msgid "" "The title part of this media's URL. You usually don't need to change this." msgstr "" "Partea din adresa acestui fiÈ™ier corespunzătoare titlului. De regulă nu " "trebuie modificată." -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "Bio" msgstr "Biografie" -#: mediagoblin/edit/forms.py:43 +#: mediagoblin/edit/forms.py:45 msgid "Website" msgstr "Sit Web" -#: mediagoblin/edit/views.py:64 +#: mediagoblin/edit/forms.py:49 +msgid "Old password" +msgstr "Vechea parolă" + +#: mediagoblin/edit/forms.py:52 +msgid "New Password" +msgstr "Noua parolă" + +#: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." msgstr "" "Există deja un entry cu acelaÈ™i identificator pentru acest utilizator." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:86 msgid "You are editing another user's media. Proceed with caution." msgstr "Editezi fiÈ™ierul unui alt utilizator. Se recomandă prudență." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:156 msgid "You are editing a user's profile. Proceed with caution." msgstr "Editezi profilul unui utilizator. Se recomandă prudență." -#: mediagoblin/process_media/errors.py:44 -msgid "Invalid file given for media type." -msgstr "Formatul fiÈ™ierului nu corespunde cu tipul de media selectat." +#: mediagoblin/edit/views.py:171 +msgid "Wrong password" +msgstr "Parolă incorectă" + +#: mediagoblin/edit/views.py:192 +msgid "Profile edited!" +msgstr "Profilul a fost modificat!" + +#: mediagoblin/media_types/__init__.py:65 +msgid "Could not find any file extension in \"{filename}\"" +msgstr "Nu pot extrage extensia din „{filename}â€" #: mediagoblin/submit/forms.py:25 msgid "File" @@ -135,25 +168,25 @@ msgstr "FiÈ™ier" msgid "Description of this work" msgstr "Descrierea acestui fiÈ™ier" -#: mediagoblin/submit/views.py:46 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "Trebuie să selectezi un fiÈ™ier." -#: mediagoblin/submit/views.py:49 -msgid "The file doesn't seem to be an image!" -msgstr "FiÈ™ierul nu pare a fi o imagine!" - -#: mediagoblin/submit/views.py:121 +#: mediagoblin/submit/views.py:127 msgid "Woohoo! Submitted!" -msgstr "Gata, trimis!" +msgstr "Ura! Trimis!" + +#: mediagoblin/submit/views.py:133 +msgid "Invalid file type." +msgstr "Tip de fiÈ™ier incompatibil." #: mediagoblin/templates/mediagoblin/404.html:21 msgid "Oops!" -msgstr "Oops!" +msgstr "Hopa!" #: mediagoblin/templates/mediagoblin/404.html:24 msgid "There doesn't seem to be a page at this address. Sorry!" -msgstr "Ne pare rău, nu există nicio pagină la această adresă." +msgstr "Nu există nicio pagină la această adresă. Ne pare rău!" #: mediagoblin/templates/mediagoblin/404.html:26 msgid "" @@ -167,29 +200,29 @@ msgstr "" msgid "Image of 404 goblin stressing out" msgstr "Imagine cu elful 404 stresat." -#: mediagoblin/templates/mediagoblin/base.html:22 -msgid "GNU MediaGoblin" -msgstr "GNU MediaGoblin" - -#: mediagoblin/templates/mediagoblin/base.html:47 +#: mediagoblin/templates/mediagoblin/base.html:49 msgid "MediaGoblin logo" msgstr "logo MediaGoblin" -#: mediagoblin/templates/mediagoblin/base.html:52 +#: mediagoblin/templates/mediagoblin/base.html:54 msgid "Submit media" msgstr "Transmite un fiÈ™ier media" -#: mediagoblin/templates/mediagoblin/base.html:63 -msgid "verify your email!" -msgstr "verifică e-mail-ul!" +#: mediagoblin/templates/mediagoblin/base.html:65 +msgid "Verify your email!" +msgstr "Verifică adresa de e-mail!" + +#: mediagoblin/templates/mediagoblin/base.html:72 +msgid "log out" +msgstr "ieÈ™ire" -#: mediagoblin/templates/mediagoblin/base.html:73 +#: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 -#: mediagoblin/templates/mediagoblin/auth/login.html:35 +#: mediagoblin/templates/mediagoblin/auth/login.html:45 msgid "Log in" msgstr "Autentificare" -#: mediagoblin/templates/mediagoblin/base.html:89 +#: mediagoblin/templates/mediagoblin/base.html:91 msgid "" "Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a " "href=\"http://gnu.org/\">GNU</a> project" @@ -202,70 +235,41 @@ msgid "Explore" msgstr "Explorează" #: mediagoblin/templates/mediagoblin/root.html:27 -msgid "Hi there, media lover! MediaGoblin is..." -msgstr "Bună! MediaGoblin este..." - -#: mediagoblin/templates/mediagoblin/root.html:29 -msgid "The perfect place for your media!" -msgstr "Locul perfect pentru fiÈ™ierele tale media!" - -#: mediagoblin/templates/mediagoblin/root.html:30 -msgid "" -"A place for people to collaborate and show off original and derived " -"creations!" -msgstr "" -"Un loc unde oamenii colaborează È™i își expun creaÈ›iile originale È™i " -"derivate!" - -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "" -"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project, " -"after all.)" -msgstr "" -"Liber. (Suntem un proiect <a href=\"http://gnu.org\">GNU</a>, până la urmă.)" +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "Salut, bine ai venit pe acest site MediaGoblin!" -#: mediagoblin/templates/mediagoblin/root.html:32 +#: mediagoblin/templates/mediagoblin/root.html:28 msgid "" -"Aiming to make the world a better place through decentralization and " -"(eventually, coming soon!) federation!" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." msgstr "" -"Un pas spre o lume mai bună prin descentralizare È™i (în curând) " -"federalizare!" +"Acest site foloseÈ™te <a href=\"http://mediagoblin.org\">MediaGoblin</a>, un " +"software excepÈ›ional pentru găzduirea fiÈ™ierelor media." -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "" -"Built for extensibility. (Multiple media types coming soon to the software," -" including video support!)" -msgstr "" -"Proiectat să fie extensibil. (Software-ul va avea în curând suport pentru " -"mai multe formate de media, inclusiv pentru video!)" - -#: mediagoblin/templates/mediagoblin/root.html:34 +#: mediagoblin/templates/mediagoblin/root.html:29 msgid "" -"Powered by people like you. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve this" -" software!</a>)" +"To add your own media, place comments, save your favourites and more, you " +"can log in with your MediaGoblin account." msgstr "" -"Animat de oameni ca tine. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">Ne poÈ›i ajuta să îmbunătățim" -" acest software!</a>)" +"Ca să adăugi propriile tale fiÈ™iere, să scrii comentarii, să salvezi " +"favoritele tale È™i multe altele, autentifică-te cu contul tău MediaGoblin." -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Excited to join us?" -msgstr "Vrei să ni te alături?" +#: mediagoblin/templates/mediagoblin/root.html:31 +msgid "Don't have one yet? It's easy!" +msgstr "ÃŽncă nu ai unul? E simplu!" -#: mediagoblin/templates/mediagoblin/root.html:39 +#: mediagoblin/templates/mediagoblin/root.html:32 #, python-format msgid "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n" +"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" " or\n" -" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" msgstr "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Creează gratuit un cont</a>\n" +"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Creează un cont pe acest site</a>\n" " sau\n" -" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">instalează MediaGoblin pe serverul tău</a>" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Instalează MediaGoblin pe propriul tău server</a>" -#: mediagoblin/templates/mediagoblin/root.html:53 +#: mediagoblin/templates/mediagoblin/root.html:44 msgid "Most recent media" msgstr "Cele mai recente fiÈ™iere" @@ -273,9 +277,18 @@ msgstr "Cele mai recente fiÈ™iere" msgid "Enter your new password" msgstr "Introdu noua parolă" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29 -msgid "Enter your username or email" -msgstr "Introdu numele de utilizator sau adresa de e-mail" +#: mediagoblin/templates/mediagoblin/auth/change_fp.html:33 +#: mediagoblin/templates/mediagoblin/submit/start.html:30 +msgid "Submit" +msgstr "Trimite" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27 +msgid "Recover password" +msgstr "Recuperează parola" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 +msgid "Send instructions" +msgstr "Trimite instrucÈ›iuni" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 msgid "Your password has been changed. Try to log in now." @@ -313,22 +326,18 @@ msgstr "" msgid "Logging in failed!" msgstr "Autentificare eÈ™uată!" -#: mediagoblin/templates/mediagoblin/auth/login.html:43 +#: mediagoblin/templates/mediagoblin/auth/login.html:35 msgid "Don't have an account yet?" msgstr "Nu ai un cont?" -#: mediagoblin/templates/mediagoblin/auth/login.html:46 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 msgid "Create one here!" msgstr "Creează-l aici!" -#: mediagoblin/templates/mediagoblin/auth/login.html:49 +#: mediagoblin/templates/mediagoblin/auth/login.html:42 msgid "Forgot your password?" msgstr "Ai uitat parola?" -#: mediagoblin/templates/mediagoblin/auth/login.html:52 -msgid "Change it!" -msgstr "Schimb-o!" - #: mediagoblin/templates/mediagoblin/auth/register.html:27 msgid "Create an account!" msgstr "Creează un cont!" @@ -373,27 +382,54 @@ msgstr "Salvează modificările" msgid "Editing %(username)s's profile" msgstr "Editare profil %(username)s" -#: mediagoblin/templates/mediagoblin/listings/tag.html:31 -msgid "Media tagged with:" -msgstr "Etichete:" +#: mediagoblin/templates/mediagoblin/listings/tag.html:30 +#: mediagoblin/templates/mediagoblin/listings/tag.html:35 +#, python-format +msgid "Media tagged with: %(tag_name)s" +msgstr "FiÈ™ier etichetat cu tag-urile: %(tag_name)s" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:19 +msgid "Original" +msgstr "Original" #: mediagoblin/templates/mediagoblin/submit/start.html:26 msgid "Submit yer media" msgstr "Trimite fiÈ™ierele tale media" -#: mediagoblin/templates/mediagoblin/submit/start.html:30 -msgid "Submit" -msgstr "Trimite" +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 +#, python-format +msgid "%(username)s's media" +msgstr "FiÈ™ierele lui %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32 +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:37 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" msgstr "FiÈ™ierele media ale lui <a href=\"%(user_url)s\">%(username)s</a>" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:32 -msgid "Sorry, no such user found." -msgstr "Ne pare rău, nu am găsit utilizatorul căutat." +#: mediagoblin/templates/mediagoblin/user_pages/media.html:57 +#, python-format +msgid "By <a href=\"%(user_url)s\">%(username)s</a> on %(date)s" +msgstr "De <a href=\"%(user_url)s\">%(username)s</a> la %(date)s" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:67 +msgid "Post a comment" +msgstr "Scrie un comentariu" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:85 +msgid "at" +msgstr "la" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +msgid "Post comment!" +msgstr "Trimite comentariul" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:124 +msgid "Edit" +msgstr "Editare" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:130 +msgid "Delete" +msgstr "Șterge" #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -425,29 +461,39 @@ msgstr "Niciun fiÈ™ier în curs de procesare" msgid "These uploads failed to process:" msgstr "Aceste fiÈ™iere nu au putut fi procesate:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:39 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 +#, python-format +msgid "%(username)s's profile" +msgstr "Profil %(username)s" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 +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:50 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 msgid "Email verification needed" -msgstr "Este necesară confirmarea adresei de e-mail" +msgstr "Este necesară verificarea adresei de e-mail" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:42 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 msgid "Almost done! Your account still needs to be activated." msgstr "Aproape gata! Mai trebuie doar să activezi contul." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 msgid "" "An email should arrive in a few moments with instructions on how to do so." msgstr "Vei primi în scurt timp un e-mail cu instrucÈ›iuni." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:51 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 msgid "In case it doesn't:" msgstr "Dacă nu-l primeÈ™ti:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:54 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 msgid "Resend verification email" msgstr "Retrimite mesajul de verificare" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "" "Someone has registered an account with this username, but it still has to be" " activated." @@ -455,7 +501,7 @@ msgstr "" "Cineva a înregistrat un cont cu acest nume de utilizator, dar contul nu a " "fost încă activat." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:68 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 #, python-format msgid "" "If you are that person but you've lost your verification email, you can <a " @@ -464,30 +510,25 @@ msgstr "" "Dacă tu eÈ™ti persoana respectivă È™i nu mai ai e-mail-ul de verificare, poÈ›i " "să te <a href=\"%(login_url)s\">autentifici</a> pentru a-l retrimite." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:78 -#, python-format -msgid "%(username)s's profile" -msgstr "Profil %(username)s" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:85 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 msgid "Here's a spot to tell others about yourself." msgstr "Aici poÈ›i spune altora ceva despre tine." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:108 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:101 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:119 msgid "Edit profile" msgstr "Editare profil" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:107 msgid "This user hasn't filled in their profile (yet)." msgstr "Acest utilizator nu È™i-a completat (încă) profilul." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:122 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:133 #, python-format msgid "View all of %(username)s's media" msgstr "Vezi toate fiÈ™ierele media ale lui %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:135 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:146 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." @@ -495,11 +536,11 @@ msgstr "" "Aici vor apărea fiÈ™ierele tale media, dar se pare că încă nu ai trimis " "nimic." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:152 msgid "Add media" msgstr "Trimite fiÈ™ier" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:147 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:158 msgid "There doesn't seem to be any media here yet..." msgstr "Nu pare să existe niciun fiÈ™ier media deocamdată..." @@ -519,6 +560,18 @@ msgstr "Mai noi" msgid "Older" msgstr "Mai vechi" +#: mediagoblin/templates/mediagoblin/utils/pagination.html:50 +msgid "Go to page:" +msgstr "Salt la pagina:" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:20 +msgid "Tagged with" +msgstr "Tag-uri" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:25 +msgid "and" +msgstr "È™i" + #: mediagoblin/user_pages/forms.py:24 msgid "Comment" msgstr "Scrie un comentariu" @@ -527,15 +580,23 @@ msgstr "Scrie un comentariu" msgid "I am sure I want to delete this" msgstr "Sunt sigur că doresc să È™terg" -#: mediagoblin/user_pages/views.py:142 -msgid "Empty comments are not allowed." -msgstr "Comentariul trebuie să aibă un conÈ›inut." +#: mediagoblin/user_pages/views.py:155 +msgid "Oops, your comment was empty." +msgstr "Hopa, ai uitat să scrii comentariul." + +#: mediagoblin/user_pages/views.py:161 +msgid "Your comment has been posted!" +msgstr "Comentariul tău a fost trimis!" + +#: mediagoblin/user_pages/views.py:183 +msgid "You deleted the media." +msgstr "Ai È™ters acest fiÈ™ier" -#: mediagoblin/user_pages/views.py:148 -msgid "Comment posted!" -msgstr "Comentariul a fost transmis." +#: mediagoblin/user_pages/views.py:190 +msgid "The media was not deleted because you didn't check that you were sure." +msgstr "FiÈ™ierul nu a fost È™ters deoarece nu ai confirmat că eÈ™ti sigur." -#: mediagoblin/user_pages/views.py:181 +#: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." msgstr "" "Urmează să È™tergi fiÈ™ierele media ale unui alt utilizator. Se recomandă " diff --git a/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.mo Binary files differindex 4b5481e0..7e62de83 100644 --- a/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.po index f4bfbd67..098ea38c 100644 --- a/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" "Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n" -"POT-Creation-Date: 2011-11-01 23:14-0500\n" -"PO-Revision-Date: 2011-11-04 11:13+0000\n" +"POT-Creation-Date: 2011-12-04 10:24-0600\n" +"PO-Revision-Date: 2011-12-04 19:58+0000\n" "Last-Translator: aleksejrs <deletesoftware@yandex.ru>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" @@ -19,6 +19,10 @@ msgstr "" "Language: ru\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" +#: mediagoblin/processing.py:143 +msgid "Invalid file given for media type." +msgstr "Ðеправильный формат файла." + #: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:49 msgid "Username" msgstr "Логин" @@ -52,8 +56,10 @@ msgid "Sorry, a user with that name already exists." msgstr "Извините, пользователь Ñ Ñтим именем уже зарегиÑтрирован." #: mediagoblin/auth/views.py:77 -msgid "Sorry, that email address has already been taken." -msgstr "Извините, Ñтот Ð°Ð´Ñ€ÐµÑ Ñлектронной почты уже занÑÑ‚." +msgid "Sorry, a user with that email address already exists." +msgstr "" +"Сожалеем, но на Ñтот Ð°Ð´Ñ€ÐµÑ Ñлектронной почты уже зарегиÑтрирована Ð´Ñ€ÑƒÐ³Ð°Ñ " +"ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ." #: mediagoblin/auth/views.py:179 msgid "" @@ -67,11 +73,19 @@ msgstr "" msgid "The verification key or user id is incorrect" msgstr "Ðеверный ключ проверки или идентификатор пользователÑ" -#: mediagoblin/auth/views.py:207 +#: mediagoblin/auth/views.py:203 +msgid "You must be logged in so we know who to send the email to!" +msgstr "Вам надо предÑтавитьÑÑ, чтобы мы знали, кому отправлÑть Ñообщение!" + +#: mediagoblin/auth/views.py:211 +msgid "You've already verified your email address!" +msgstr "Ð’Ñ‹ уже потвердили Ñвой Ð°Ð´Ñ€ÐµÑ Ñлектронной почты!" + +#: mediagoblin/auth/views.py:224 msgid "Resent your verification email." msgstr "ПереÑлать Ñообщение Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸ÐµÐ¼ аккаунта." -#: mediagoblin/auth/views.py:248 +#: mediagoblin/auth/views.py:265 msgid "" "Could not send password recovery email as your username is inactive or your " "account's email address has not been verified." @@ -88,45 +102,65 @@ msgstr "Ðазвание" msgid "Tags" msgstr "Метки" -#: mediagoblin/edit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 +msgid "Seperate tags by commas." +msgstr "РазделÑйте метки запÑтыми." + +#: mediagoblin/edit/forms.py:33 msgid "Slug" msgstr "ÐžÑ‚Ð»Ð¸Ñ‡Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ñ‡Ð°Ñть адреÑа" -#: mediagoblin/edit/forms.py:32 +#: mediagoblin/edit/forms.py:34 msgid "The slug can't be empty" msgstr "ÐžÑ‚Ð»Ð¸Ñ‡Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ñ‡Ð°Ñть адреÑа необходима" -#: mediagoblin/edit/forms.py:33 +#: mediagoblin/edit/forms.py:35 msgid "" "The title part of this media's URL. You usually don't need to change this." msgstr "" "ЧаÑть адреÑа Ñтого файла, Ð¿Ñ€Ð¾Ð¸Ð·Ð²Ð¾Ð´Ð½Ð°Ñ Ð¾Ñ‚ его названиÑ. Её обычно не нужно " "изменÑть." -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "Bio" msgstr "БиографиÑ" -#: mediagoblin/edit/forms.py:43 +#: mediagoblin/edit/forms.py:45 msgid "Website" msgstr "Сайт" -#: mediagoblin/edit/views.py:64 +#: mediagoblin/edit/forms.py:49 +msgid "Old password" +msgstr "Старый пароль" + +#: mediagoblin/edit/forms.py:52 +msgid "New Password" +msgstr "Ðовый пароль" + +#: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." msgstr "" "У Ñтого Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ ÑƒÐ¶Ðµ еÑть файл Ñ Ñ‚Ð°ÐºÐ¾Ð¹ отличительной чаÑтью адреÑа." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:86 msgid "You are editing another user's media. Proceed with caution." msgstr "Ð’Ñ‹ редактируете файлы другого пользователÑ. Будьте оÑторожны." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:156 msgid "You are editing a user's profile. Proceed with caution." msgstr "Ð’Ñ‹ редактируете профиль пользователÑ. Будьте оÑторожны." -#: mediagoblin/process_media/errors.py:44 -msgid "Invalid file given for media type." -msgstr "Ðеправильный формат файла." +#: mediagoblin/edit/views.py:171 +msgid "Wrong password" +msgstr "Ðеправильный пароль" + +#: mediagoblin/edit/views.py:192 +msgid "Profile edited!" +msgstr "Профиль изменён!" + +#: mediagoblin/media_types/__init__.py:65 +msgid "Could not find any file extension in \"{filename}\"" +msgstr "Ð’ «{filename}» не обнаружено раÑширение имени файла" #: mediagoblin/submit/forms.py:25 msgid "File" @@ -136,18 +170,18 @@ msgstr "Файл" msgid "Description of this work" msgstr "ОпиÑание Ñтого произведениÑ" -#: mediagoblin/submit/views.py:46 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "Ð’Ñ‹ должны загрузить файл." -#: mediagoblin/submit/views.py:49 -msgid "The file doesn't seem to be an image!" -msgstr "Файл, похоже, не ÑвлÑетÑÑ ÐºÐ°Ñ€Ñ‚Ð¸Ð½ÐºÐ¾Ð¹!" - -#: mediagoblin/submit/views.py:121 +#: mediagoblin/submit/views.py:127 msgid "Woohoo! Submitted!" msgstr "Ура! Файл загружен!" +#: mediagoblin/submit/views.py:133 +msgid "Invalid file type." +msgstr "ÐеподходÑщий тип файла." + #: mediagoblin/templates/mediagoblin/404.html:21 msgid "Oops!" msgstr "Ой!" @@ -160,35 +194,35 @@ msgstr "КажетÑÑ, такой Ñтраницы не ÑущеÑтвует. Ð msgid "" "If you're sure the address is correct, maybe the page you're looking for has" " been moved or deleted." -msgstr "Возможно, Ñтраница которую вы ищете была удалена или переехала." +msgstr "Возможно, Ñтраница, которую вы ищете, была удалена или переехала." #: mediagoblin/templates/mediagoblin/404.html:32 msgid "Image of 404 goblin stressing out" msgstr "Изображение 404 нервничающего гоблина" -#: mediagoblin/templates/mediagoblin/base.html:22 -msgid "GNU MediaGoblin" -msgstr "GNU MediaGoblin" - -#: mediagoblin/templates/mediagoblin/base.html:47 +#: mediagoblin/templates/mediagoblin/base.html:49 msgid "MediaGoblin logo" msgstr "Символ MediaGoblin" -#: mediagoblin/templates/mediagoblin/base.html:52 +#: mediagoblin/templates/mediagoblin/base.html:54 msgid "Submit media" msgstr "Загрузить файл" -#: mediagoblin/templates/mediagoblin/base.html:63 -msgid "verify your email!" -msgstr "подтвердите ваш Ð°Ð´Ñ€ÐµÑ Ñлектронной почты!" +#: mediagoblin/templates/mediagoblin/base.html:65 +msgid "Verify your email!" +msgstr "Подтвердите ваш Ð°Ð´Ñ€ÐµÑ Ñлектронной почты!" -#: mediagoblin/templates/mediagoblin/base.html:73 +#: mediagoblin/templates/mediagoblin/base.html:72 +msgid "log out" +msgstr "завершение ÑеанÑа" + +#: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 -#: mediagoblin/templates/mediagoblin/auth/login.html:35 +#: mediagoblin/templates/mediagoblin/auth/login.html:45 msgid "Log in" msgstr "Войти" -#: mediagoblin/templates/mediagoblin/base.html:89 +#: mediagoblin/templates/mediagoblin/base.html:91 msgid "" "Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a " "href=\"http://gnu.org/\">GNU</a> project" @@ -198,69 +232,45 @@ msgstr "" #: mediagoblin/templates/mediagoblin/root.html:24 msgid "Explore" -msgstr "" +msgstr "Смотреть" #: mediagoblin/templates/mediagoblin/root.html:27 -msgid "Hi there, media lover! MediaGoblin is..." -msgstr "Привет, любитель мультимедиа! MediaGoblin…" - -#: mediagoblin/templates/mediagoblin/root.html:29 -msgid "The perfect place for your media!" -msgstr "Отличное меÑто Ð´Ð»Ñ Ð²Ð°ÑˆÐ¸Ñ… файлов!" +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "Привет! Добро пожаловать на наш MediaGoblin’овый Ñайт!" -#: mediagoblin/templates/mediagoblin/root.html:30 +#: mediagoblin/templates/mediagoblin/root.html:28 msgid "" -"A place for people to collaborate and show off original and derived " -"creations!" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." msgstr "" -"МеÑто Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, чтобы ÑовмеÑтно работать или проÑто показать Ñвои " -"оригинальные и/или заимÑтвованные ÑозданиÑ!" - -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "" -"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project, " -"after all.)" -msgstr "Свободное ПО. (Мы же проект <a href=\"http://gnu.org\">GNU</a>.)" +"Ðтот Ñайт работает на <a href=\"http://mediagoblin.org\">MediaGoblin</a>, " +"необыкновенно замечательном ПО Ð´Ð»Ñ Ñ…Ð¾Ñтинга мультимедийных файлов." -#: mediagoblin/templates/mediagoblin/root.html:32 -msgid "" -"Aiming to make the world a better place through decentralization and " -"(eventually, coming soon!) federation!" -msgstr "" -"Попытка Ñделать мир лучше Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ децентрализации и (надеемÑÑ, что Ñкоро!)" -" интеграции!" - -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "" -"Built for extensibility. (Multiple media types coming soon to the software," -" including video support!)" -msgstr "" -"РаÑÑчитан на раÑширÑемоÑть. (Ð’ программе Ñкоро должна поÑвитьÑÑ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ° " -"других видов мультимедиа, таких как видео!)" - -#: mediagoblin/templates/mediagoblin/root.html:34 +#: mediagoblin/templates/mediagoblin/root.html:29 msgid "" -"Powered by people like you. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve this" -" software!</a>)" +"To add your own media, place comments, save your favourites and more, you " +"can log in with your MediaGoblin account." msgstr "" -"ПоддерживаетÑÑ Ñ‚Ð°ÐºÐ¸Ð¼Ð¸ же, как и ты. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">Ты можешь помочь Ñделать Ñто" -" ПО лучше!</a>)" +"Ð”Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ ÑобÑтвенных файлов, комментированиÑ, Ð²ÐµÐ´ÐµÐ½Ð¸Ñ ÑпиÑка любимых " +"файлов и Ñ‚. п. вы можете предÑтавитьÑÑ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ вашей MediaGoblin’овой " +"учётной запиÑи." -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Excited to join us?" -msgstr "" +#: mediagoblin/templates/mediagoblin/root.html:31 +msgid "Don't have one yet? It's easy!" +msgstr "У Ð²Ð°Ñ ÐµÑ‘ ещё нет? Ðе проблема!" -#: mediagoblin/templates/mediagoblin/root.html:39 +#: mediagoblin/templates/mediagoblin/root.html:32 #, python-format msgid "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n" +"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" " or\n" -" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" msgstr "" +"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Создайте учётную запиÑÑŒ на Ñтом Ñайте</a>\n" +" или\n" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">УÑтановите MediaGoblin на ÑобÑтвенный Ñервер</a>" -#: mediagoblin/templates/mediagoblin/root.html:53 +#: mediagoblin/templates/mediagoblin/root.html:44 msgid "Most recent media" msgstr "Самые новые файлы" @@ -268,18 +278,29 @@ msgstr "Самые новые файлы" msgid "Enter your new password" msgstr "Введите Ñвой новый пароль" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29 -msgid "Enter your username or email" -msgstr "Введите Ваше Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ Ð°Ð´Ñ€ÐµÑ Ñлектронной почты" +#: mediagoblin/templates/mediagoblin/auth/change_fp.html:33 +#: mediagoblin/templates/mediagoblin/submit/start.html:30 +msgid "Submit" +msgstr "Подтвердить" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27 +msgid "Recover password" +msgstr "Ð¡Ð±Ñ€Ð¾Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 +msgid "Send instructions" +msgstr "Отправить инÑтрукцию" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 msgid "Your password has been changed. Try to log in now." -msgstr "" +msgstr "Ваш пароль изменён. Теперь попробуйте предÑтавитьÑÑ." #: mediagoblin/templates/mediagoblin/auth/fp_email_sent.html:22 msgid "" "Check your inbox. We sent an email with a URL for changing your password." msgstr "" +"Проверьте Ñвой Ñлектронный почтовый Ñщик. Мы отправили Ñообщение Ñ Ð°Ð´Ñ€ÐµÑом " +"Ð´Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð’Ð°ÑˆÐµÐ³Ð¾ паролÑ." #: mediagoblin/templates/mediagoblin/auth/fp_verification_email.txt:19 #, python-format @@ -294,27 +315,32 @@ msgid "" "If you think this is an error, just ignore this email and continue being\n" "a happy goblin!" msgstr "" +"Привет, %(username)s,\n" +"\n" +"чтобы Ñменить Ñвой пароль от GNU MediaGoblin, откройте\n" +"Ñледующий URL вашим вебâ€Ð±Ñ€Ð°ÑƒÐ·ÐµÑ€Ð¾Ð¼:\n" +"\n" +"%(verification_url)s\n" +"\n" +"ЕÑли вы думаете, что Ñто какаÑâ€Ñ‚о ошибка, то игнорируйте\n" +"Ñто Ñообщение и продолжайте быть ÑчаÑтливым гоблином!" #: mediagoblin/templates/mediagoblin/auth/login.html:30 msgid "Logging in failed!" msgstr "ÐÐ²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð½ÐµÑƒÑпешна!" -#: mediagoblin/templates/mediagoblin/auth/login.html:43 +#: mediagoblin/templates/mediagoblin/auth/login.html:35 msgid "Don't have an account yet?" msgstr "Ещё нету аккаунта?" -#: mediagoblin/templates/mediagoblin/auth/login.html:46 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 msgid "Create one here!" msgstr "Создайте здеÑÑŒ!" -#: mediagoblin/templates/mediagoblin/auth/login.html:49 +#: mediagoblin/templates/mediagoblin/auth/login.html:42 msgid "Forgot your password?" msgstr "Забыли Ñвой пароль?" -#: mediagoblin/templates/mediagoblin/auth/login.html:52 -msgid "Change it!" -msgstr "Смените его!" - #: mediagoblin/templates/mediagoblin/auth/register.html:27 msgid "Create an account!" msgstr "Создать аккаунт!" @@ -359,27 +385,54 @@ msgstr "Сохранить изменениÑ" msgid "Editing %(username)s's profile" msgstr "Редактирование Ð¿Ñ€Ð¾Ñ„Ð¸Ð»Ñ %(username)s" -#: mediagoblin/templates/mediagoblin/listings/tag.html:31 -msgid "Media tagged with:" -msgstr "Файлы Ñ Ð¼ÐµÑ‚ÐºÐ¾Ð¹:" +#: mediagoblin/templates/mediagoblin/listings/tag.html:30 +#: mediagoblin/templates/mediagoblin/listings/tag.html:35 +#, python-format +msgid "Media tagged with: %(tag_name)s" +msgstr "Файлы Ñ Ð¼ÐµÑ‚ÐºÐ¾Ð¹: %(tag_name)s" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:19 +msgid "Original" +msgstr "Оригинал" #: mediagoblin/templates/mediagoblin/submit/start.html:26 msgid "Submit yer media" msgstr "Загрузить файл(Ñ‹)" -#: mediagoblin/templates/mediagoblin/submit/start.html:30 -msgid "Submit" -msgstr "Подтвердить" +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 +#, python-format +msgid "%(username)s's media" +msgstr "Файлы %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32 +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:37 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" msgstr "Файлы Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ <a href=\"%(user_url)s\">%(username)s</a>" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:32 -msgid "Sorry, no such user found." -msgstr "Извините, но такой пользователь не найден." +#: mediagoblin/templates/mediagoblin/user_pages/media.html:57 +#, python-format +msgid "By <a href=\"%(user_url)s\">%(username)s</a> on %(date)s" +msgstr "Загружено <a href=\"%(user_url)s\">%(username)s</a> %(date)s" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:67 +msgid "Post a comment" +msgstr "ОÑтавить комментарий" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:85 +msgid "at" +msgstr "в" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +msgid "Post comment!" +msgstr "РазмеÑтить комментарий!" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:124 +msgid "Edit" +msgstr "Изменить" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:130 +msgid "Delete" +msgstr "Удалить" #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -412,38 +465,48 @@ msgstr "Ðету файлов Ð´Ð»Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸" msgid "These uploads failed to process:" msgstr "Обработка Ñтих файлов вызвала ошибку:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:39 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 +#, python-format +msgid "%(username)s's profile" +msgstr "Профиль Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %(username)s" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 +msgid "Sorry, no such user found." +msgstr "Извините, но такой пользователь не найден." + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 msgid "Email verification needed" msgstr "Ðужно подтверждение почтового адреÑа" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:42 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 msgid "Almost done! Your account still needs to be activated." msgstr "Почти закончили! Теперь надо активировать ваш аккаунт." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 msgid "" "An email should arrive in a few moments with instructions on how to do so." msgstr "" "Через пару мгновений на Ð°Ð´Ñ€ÐµÑ Ð²Ð°ÑˆÐµÐ¹ Ñлектронной почты должно прийти " "Ñообщение Ñ Ð´Ð°Ð»ÑŒÐ½ÐµÐ¹ÑˆÐ¸Ð¼Ð¸ инÑтрукциÑми." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:51 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 msgid "In case it doesn't:" msgstr "РеÑли нет, то:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:54 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 msgid "Resend verification email" msgstr "" "Повторно отправить Ñообщение Ð´Ð»Ñ Ð¿Ð¾Ð´Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð°Ð´Ñ€ÐµÑа Ñлектронной почты" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "" "Someone has registered an account with this username, but it still has to be" " activated." msgstr "Ктоâ€Ñ‚о Ñоздал аккаунт Ñ Ñтим именем, но его еще надо активировать." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:68 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 #, python-format msgid "" "If you are that person but you've lost your verification email, you can <a " @@ -452,40 +515,35 @@ msgstr "" "ЕÑли Ñто были вы, и еÑли вы потерÑли Ñообщение Ð´Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð°ÐºÐºÐ°ÑƒÐ½Ñ‚Ð°, " "то вы можете <a href=\"%(login_url)s\">войти</a> и отправить его повторно." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:78 -#, python-format -msgid "%(username)s's profile" -msgstr "Профиль Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %(username)s" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:85 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 msgid "Here's a spot to tell others about yourself." msgstr "ЗдеÑÑŒ вы можете раÑÑказать о Ñебе." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:108 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:101 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:119 msgid "Edit profile" msgstr "Редактировать профиль" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:107 msgid "This user hasn't filled in their profile (yet)." msgstr "Ðто пользователь не заполнил Ñвой профайл (пока)." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:122 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:133 #, python-format msgid "View all of %(username)s's media" msgstr "Смотреть вÑе файлы %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:135 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:146 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "Ваши файлы поÑвÑÑ‚ÑÑ Ð·Ð´ÐµÑÑŒ, когда вы их добавите." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:152 msgid "Add media" msgstr "Добавить файлы" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:147 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:158 msgid "There doesn't seem to be any media here yet..." msgstr "Пока что тут файлов нет…" @@ -505,6 +563,18 @@ msgstr "Более новые" msgid "Older" msgstr "Более Ñтарые" +#: mediagoblin/templates/mediagoblin/utils/pagination.html:50 +msgid "Go to page:" +msgstr "Перейти к Ñтранице:" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:20 +msgid "Tagged with" +msgstr "Метки:" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:25 +msgid "and" +msgstr "и" + #: mediagoblin/user_pages/forms.py:24 msgid "Comment" msgstr "Комментарий" @@ -513,15 +583,23 @@ msgstr "Комментарий" msgid "I am sure I want to delete this" msgstr "Я уверен, что хочу удалить Ñто" -#: mediagoblin/user_pages/views.py:142 -msgid "Empty comments are not allowed." -msgstr "Empty comments are not allowed." +#: mediagoblin/user_pages/views.py:155 +msgid "Oops, your comment was empty." +msgstr "Ой, ваш комментарий был пуÑÑ‚." -#: mediagoblin/user_pages/views.py:148 -msgid "Comment posted!" -msgstr "" +#: mediagoblin/user_pages/views.py:161 +msgid "Your comment has been posted!" +msgstr "Ваш комментарий размещён!" + +#: mediagoblin/user_pages/views.py:183 +msgid "You deleted the media." +msgstr "Ð’Ñ‹ удалили файл." + +#: mediagoblin/user_pages/views.py:190 +msgid "The media was not deleted because you didn't check that you were sure." +msgstr "Файл не удалён, так как вы не подтвердили Ñвою уверенноÑть галочкой." -#: mediagoblin/user_pages/views.py:181 +#: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." msgstr "Ð’Ñ‹ на пороге ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° другого пользователÑ. Будьте оÑторожны." diff --git a/mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.mo Binary files differindex 684c850a..5ab7befa 100644 --- a/mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.po index d3196b9c..34cf1679 100644 --- a/mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/sk/LC_MESSAGES/mediagoblin.po @@ -8,9 +8,9 @@ msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" "Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n" -"POT-Creation-Date: 2011-11-01 23:14-0500\n" -"PO-Revision-Date: 2011-11-02 04:13+0000\n" -"Last-Translator: cwebber <cwebber@dustycloud.org>\n" +"POT-Creation-Date: 2011-12-04 10:24-0600\n" +"PO-Revision-Date: 2011-12-10 23:09+0000\n" +"Last-Translator: martin <zatroch.martin@gmail.com>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -19,6 +19,10 @@ msgstr "" "Language: sk\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2\n" +#: mediagoblin/processing.py:143 +msgid "Invalid file given for media type." +msgstr "Odovzdaný nesprávny súbor pre daný typ média." + #: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:49 msgid "Username" msgstr "Prihlasovacie meno" @@ -52,8 +56,8 @@ msgid "Sorry, a user with that name already exists." msgstr "PrepáÄ, rovnaké prihlasovacie meno už niekto použÃva." #: mediagoblin/auth/views.py:77 -msgid "Sorry, that email address has already been taken." -msgstr "PrepáÄ, daná e-mailová adresa už bola pri registrácii využitá." +msgid "Sorry, a user with that email address already exists." +msgstr "PrepáÄ, použÃvateľ s rovnakou e-mailovou adresou už existuje." #: mediagoblin/auth/views.py:179 msgid "" @@ -67,11 +71,19 @@ msgstr "" msgid "The verification key or user id is incorrect" msgstr "Nesprávny overovacà kÄ¾ÃºÄ alebo použÃvateľské ID" -#: mediagoblin/auth/views.py:207 +#: mediagoblin/auth/views.py:203 +msgid "You must be logged in so we know who to send the email to!" +msgstr "Aby sme ti mohli zaslaÅ¥ e-mail, je potrebné byÅ¥ prihláseným!" + +#: mediagoblin/auth/views.py:211 +msgid "You've already verified your email address!" +msgstr "Tvoja e-mailová adresa už bola raz overená!" + +#: mediagoblin/auth/views.py:224 msgid "Resent your verification email." msgstr "Opätovne zaslaÅ¥ overovaciu správu." -#: mediagoblin/auth/views.py:248 +#: mediagoblin/auth/views.py:265 msgid "" "Could not send password recovery email as your username is inactive or your " "account's email address has not been verified." @@ -87,42 +99,62 @@ msgstr "Nadpis" msgid "Tags" msgstr "Å tÃtky" -#: mediagoblin/edit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 +msgid "Seperate tags by commas." +msgstr "Oddeľ Å¡tÃtky pomocou Äiarky." + +#: mediagoblin/edit/forms.py:33 msgid "Slug" msgstr "Unikátna ÄasÅ¥ adresy" -#: mediagoblin/edit/forms.py:32 +#: mediagoblin/edit/forms.py:34 msgid "The slug can't be empty" msgstr "Unikátna ÄasÅ¥ adresy musà byÅ¥ vyplnená" -#: mediagoblin/edit/forms.py:33 +#: mediagoblin/edit/forms.py:35 msgid "" "The title part of this media's URL. You usually don't need to change this." msgstr "Titulná ÄasÅ¥ URL odkazu média. ZvyÄajne to meniÅ¥ nemusÃÅ¡." -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "Bio" msgstr "Bio" -#: mediagoblin/edit/forms.py:43 +#: mediagoblin/edit/forms.py:45 msgid "Website" msgstr "Webstránka" -#: mediagoblin/edit/views.py:64 +#: mediagoblin/edit/forms.py:49 +msgid "Old password" +msgstr "Staré heslo" + +#: mediagoblin/edit/forms.py:52 +msgid "New Password" +msgstr "Nové heslo" + +#: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." msgstr "Položku s rovnakou unikátnou ÄasÅ¥ou adresy už niekde máš." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:86 msgid "You are editing another user's media. Proceed with caution." msgstr "UpravujeÅ¡ médiá niekoho iného. Pristupuj opatrne." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:156 msgid "You are editing a user's profile. Proceed with caution." msgstr "UpravujeÅ¡ použÃvateľský profil. Pristupuj opatrne." -#: mediagoblin/process_media/errors.py:44 -msgid "Invalid file given for media type." -msgstr "Odovzdaný nesprávny súbor pre daný typ média." +#: mediagoblin/edit/views.py:171 +msgid "Wrong password" +msgstr "Nesprávne heslo" + +#: mediagoblin/edit/views.py:192 +msgid "Profile edited!" +msgstr "Profil upravený!" + +#: mediagoblin/media_types/__init__.py:65 +msgid "Could not find any file extension in \"{filename}\"" +msgstr "Nebolo možné nájsÅ¥ žiadnu prÃponu v súbore \"{filename}\"" #: mediagoblin/submit/forms.py:25 msgid "File" @@ -132,18 +164,18 @@ msgstr "Súbor" msgid "Description of this work" msgstr "Charakteristika diela" -#: mediagoblin/submit/views.py:46 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "Poskytni súbor." -#: mediagoblin/submit/views.py:49 -msgid "The file doesn't seem to be an image!" -msgstr "Súbor najskôr nie je obrázkom!" - -#: mediagoblin/submit/views.py:121 +#: mediagoblin/submit/views.py:127 msgid "Woohoo! Submitted!" msgstr "Juchú! ÚspeÅ¡ne vložené!" +#: mediagoblin/submit/views.py:133 +msgid "Invalid file type." +msgstr "Nesprávny typ súboru." + #: mediagoblin/templates/mediagoblin/404.html:21 msgid "Oops!" msgstr "Ajaj!" @@ -164,29 +196,29 @@ msgstr "" msgid "Image of 404 goblin stressing out" msgstr "Obrázok stresujúceho goblina pri chybovom kóde Ä. 404" -#: mediagoblin/templates/mediagoblin/base.html:22 -msgid "GNU MediaGoblin" -msgstr "GNU MediaGoblin" - -#: mediagoblin/templates/mediagoblin/base.html:47 +#: mediagoblin/templates/mediagoblin/base.html:49 msgid "MediaGoblin logo" msgstr "MediaGoblin logo" -#: mediagoblin/templates/mediagoblin/base.html:52 +#: mediagoblin/templates/mediagoblin/base.html:54 msgid "Submit media" msgstr "VložiÅ¥ výtvor" -#: mediagoblin/templates/mediagoblin/base.html:63 -msgid "verify your email!" -msgstr "over si svoj e-mail!" +#: mediagoblin/templates/mediagoblin/base.html:65 +msgid "Verify your email!" +msgstr "Over si e-mail!" + +#: mediagoblin/templates/mediagoblin/base.html:72 +msgid "log out" +msgstr "odhlásenie" -#: mediagoblin/templates/mediagoblin/base.html:73 +#: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 -#: mediagoblin/templates/mediagoblin/auth/login.html:35 +#: mediagoblin/templates/mediagoblin/auth/login.html:45 msgid "Log in" msgstr "Prihlásenie" -#: mediagoblin/templates/mediagoblin/base.html:89 +#: mediagoblin/templates/mediagoblin/base.html:91 msgid "" "Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a " "href=\"http://gnu.org/\">GNU</a> project" @@ -199,71 +231,41 @@ msgid "Explore" msgstr "PreskúmaÅ¥" #: mediagoblin/templates/mediagoblin/root.html:27 -msgid "Hi there, media lover! MediaGoblin is..." -msgstr "Vitaj medzi nami, kreatÃvne stvorenie! MediaGoblin je..." - -#: mediagoblin/templates/mediagoblin/root.html:29 -msgid "The perfect place for your media!" -msgstr "Parádne miesto pre tvoje výtvory!" - -#: mediagoblin/templates/mediagoblin/root.html:30 -msgid "" -"A place for people to collaborate and show off original and derived " -"creations!" -msgstr "" -"Miesto pre ľudÃ, vhodné na spoluprácu a vystavovanie tak originálnych, ako " -"aj odvodených kreáciÃ!" - -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "" -"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project, " -"after all.)" -msgstr "" -"Voľné, vo význame slobody. (Koniec-koncov, sme predsa <a " -"href=\"http://gnu.org\">GNU</a> projekt.)" +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "Ahoj, vitaj na tejto MediaGoblin stránke!" -#: mediagoblin/templates/mediagoblin/root.html:32 +#: mediagoblin/templates/mediagoblin/root.html:28 msgid "" -"Aiming to make the world a better place through decentralization and " -"(eventually, coming soon!) federation!" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." msgstr "" -"Zo snahou spraviÅ¥ svet lepÅ¡Ãm miestom vÄaka decentralizácii a (eventuálne, " -"už Äoskoro!) federácii!" +"Táto stránka použÃva <a href=\"http://mediagoblin.org\">MediaGoblin</a>, " +"výnimoÄne skvelý kus softvéru na hostovanie médiÃ." -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "" -"Built for extensibility. (Multiple media types coming soon to the software," -" including video support!)" -msgstr "" -"S dôrazom na rozÅ¡ÃriteľnosÅ¥. (Podpora pre rozliÄné typy médià v tomto " -"softvéri už Äoskoro, nevynÃmajúc videá!)" - -#: mediagoblin/templates/mediagoblin/root.html:34 +#: mediagoblin/templates/mediagoblin/root.html:29 msgid "" -"Powered by people like you. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve this" -" software!</a>)" +"To add your own media, place comments, save your favourites and more, you " +"can log in with your MediaGoblin account." msgstr "" -"Existujeme aj vÄaka ľudom ako si ty. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">MôžeÅ¡ nám pomôcÅ¥ softvér " -"vylepÅ¡iÅ¥!</a>)" +"Pre pridanie vlastných výtvorov, vloženie komentárov, uloženie svojich " +"obľúbených položiek a viac, sa musÃÅ¡ prihlásiÅ¥ so svojim MediaGoblin úÄtom." -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Excited to join us?" -msgstr "Tak Äo, chceÅ¡ sa pridaÅ¥?" +#: mediagoblin/templates/mediagoblin/root.html:31 +msgid "Don't have one yet? It's easy!" +msgstr "EÅ¡te žiaden nemáš? Je to jednoduché!" -#: mediagoblin/templates/mediagoblin/root.html:39 +#: mediagoblin/templates/mediagoblin/root.html:32 #, python-format msgid "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n" +"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" " or\n" -" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" msgstr "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">VytvoriÅ¥ bezplatný úÄet</a>\n" +"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">VytvoriÅ¥ bezplatný úÄet</a>\n" " alebo\n" -" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">SprevádzkovaÅ¥ MediaGoblin na vlastnom serveri</a>" +" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">SprevádzkovaÅ¥ MediaGoblin na vlastnom serveri</a>" -#: mediagoblin/templates/mediagoblin/root.html:53 +#: mediagoblin/templates/mediagoblin/root.html:44 msgid "Most recent media" msgstr "NajÄerstvejÅ¡ie výtvory" @@ -271,9 +273,18 @@ msgstr "NajÄerstvejÅ¡ie výtvory" msgid "Enter your new password" msgstr "Vlož svoje nové heslo" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29 -msgid "Enter your username or email" -msgstr "Vlož svoje použÃvateľské meno alebo e-mailovú adresu" +#: mediagoblin/templates/mediagoblin/auth/change_fp.html:33 +#: mediagoblin/templates/mediagoblin/submit/start.html:30 +msgid "Submit" +msgstr "VložiÅ¥" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27 +msgid "Recover password" +msgstr "ObnoviÅ¥ heslo" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 +msgid "Send instructions" +msgstr "ZaslaÅ¥ inÅ¡trukcie" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 msgid "Your password has been changed. Try to log in now." @@ -312,22 +323,18 @@ msgstr "" msgid "Logging in failed!" msgstr "Prihlásenie zlyhalo!" -#: mediagoblin/templates/mediagoblin/auth/login.html:43 +#: mediagoblin/templates/mediagoblin/auth/login.html:35 msgid "Don't have an account yet?" msgstr "EÅ¡te nemáš úÄet?" -#: mediagoblin/templates/mediagoblin/auth/login.html:46 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 msgid "Create one here!" msgstr "VytvoriÅ¥ jeden tu!" -#: mediagoblin/templates/mediagoblin/auth/login.html:49 +#: mediagoblin/templates/mediagoblin/auth/login.html:42 msgid "Forgot your password?" msgstr "Zabudnuté heslo?" -#: mediagoblin/templates/mediagoblin/auth/login.html:52 -msgid "Change it!" -msgstr "ZmeniÅ¥ ho!" - #: mediagoblin/templates/mediagoblin/auth/register.html:27 msgid "Create an account!" msgstr "VytvoriÅ¥ úÄet!" @@ -373,27 +380,54 @@ msgstr "UložiÅ¥ zmeny" msgid "Editing %(username)s's profile" msgstr "Úprava profilu, ktorý vlastnà %(username)s" -#: mediagoblin/templates/mediagoblin/listings/tag.html:31 -msgid "Media tagged with:" -msgstr "Výtvor znaÄený Å¡tÃtkami:" +#: mediagoblin/templates/mediagoblin/listings/tag.html:30 +#: mediagoblin/templates/mediagoblin/listings/tag.html:35 +#, python-format +msgid "Media tagged with: %(tag_name)s" +msgstr "Výtvory oznaÄené s: %(tag_name)s" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:19 +msgid "Original" +msgstr "Originál" #: mediagoblin/templates/mediagoblin/submit/start.html:26 msgid "Submit yer media" msgstr "Vlož svoj výtvor" -#: mediagoblin/templates/mediagoblin/submit/start.html:30 -msgid "Submit" -msgstr "VložiÅ¥" +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 +#, python-format +msgid "%(username)s's media" +msgstr "Výtvory použÃvateľa %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32 +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:37 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" msgstr "<a href=\"%(user_url)s\">Výtvory, ktoré vlastnà %(username)s</a>" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:32 -msgid "Sorry, no such user found." -msgstr "PrepáÄ, použÃvateľské meno nenájdené." +#: mediagoblin/templates/mediagoblin/user_pages/media.html:57 +#, python-format +msgid "By <a href=\"%(user_url)s\">%(username)s</a> on %(date)s" +msgstr "Od <a href=\"%(user_url)s\">%(username)s</a> v Äase %(date)s" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:67 +msgid "Post a comment" +msgstr "ZaslaÅ¥ komentár" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:85 +msgid "at" +msgstr "o" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +msgid "Post comment!" +msgstr "ZaslaÅ¥ komentár!" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:124 +msgid "Edit" +msgstr "UpraviÅ¥" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:130 +msgid "Delete" +msgstr "OdstrániÅ¥" #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -425,29 +459,39 @@ msgstr "Žiadne médiá v procese spracovania" msgid "These uploads failed to process:" msgstr "Nasledovné vloženia nepreÅ¡li spracovanÃm:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:39 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 +#, python-format +msgid "%(username)s's profile" +msgstr "Profil, ktorý vlastnà %(username)s" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 +msgid "Sorry, no such user found." +msgstr "PrepáÄ, použÃvateľské meno nenájdené." + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 msgid "Email verification needed" msgstr "Potrebné overenie e-mailovej adresy" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:42 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 msgid "Almost done! Your account still needs to be activated." msgstr "Takmer hotovo! EÅ¡te ti musà byÅ¥ aktivovaný úÄet." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 msgid "" "An email should arrive in a few moments with instructions on how to do so." msgstr "E-mailová správa s popisom ako to spraviÅ¥, by mala onedlho doraziÅ¥." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:51 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 msgid "In case it doesn't:" msgstr "V prÃpade, že sa tak nestalo:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:54 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 msgid "Resend verification email" msgstr "Opätovne zaslaÅ¥ overovaciu správu" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "" "Someone has registered an account with this username, but it still has to be" " activated." @@ -455,7 +499,7 @@ msgstr "" "ÚÄet s týmto prihlasovacÃm menom je už registrovaný, avÅ¡ak eÅ¡te stále " "neaktÃvny." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:68 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 #, python-format msgid "" "If you are that person but you've lost your verification email, you can <a " @@ -464,41 +508,36 @@ msgstr "" "Pokiaľ si to ty, ale už nemáš overovaciu správu, tak sa môžeÅ¡ <a " "href=\"%(login_url)s\">prihlásiÅ¥</a> a preposlaÅ¥ si ju." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:78 -#, python-format -msgid "%(username)s's profile" -msgstr "Profil, ktorý vlastnà %(username)s" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:85 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 msgid "Here's a spot to tell others about yourself." msgstr "Povedz tu o sebe ostatným." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:108 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:101 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:119 msgid "Edit profile" msgstr "UpraviÅ¥ profil" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:107 msgid "This user hasn't filled in their profile (yet)." msgstr "DotyÄná osoba eÅ¡te nevyplnila svoj profil (zatiaľ)." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:122 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:133 #, python-format msgid "View all of %(username)s's media" msgstr "ZhliadnuÅ¥ vÅ¡etky výtvory, ktoré vlastnà %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:135 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:146 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "" "VÅ¡etky tvoje výtvory sa objavia práve tu, ale zatiaľ nemáš niÄ pridané." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:152 msgid "Add media" msgstr "PridaÅ¥ výtvor" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:147 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:158 msgid "There doesn't seem to be any media here yet..." msgstr "Najskôr tu eÅ¡te nebudú žiadne výtvory..." @@ -518,6 +557,18 @@ msgstr "NovÅ¡ie" msgid "Older" msgstr "StarÅ¡ie" +#: mediagoblin/templates/mediagoblin/utils/pagination.html:50 +msgid "Go to page:" +msgstr "ÃsÅ¥ na stránku:" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:20 +msgid "Tagged with" +msgstr "OznaÄené s" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:25 +msgid "and" +msgstr "a" + #: mediagoblin/user_pages/forms.py:24 msgid "Comment" msgstr "Komentár" @@ -526,15 +577,23 @@ msgstr "Komentár" msgid "I am sure I want to delete this" msgstr "JednoznaÄne to chcem odstrániÅ¥" -#: mediagoblin/user_pages/views.py:142 -msgid "Empty comments are not allowed." -msgstr "" +#: mediagoblin/user_pages/views.py:155 +msgid "Oops, your comment was empty." +msgstr "Ajaj, tvoj komentár bol prázdny." -#: mediagoblin/user_pages/views.py:148 -msgid "Comment posted!" -msgstr "" +#: mediagoblin/user_pages/views.py:161 +msgid "Your comment has been posted!" +msgstr "Tvoj komentár bol zaslaný!" + +#: mediagoblin/user_pages/views.py:183 +msgid "You deleted the media." +msgstr "Výtvor bol odstránený tebou." + +#: mediagoblin/user_pages/views.py:190 +msgid "The media was not deleted because you didn't check that you were sure." +msgstr "Výtvor nebol odstránený, nakoľko chýbala tvoja konfirmácia." -#: mediagoblin/user_pages/views.py:181 +#: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." msgstr "Chystáš sa odstrániÅ¥ výtvory niekoho iného. Pristupuj opatrne." diff --git a/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.mo Binary files differindex 52e3d632..9ad54a83 100644 --- a/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.po index cba4fdd0..ffd2c04c 100644 --- a/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/sl/LC_MESSAGES/mediagoblin.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" "Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n" -"POT-Creation-Date: 2011-11-01 23:14-0500\n" -"PO-Revision-Date: 2011-11-02 04:13+0000\n" +"POT-Creation-Date: 2011-12-04 10:24-0600\n" +"PO-Revision-Date: 2011-12-04 16:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" @@ -19,6 +19,10 @@ msgstr "" "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/processing.py:143 +msgid "Invalid file given for media type." +msgstr "Za vrsto vsebine je bila podana napaÄna datoteka." + #: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:49 msgid "Username" msgstr "UporabniÅ¡ko ime" @@ -52,8 +56,8 @@ msgid "Sorry, a user with that name already exists." msgstr "Oprostite, uporabnik s tem imenom že obstaja." #: mediagoblin/auth/views.py:77 -msgid "Sorry, that email address has already been taken." -msgstr "Oprostite, ta e-poÅ¡tni naslov je že v uporabi." +msgid "Sorry, a user with that email address already exists." +msgstr "" #: mediagoblin/auth/views.py:179 msgid "" @@ -67,11 +71,19 @@ msgstr "" msgid "The verification key or user id is incorrect" msgstr "Potrditveni kljuÄ ali uporabniÅ¡ka identifikacija je napaÄna" -#: mediagoblin/auth/views.py:207 +#: mediagoblin/auth/views.py:203 +msgid "You must be logged in so we know who to send the email to!" +msgstr "" + +#: mediagoblin/auth/views.py:211 +msgid "You've already verified your email address!" +msgstr "" + +#: mediagoblin/auth/views.py:224 msgid "Resent your verification email." msgstr "Ponovno poÅ¡iljanje potrditvene e-poÅ¡te." -#: mediagoblin/auth/views.py:248 +#: mediagoblin/auth/views.py:265 msgid "" "Could not send password recovery email as your username is inactive or your " "account's email address has not been verified." @@ -85,42 +97,62 @@ msgstr "Naslov" msgid "Tags" msgstr "Oznake" -#: mediagoblin/edit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 +msgid "Seperate tags by commas." +msgstr "" + +#: mediagoblin/edit/forms.py:33 msgid "Slug" msgstr "Oznaka" -#: mediagoblin/edit/forms.py:32 +#: mediagoblin/edit/forms.py:34 msgid "The slug can't be empty" msgstr "Oznaka ne sme biti prazna" -#: mediagoblin/edit/forms.py:33 +#: mediagoblin/edit/forms.py:35 msgid "" "The title part of this media's URL. You usually don't need to change this." msgstr "" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "Bio" msgstr "Biografija" -#: mediagoblin/edit/forms.py:43 +#: mediagoblin/edit/forms.py:45 msgid "Website" msgstr "Spletna stran" -#: mediagoblin/edit/views.py:64 +#: mediagoblin/edit/forms.py:49 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:52 +msgid "New Password" +msgstr "" + +#: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." msgstr "Vnos s to oznako za tega uporabnika že obstaja." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:86 msgid "You are editing another user's media. Proceed with caution." msgstr "Urejate vsebino drugega uporabnika. Nadaljujte pazljivo." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:156 msgid "You are editing a user's profile. Proceed with caution." msgstr "Urejate uporabniÅ¡ki profil. Nadaljujte pazljivo." -#: mediagoblin/process_media/errors.py:44 -msgid "Invalid file given for media type." -msgstr "Za vrsto vsebine je bila podana napaÄna datoteka." +#: mediagoblin/edit/views.py:171 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/edit/views.py:192 +msgid "Profile edited!" +msgstr "" + +#: mediagoblin/media_types/__init__.py:65 +msgid "Could not find any file extension in \"{filename}\"" +msgstr "" #: mediagoblin/submit/forms.py:25 msgid "File" @@ -130,18 +162,18 @@ msgstr "Datoteka" msgid "Description of this work" msgstr "" -#: mediagoblin/submit/views.py:46 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "Podati morate datoteko." -#: mediagoblin/submit/views.py:49 -msgid "The file doesn't seem to be an image!" -msgstr "Kot kaže datoteka ni slika." - -#: mediagoblin/submit/views.py:121 +#: mediagoblin/submit/views.py:127 msgid "Woohoo! Submitted!" msgstr "Juhej! Poslano." +#: mediagoblin/submit/views.py:133 +msgid "Invalid file type." +msgstr "" + #: mediagoblin/templates/mediagoblin/404.html:21 msgid "Oops!" msgstr "Opa!" @@ -162,29 +194,29 @@ msgstr "" msgid "Image of 404 goblin stressing out" msgstr "Slika napake 404 s paniÄnim Å¡kratom" -#: mediagoblin/templates/mediagoblin/base.html:22 -msgid "GNU MediaGoblin" -msgstr "GNU MediaGoblin" - -#: mediagoblin/templates/mediagoblin/base.html:47 +#: mediagoblin/templates/mediagoblin/base.html:49 msgid "MediaGoblin logo" msgstr "Logotip MediaGoblin" -#: mediagoblin/templates/mediagoblin/base.html:52 +#: mediagoblin/templates/mediagoblin/base.html:54 msgid "Submit media" msgstr "PoÅ¡lji vsebino" -#: mediagoblin/templates/mediagoblin/base.html:63 -msgid "verify your email!" -msgstr "Preverite svojo e-poÅ¡to." +#: mediagoblin/templates/mediagoblin/base.html:65 +msgid "Verify your email!" +msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:73 +#: mediagoblin/templates/mediagoblin/base.html:72 +msgid "log out" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 -#: mediagoblin/templates/mediagoblin/auth/login.html:35 +#: mediagoblin/templates/mediagoblin/auth/login.html:45 msgid "Log in" msgstr "Prijava" -#: mediagoblin/templates/mediagoblin/base.html:89 +#: mediagoblin/templates/mediagoblin/base.html:91 msgid "" "Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a " "href=\"http://gnu.org/\">GNU</a> project" @@ -195,66 +227,34 @@ msgid "Explore" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:27 -msgid "Hi there, media lover! MediaGoblin is..." -msgstr "Pozdravljen, ljubitelj veÄpredstavnostnih vsebin! MediaGoblin je ..." - -#: mediagoblin/templates/mediagoblin/root.html:29 -msgid "The perfect place for your media!" -msgstr "Popolno mesto za vaÅ¡e veÄpredstavnostne vsebine." - -#: mediagoblin/templates/mediagoblin/root.html:30 -msgid "" -"A place for people to collaborate and show off original and derived " -"creations!" -msgstr "" -"Mesto, kjer ljudje lahko sodelujejo in razkazujejo originalne in predelane " -"stvaritve." - -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "" -"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project, " -"after all.)" +msgid "Hi there, welcome to this MediaGoblin site!" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:32 +#: mediagoblin/templates/mediagoblin/root.html:28 msgid "" -"Aiming to make the world a better place through decentralization and " -"(eventually, coming soon!) federation!" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." msgstr "" -"Ustvarjen z namenom izboljÅ¡ati svet, s pomoÄjo decentralizacije in (kmalu) " -"federacije." -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "" -"Built for extensibility. (Multiple media types coming soon to the software," -" including video support!)" -msgstr "" -"Zgrajen za razÅ¡irjanje. (Kmalu bodo na voljo dodatne vrste vsebin, vkljuÄno " -"podpora za video)" - -#: mediagoblin/templates/mediagoblin/root.html:34 +#: mediagoblin/templates/mediagoblin/root.html:29 msgid "" -"Powered by people like you. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve this" -" software!</a>)" +"To add your own media, place comments, save your favourites and more, you " +"can log in with your MediaGoblin account." msgstr "" -"Sad dela ljudi, kot ste vi. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">Pri izboljÅ¡evanju nam lahko " -"pomagate tudi vi.</a>)" -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Excited to join us?" +#: mediagoblin/templates/mediagoblin/root.html:31 +msgid "Don't have one yet? It's easy!" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:39 +#: mediagoblin/templates/mediagoblin/root.html:32 #, python-format msgid "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n" +"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" " or\n" -" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:53 +#: mediagoblin/templates/mediagoblin/root.html:44 msgid "Most recent media" msgstr "" @@ -262,8 +262,17 @@ msgstr "" msgid "Enter your new password" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29 -msgid "Enter your username or email" +#: mediagoblin/templates/mediagoblin/auth/change_fp.html:33 +#: mediagoblin/templates/mediagoblin/submit/start.html:30 +msgid "Submit" +msgstr "PoÅ¡lji" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27 +msgid "Recover password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 +msgid "Send instructions" msgstr "" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 @@ -293,22 +302,18 @@ msgstr "" msgid "Logging in failed!" msgstr "Prijava ni uspela." -#: mediagoblin/templates/mediagoblin/auth/login.html:43 +#: mediagoblin/templates/mediagoblin/auth/login.html:35 msgid "Don't have an account yet?" msgstr "Å e nimate raÄuna?" -#: mediagoblin/templates/mediagoblin/auth/login.html:46 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 msgid "Create one here!" msgstr "Ustvarite si ga." -#: mediagoblin/templates/mediagoblin/auth/login.html:49 +#: mediagoblin/templates/mediagoblin/auth/login.html:42 msgid "Forgot your password?" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:52 -msgid "Change it!" -msgstr "" - #: mediagoblin/templates/mediagoblin/auth/register.html:27 msgid "Create an account!" msgstr "Ustvarite raÄun." @@ -354,27 +359,54 @@ msgstr "Shrani spremembe" msgid "Editing %(username)s's profile" msgstr "Urejanje profila – %(username)s" -#: mediagoblin/templates/mediagoblin/listings/tag.html:31 -msgid "Media tagged with:" -msgstr "Vsebina oznaÄena z:" +#: mediagoblin/templates/mediagoblin/listings/tag.html:30 +#: mediagoblin/templates/mediagoblin/listings/tag.html:35 +#, python-format +msgid "Media tagged with: %(tag_name)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:19 +msgid "Original" +msgstr "" #: mediagoblin/templates/mediagoblin/submit/start.html:26 msgid "Submit yer media" msgstr "PoÅ¡ljite svojo vsebino" -#: mediagoblin/templates/mediagoblin/submit/start.html:30 -msgid "Submit" -msgstr "PoÅ¡lji" +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 +#, python-format +msgid "%(username)s's media" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32 +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:37 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" msgstr "Vsebina uporabnika <a href=\"%(user_url)s\">%(username)s</a>" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:32 -msgid "Sorry, no such user found." -msgstr "Oprostite, tega uporabnika ni bilo moÄ najti." +#: mediagoblin/templates/mediagoblin/user_pages/media.html:57 +#, python-format +msgid "By <a href=\"%(user_url)s\">%(username)s</a> on %(date)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:67 +msgid "Post a comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:85 +msgid "at" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +msgid "Post comment!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:124 +msgid "Edit" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:130 +msgid "Delete" +msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -406,29 +438,39 @@ msgstr "V obdelavi ni nobene vsebine" msgid "These uploads failed to process:" msgstr "Teh vsebin ni bilo moÄ obdelati:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:39 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 +#, python-format +msgid "%(username)s's profile" +msgstr "Profil – %(username)s" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 +msgid "Sorry, no such user found." +msgstr "Oprostite, tega uporabnika ni bilo moÄ najti." + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 msgid "Email verification needed" msgstr "Potrebna je potrditev prek e-poÅ¡te" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:42 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 msgid "Almost done! Your account still needs to be activated." msgstr "Skoraj ste zakljuÄili. Svoj raÄun morate le Å¡e aktivirati." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 msgid "" "An email should arrive in a few moments with instructions on how to do so." msgstr "V kratkem bi morali prejeti e-poÅ¡to z navodili, kako to storiti." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:51 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 msgid "In case it doesn't:" msgstr "ÄŒe je ne prejmete:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:54 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 msgid "Resend verification email" msgstr "Ponovno poÅ¡lji potrditveno e-poÅ¡to" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "" "Someone has registered an account with this username, but it still has to be" " activated." @@ -436,7 +478,7 @@ msgstr "" "Nekdo je s tem uporabniÅ¡kim imenom že registriral raÄun, vendar mora biti Å¡e" " aktiviran." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:68 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 #, python-format msgid "" "If you are that person but you've lost your verification email, you can <a " @@ -445,40 +487,35 @@ msgstr "" "ÄŒe ste ta oseba vi, a ste izgubili potrditveno e-poÅ¡to, se lahko <a " "href=\"%(login_url)s\">prijavite</a> in jo ponovno poÅ¡ljete." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:78 -#, python-format -msgid "%(username)s's profile" -msgstr "Profil – %(username)s" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:85 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 msgid "Here's a spot to tell others about yourself." msgstr "Na tem mestu lahko drugim poveste nekaj o sebi." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:108 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:101 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:119 msgid "Edit profile" msgstr "Uredi profil" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:107 msgid "This user hasn't filled in their profile (yet)." msgstr "Ta uporabnik Å¡e ni izpolnil svojega profila." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:122 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:133 #, python-format msgid "View all of %(username)s's media" msgstr "Prikaži vso vsebino uporabnika %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:135 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:146 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "Tu bo prikazana vaÅ¡a vsebina, a trenutno Å¡e niste dodali niÄ." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:152 msgid "Add media" msgstr "Dodaj vsebino" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:147 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:158 msgid "There doesn't seem to be any media here yet..." msgstr "Videti je, da tu Å¡e ni nobene vsebine ..." @@ -498,6 +535,18 @@ msgstr "" msgid "Older" msgstr "" +#: mediagoblin/templates/mediagoblin/utils/pagination.html:50 +msgid "Go to page:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:20 +msgid "Tagged with" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:25 +msgid "and" +msgstr "" + #: mediagoblin/user_pages/forms.py:24 msgid "Comment" msgstr "Komentar" @@ -506,15 +555,23 @@ msgstr "Komentar" msgid "I am sure I want to delete this" msgstr "" -#: mediagoblin/user_pages/views.py:142 -msgid "Empty comments are not allowed." +#: mediagoblin/user_pages/views.py:155 +msgid "Oops, your comment was empty." +msgstr "" + +#: mediagoblin/user_pages/views.py:161 +msgid "Your comment has been posted!" +msgstr "" + +#: mediagoblin/user_pages/views.py:183 +msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:148 -msgid "Comment posted!" +#: mediagoblin/user_pages/views.py:190 +msgid "The media was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:181 +#: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." msgstr "" diff --git a/mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.mo Binary files differindex d2649938..ece8989f 100644 --- a/mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.po index b4b2fb7b..942f7203 100644 --- a/mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/sr/LC_MESSAGES/mediagoblin.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" "Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n" -"POT-Creation-Date: 2011-11-01 23:14-0500\n" -"PO-Revision-Date: 2011-11-02 04:13+0000\n" +"POT-Creation-Date: 2011-12-04 10:24-0600\n" +"PO-Revision-Date: 2011-12-04 16:23+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" @@ -18,6 +18,10 @@ msgstr "" "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/processing.py:143 +msgid "Invalid file given for media type." +msgstr "" + #: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:49 msgid "Username" msgstr "" @@ -51,7 +55,7 @@ msgid "Sorry, a user with that name already exists." msgstr "" #: mediagoblin/auth/views.py:77 -msgid "Sorry, that email address has already been taken." +msgid "Sorry, a user with that email address already exists." msgstr "" #: mediagoblin/auth/views.py:179 @@ -64,11 +68,19 @@ msgstr "" msgid "The verification key or user id is incorrect" msgstr "" -#: mediagoblin/auth/views.py:207 +#: mediagoblin/auth/views.py:203 +msgid "You must be logged in so we know who to send the email to!" +msgstr "" + +#: mediagoblin/auth/views.py:211 +msgid "You've already verified your email address!" +msgstr "" + +#: mediagoblin/auth/views.py:224 msgid "Resent your verification email." msgstr "" -#: mediagoblin/auth/views.py:248 +#: mediagoblin/auth/views.py:265 msgid "" "Could not send password recovery email as your username is inactive or your " "account's email address has not been verified." @@ -82,41 +94,61 @@ msgstr "" msgid "Tags" msgstr "" -#: mediagoblin/edit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 +msgid "Seperate tags by commas." +msgstr "" + +#: mediagoblin/edit/forms.py:33 msgid "Slug" msgstr "" -#: mediagoblin/edit/forms.py:32 +#: mediagoblin/edit/forms.py:34 msgid "The slug can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:33 +#: mediagoblin/edit/forms.py:35 msgid "" "The title part of this media's URL. You usually don't need to change this." msgstr "" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "Bio" msgstr "" -#: mediagoblin/edit/forms.py:43 +#: mediagoblin/edit/forms.py:45 msgid "Website" msgstr "" -#: mediagoblin/edit/views.py:64 +#: mediagoblin/edit/forms.py:49 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:52 +msgid "New Password" +msgstr "" + +#: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:86 msgid "You are editing another user's media. Proceed with caution." msgstr "" -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:156 msgid "You are editing a user's profile. Proceed with caution." msgstr "" -#: mediagoblin/process_media/errors.py:44 -msgid "Invalid file given for media type." +#: mediagoblin/edit/views.py:171 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/edit/views.py:192 +msgid "Profile edited!" +msgstr "" + +#: mediagoblin/media_types/__init__.py:65 +msgid "Could not find any file extension in \"{filename}\"" msgstr "" #: mediagoblin/submit/forms.py:25 @@ -127,16 +159,16 @@ msgstr "" msgid "Description of this work" msgstr "" -#: mediagoblin/submit/views.py:46 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "" -#: mediagoblin/submit/views.py:49 -msgid "The file doesn't seem to be an image!" +#: mediagoblin/submit/views.py:127 +msgid "Woohoo! Submitted!" msgstr "" -#: mediagoblin/submit/views.py:121 -msgid "Woohoo! Submitted!" +#: mediagoblin/submit/views.py:133 +msgid "Invalid file type." msgstr "" #: mediagoblin/templates/mediagoblin/404.html:21 @@ -157,29 +189,29 @@ msgstr "" msgid "Image of 404 goblin stressing out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:22 -msgid "GNU MediaGoblin" -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:47 +#: mediagoblin/templates/mediagoblin/base.html:49 msgid "MediaGoblin logo" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:52 +#: mediagoblin/templates/mediagoblin/base.html:54 msgid "Submit media" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:63 -msgid "verify your email!" +#: mediagoblin/templates/mediagoblin/base.html:65 +msgid "Verify your email!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:72 +msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:73 +#: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 -#: mediagoblin/templates/mediagoblin/auth/login.html:35 +#: mediagoblin/templates/mediagoblin/auth/login.html:45 msgid "Log in" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:89 +#: mediagoblin/templates/mediagoblin/base.html:91 msgid "" "Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a " "href=\"http://gnu.org/\">GNU</a> project" @@ -190,57 +222,34 @@ msgid "Explore" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:27 -msgid "Hi there, media lover! MediaGoblin is..." +msgid "Hi there, welcome to this MediaGoblin site!" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:29 -msgid "The perfect place for your media!" +#: mediagoblin/templates/mediagoblin/root.html:28 +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:30 +#: mediagoblin/templates/mediagoblin/root.html:29 msgid "" -"A place for people to collaborate and show off original and derived " -"creations!" +"To add your own media, place comments, save your favourites and more, you " +"can log in with your MediaGoblin account." msgstr "" #: mediagoblin/templates/mediagoblin/root.html:31 -msgid "" -"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project, " -"after all.)" +msgid "Don't have one yet? It's easy!" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:32 -msgid "" -"Aiming to make the world a better place through decentralization and " -"(eventually, coming soon!) federation!" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "" -"Built for extensibility. (Multiple media types coming soon to the software," -" including video support!)" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:34 -msgid "" -"Powered by people like you. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve this" -" software!</a>)" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Excited to join us?" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:39 #, python-format msgid "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n" +"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" " or\n" -" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:53 +#: mediagoblin/templates/mediagoblin/root.html:44 msgid "Most recent media" msgstr "" @@ -248,8 +257,17 @@ msgstr "" msgid "Enter your new password" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29 -msgid "Enter your username or email" +#: mediagoblin/templates/mediagoblin/auth/change_fp.html:33 +#: mediagoblin/templates/mediagoblin/submit/start.html:30 +msgid "Submit" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27 +msgid "Recover password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 +msgid "Send instructions" msgstr "" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 @@ -279,22 +297,18 @@ msgstr "" msgid "Logging in failed!" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:43 +#: mediagoblin/templates/mediagoblin/auth/login.html:35 msgid "Don't have an account yet?" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:46 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 msgid "Create one here!" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:49 +#: mediagoblin/templates/mediagoblin/auth/login.html:42 msgid "Forgot your password?" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:52 -msgid "Change it!" -msgstr "" - #: mediagoblin/templates/mediagoblin/auth/register.html:27 msgid "Create an account!" msgstr "" @@ -334,26 +348,53 @@ msgstr "" msgid "Editing %(username)s's profile" msgstr "" -#: mediagoblin/templates/mediagoblin/listings/tag.html:31 -msgid "Media tagged with:" +#: mediagoblin/templates/mediagoblin/listings/tag.html:30 +#: mediagoblin/templates/mediagoblin/listings/tag.html:35 +#, python-format +msgid "Media tagged with: %(tag_name)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:19 +msgid "Original" msgstr "" #: mediagoblin/templates/mediagoblin/submit/start.html:26 msgid "Submit yer media" msgstr "" -#: mediagoblin/templates/mediagoblin/submit/start.html:30 -msgid "Submit" +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 +#, python-format +msgid "%(username)s's media" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32 +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:37 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:32 -msgid "Sorry, no such user found." +#: mediagoblin/templates/mediagoblin/user_pages/media.html:57 +#, python-format +msgid "By <a href=\"%(user_url)s\">%(username)s</a> on %(date)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:67 +msgid "Post a comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:85 +msgid "at" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +msgid "Post comment!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:124 +msgid "Edit" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:130 +msgid "Delete" msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 @@ -386,75 +427,80 @@ msgstr "" msgid "These uploads failed to process:" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:39 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 +#, python-format +msgid "%(username)s's profile" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 +msgid "Sorry, no such user found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 msgid "Email verification needed" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:42 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 msgid "Almost done! Your account still needs to be activated." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 msgid "" "An email should arrive in a few moments with instructions on how to do so." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:51 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 msgid "In case it doesn't:" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:54 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 msgid "Resend verification email" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "" "Someone has registered an account with this username, but it still has to be" " activated." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:68 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 #, python-format msgid "" "If you are that person but you've lost your verification email, you can <a " "href=\"%(login_url)s\">log in</a> and resend it." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:78 -#, python-format -msgid "%(username)s's profile" -msgstr "" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:85 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 msgid "Here's a spot to tell others about yourself." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:108 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:101 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:119 msgid "Edit profile" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:107 msgid "This user hasn't filled in their profile (yet)." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:122 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:133 #, python-format msgid "View all of %(username)s's media" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:135 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:146 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:152 msgid "Add media" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:147 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:158 msgid "There doesn't seem to be any media here yet..." msgstr "" @@ -474,6 +520,18 @@ msgstr "" msgid "Older" msgstr "" +#: mediagoblin/templates/mediagoblin/utils/pagination.html:50 +msgid "Go to page:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:20 +msgid "Tagged with" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:25 +msgid "and" +msgstr "" + #: mediagoblin/user_pages/forms.py:24 msgid "Comment" msgstr "" @@ -482,15 +540,23 @@ msgstr "" msgid "I am sure I want to delete this" msgstr "" -#: mediagoblin/user_pages/views.py:142 -msgid "Empty comments are not allowed." +#: mediagoblin/user_pages/views.py:155 +msgid "Oops, your comment was empty." +msgstr "" + +#: mediagoblin/user_pages/views.py:161 +msgid "Your comment has been posted!" +msgstr "" + +#: mediagoblin/user_pages/views.py:183 +msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:148 -msgid "Comment posted!" +#: mediagoblin/user_pages/views.py:190 +msgid "The media was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:181 +#: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." msgstr "" diff --git a/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.mo Binary files differindex 2ae7c510..c6cf0df9 100644 --- a/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.po index 3ee44b18..e195ad70 100644 --- a/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/sv/LC_MESSAGES/mediagoblin.po @@ -9,8 +9,8 @@ msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" "Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n" -"POT-Creation-Date: 2011-11-01 23:14-0500\n" -"PO-Revision-Date: 2011-11-02 04:13+0000\n" +"POT-Creation-Date: 2011-12-04 10:24-0600\n" +"PO-Revision-Date: 2011-12-04 16:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" "Language-Team: Swedish (http://www.transifex.net/projects/p/mediagoblin/team/sv/)\n" "MIME-Version: 1.0\n" @@ -20,6 +20,10 @@ msgstr "" "Language: sv\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" +#: mediagoblin/processing.py:143 +msgid "Invalid file given for media type." +msgstr "Ogiltig fil för mediatypen." + #: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:49 msgid "Username" msgstr "Användarnamn" @@ -53,8 +57,8 @@ msgid "Sorry, a user with that name already exists." msgstr "En användare med det användarnamnet finns redan." #: mediagoblin/auth/views.py:77 -msgid "Sorry, that email address has already been taken." -msgstr "Den e-postadressen är redan tagen." +msgid "Sorry, a user with that email address already exists." +msgstr "" #: mediagoblin/auth/views.py:179 msgid "" @@ -68,11 +72,19 @@ msgstr "" msgid "The verification key or user id is incorrect" msgstr "Verifieringsnyckeln eller användar-IDt är fel." -#: mediagoblin/auth/views.py:207 +#: mediagoblin/auth/views.py:203 +msgid "You must be logged in so we know who to send the email to!" +msgstr "" + +#: mediagoblin/auth/views.py:211 +msgid "You've already verified your email address!" +msgstr "" + +#: mediagoblin/auth/views.py:224 msgid "Resent your verification email." msgstr "Skickade ett nytt verifierings-email." -#: mediagoblin/auth/views.py:248 +#: mediagoblin/auth/views.py:265 msgid "" "Could not send password recovery email as your username is inactive or your " "account's email address has not been verified." @@ -88,42 +100,62 @@ msgstr "Titel" msgid "Tags" msgstr "Taggar" -#: mediagoblin/edit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 +msgid "Seperate tags by commas." +msgstr "" + +#: mediagoblin/edit/forms.py:33 msgid "Slug" msgstr "Sökvägsnamn" -#: mediagoblin/edit/forms.py:32 +#: mediagoblin/edit/forms.py:34 msgid "The slug can't be empty" msgstr "Sökvägsnamnet kan inte vara tomt" -#: mediagoblin/edit/forms.py:33 +#: mediagoblin/edit/forms.py:35 msgid "" "The title part of this media's URL. You usually don't need to change this." msgstr "Sökvägstitlen för din media. Du brukar inte behöva ändra denna." -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "Bio" msgstr "Presentation" -#: mediagoblin/edit/forms.py:43 +#: mediagoblin/edit/forms.py:45 msgid "Website" msgstr "Hemsida" -#: mediagoblin/edit/views.py:64 +#: mediagoblin/edit/forms.py:49 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:52 +msgid "New Password" +msgstr "" + +#: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." msgstr "Ett inlägg med det sökvägsnamnet existerar redan." -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:86 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:155 +#: mediagoblin/edit/views.py:156 msgid "You are editing a user's profile. Proceed with caution." msgstr "Var försiktig, du redigerar en annan användares profil." -#: mediagoblin/process_media/errors.py:44 -msgid "Invalid file given for media type." -msgstr "Ogiltig fil för mediatypen." +#: mediagoblin/edit/views.py:171 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/edit/views.py:192 +msgid "Profile edited!" +msgstr "" + +#: mediagoblin/media_types/__init__.py:65 +msgid "Could not find any file extension in \"{filename}\"" +msgstr "" #: mediagoblin/submit/forms.py:25 msgid "File" @@ -133,18 +165,18 @@ msgstr "Fil" msgid "Description of this work" msgstr "Beskrivning av verket" -#: mediagoblin/submit/views.py:46 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "Du mÃ¥ste ange en fil" -#: mediagoblin/submit/views.py:49 -msgid "The file doesn't seem to be an image!" -msgstr "Filen verkar inte vara en giltig bildfil!" - -#: mediagoblin/submit/views.py:121 +#: mediagoblin/submit/views.py:127 msgid "Woohoo! Submitted!" msgstr "Tjohoo! Upladdat!" +#: mediagoblin/submit/views.py:133 +msgid "Invalid file type." +msgstr "" + #: mediagoblin/templates/mediagoblin/404.html:21 msgid "Oops!" msgstr "Ojoj!" @@ -165,29 +197,29 @@ msgstr "" msgid "Image of 404 goblin stressing out" msgstr "Bild av stressat 404-troll." -#: mediagoblin/templates/mediagoblin/base.html:22 -msgid "GNU MediaGoblin" -msgstr "GNU MediaGoblin" - -#: mediagoblin/templates/mediagoblin/base.html:47 +#: mediagoblin/templates/mediagoblin/base.html:49 msgid "MediaGoblin logo" msgstr "MediaGoblin-logotyp" -#: mediagoblin/templates/mediagoblin/base.html:52 +#: mediagoblin/templates/mediagoblin/base.html:54 msgid "Submit media" msgstr "Ladda upp" -#: mediagoblin/templates/mediagoblin/base.html:63 -msgid "verify your email!" -msgstr "Verifiera din e-postadress!" +#: mediagoblin/templates/mediagoblin/base.html:65 +msgid "Verify your email!" +msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:73 +#: mediagoblin/templates/mediagoblin/base.html:72 +msgid "log out" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 -#: mediagoblin/templates/mediagoblin/auth/login.html:35 +#: mediagoblin/templates/mediagoblin/auth/login.html:45 msgid "Log in" msgstr "Logga in" -#: mediagoblin/templates/mediagoblin/base.html:89 +#: mediagoblin/templates/mediagoblin/base.html:91 msgid "" "Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a " "href=\"http://gnu.org/\">GNU</a> project" @@ -200,75 +232,34 @@ msgid "Explore" msgstr "Utforska" #: mediagoblin/templates/mediagoblin/root.html:27 -msgid "Hi there, media lover! MediaGoblin is..." -msgstr "Hej där mediaentusiast, MediaGoblin..." - -#: mediagoblin/templates/mediagoblin/root.html:29 -msgid "The perfect place for your media!" -msgstr "Är ett perfekt ställe för din media!" - -#: mediagoblin/templates/mediagoblin/root.html:30 -msgid "" -"A place for people to collaborate and show off original and derived " -"creations!" -msgstr "" -"Är ett ställe för människor att samarbeta och visa upp originella och " -"härrörande verk." - -#: mediagoblin/templates/mediagoblin/root.html:31 -msgid "" -"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project, " -"after all.)" +msgid "Hi there, welcome to this MediaGoblin site!" msgstr "" -"Är fritt som i frihet. (Vi är ju ett <a " -"href=\"http://gnu.org\">GNU</a>-projekt.)" -#: mediagoblin/templates/mediagoblin/root.html:32 +#: mediagoblin/templates/mediagoblin/root.html:28 msgid "" -"Aiming to make the world a better place through decentralization and " -"(eventually, coming soon!) federation!" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." msgstr "" -"Arbetar för att göra världen till ett bättre ställe genom decentralisering " -"och (sÃ¥ smÃ¥ningom, kommer snart!) -- Google Translate säger " -"\"sammanslutning\", <em>en: <a " -"href=\"http://en.wikipedia.org/wiki/Federation_(information_technology)\">federation</a></em>" -" " -#: mediagoblin/templates/mediagoblin/root.html:33 +#: mediagoblin/templates/mediagoblin/root.html:29 msgid "" -"Built for extensibility. (Multiple media types coming soon to the software," -" including video support!)" +"To add your own media, place comments, save your favourites and more, you " +"can log in with your MediaGoblin account." msgstr "" -"Byggd för utbyggbarhet. (Flera mediatyper kommer snart till MediaGoblin, " -"bland annat video!)" -#: mediagoblin/templates/mediagoblin/root.html:34 -msgid "" -"Powered by people like you. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve this" -" software!</a>)" +#: mediagoblin/templates/mediagoblin/root.html:31 +msgid "Don't have one yet? It's easy!" msgstr "" -"Drivs av människor som du. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">Du kan hjälpa os forbättra " -"MediaGoblin!</a>)" - -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Excited to join us?" -msgstr "Nyfiken att gÃ¥ med oss?" -#: mediagoblin/templates/mediagoblin/root.html:39 +#: mediagoblin/templates/mediagoblin/root.html:32 #, python-format msgid "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n" +"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" " or\n" -" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" msgstr "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Skapa ett konto gratis</a>\n" -"\n" -" or\n" -" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Installera MediaGoblin pÃ¥ din egen server</a>" -#: mediagoblin/templates/mediagoblin/root.html:53 +#: mediagoblin/templates/mediagoblin/root.html:44 msgid "Most recent media" msgstr "Senast medier" @@ -276,9 +267,18 @@ msgstr "Senast medier" msgid "Enter your new password" msgstr "Fyll i ditt lösenord" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29 -msgid "Enter your username or email" -msgstr "Fyll i ditt användarnamn eller lösenord" +#: mediagoblin/templates/mediagoblin/auth/change_fp.html:33 +#: mediagoblin/templates/mediagoblin/submit/start.html:30 +msgid "Submit" +msgstr "Skicka" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27 +msgid "Recover password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 +msgid "Send instructions" +msgstr "" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 msgid "Your password has been changed. Try to log in now." @@ -317,22 +317,18 @@ msgstr "" msgid "Logging in failed!" msgstr "Inloggning misslyckades!" -#: mediagoblin/templates/mediagoblin/auth/login.html:43 +#: mediagoblin/templates/mediagoblin/auth/login.html:35 msgid "Don't have an account yet?" msgstr "Har du inget konto än?" -#: mediagoblin/templates/mediagoblin/auth/login.html:46 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 msgid "Create one here!" msgstr "Skapa ett här!" -#: mediagoblin/templates/mediagoblin/auth/login.html:49 +#: mediagoblin/templates/mediagoblin/auth/login.html:42 msgid "Forgot your password?" msgstr "Glömt ditt lösenord?" -#: mediagoblin/templates/mediagoblin/auth/login.html:52 -msgid "Change it!" -msgstr "Ändra!" - #: mediagoblin/templates/mediagoblin/auth/register.html:27 msgid "Create an account!" msgstr "Skapa ett konto!" @@ -377,27 +373,54 @@ msgstr "Spara ändringar" msgid "Editing %(username)s's profile" msgstr "Redigerar %(username)ss profil" -#: mediagoblin/templates/mediagoblin/listings/tag.html:31 -msgid "Media tagged with:" -msgstr "Media taggat med:" +#: mediagoblin/templates/mediagoblin/listings/tag.html:30 +#: mediagoblin/templates/mediagoblin/listings/tag.html:35 +#, python-format +msgid "Media tagged with: %(tag_name)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:19 +msgid "Original" +msgstr "" #: mediagoblin/templates/mediagoblin/submit/start.html:26 msgid "Submit yer media" msgstr "Ladda upp" -#: mediagoblin/templates/mediagoblin/submit/start.html:30 -msgid "Submit" -msgstr "Skicka" +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 +#, python-format +msgid "%(username)s's media" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32 +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:37 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" msgstr "<a href=\"%(user_url)s\">%(username)s</a>s media" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:32 -msgid "Sorry, no such user found." -msgstr "Ledsen, hittar ingen sÃ¥dan användare." +#: mediagoblin/templates/mediagoblin/user_pages/media.html:57 +#, python-format +msgid "By <a href=\"%(user_url)s\">%(username)s</a> on %(date)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:67 +msgid "Post a comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:85 +msgid "at" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +msgid "Post comment!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:124 +msgid "Edit" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:130 +msgid "Delete" +msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -429,30 +452,40 @@ msgstr "Ingen media under behandling" msgid "These uploads failed to process:" msgstr "De här behandlingarna misslyckades:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:39 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 +#, python-format +msgid "%(username)s's profile" +msgstr "%(username)ss profil" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 +msgid "Sorry, no such user found." +msgstr "Ledsen, hittar ingen sÃ¥dan användare." + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 msgid "Email verification needed" msgstr "E-postadressverifiering krävs." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:42 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 msgid "Almost done! Your account still needs to be activated." msgstr "Nästan klar! Ditt konto behöver bara aktiveras." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 msgid "" "An email should arrive in a few moments with instructions on how to do so." msgstr "" "Ett e-postmeddelande med instruktioner kommer att hamna hos dig inom kort." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:51 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 msgid "In case it doesn't:" msgstr "Om det inte skulle göra det:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:54 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 msgid "Resend verification email" msgstr "Skicka ett nytt e-postmeddelande" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "" "Someone has registered an account with this username, but it still has to be" " activated." @@ -460,7 +493,7 @@ msgstr "" "NÃ¥gon har redan registrerat ett konto med det här användarnamnet men det har" " inte aktiverats." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:68 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 #, python-format msgid "" "If you are that person but you've lost your verification email, you can <a " @@ -470,30 +503,25 @@ msgstr "" "detaljer om hur du verifierar ditt konto sÃ¥ kan du <a " "href=\"%(login_url)s\">logga in</a> och begära ett nytt." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:78 -#, python-format -msgid "%(username)s's profile" -msgstr "%(username)ss profil" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:85 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 msgid "Here's a spot to tell others about yourself." msgstr "Här kan du berätta för andra om dig själv." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:108 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:101 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:119 msgid "Edit profile" msgstr "Redigera profil" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:107 msgid "This user hasn't filled in their profile (yet)." msgstr "Den här användaren har inte fyllt i sin profilsida ännu." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:122 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:133 #, python-format msgid "View all of %(username)s's media" msgstr "Se all media frÃ¥n %(username)s" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:135 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:146 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." @@ -501,11 +529,11 @@ msgstr "" "Här kommer din media att dyka upp, du verkar inte ha lagt till nÃ¥gonting " "ännu." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:152 msgid "Add media" msgstr "Lägg till media" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:147 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:158 msgid "There doesn't seem to be any media here yet..." msgstr "Det verkar inte finnas nÃ¥gon media här ännu." @@ -525,6 +553,18 @@ msgstr "Nyare" msgid "Older" msgstr "Äldre" +#: mediagoblin/templates/mediagoblin/utils/pagination.html:50 +msgid "Go to page:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:20 +msgid "Tagged with" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:25 +msgid "and" +msgstr "" + #: mediagoblin/user_pages/forms.py:24 msgid "Comment" msgstr "Kommentar" @@ -533,15 +573,23 @@ msgstr "Kommentar" msgid "I am sure I want to delete this" msgstr "Jag är säker pÃ¥ att jag vill radera detta" -#: mediagoblin/user_pages/views.py:142 -msgid "Empty comments are not allowed." +#: mediagoblin/user_pages/views.py:155 +msgid "Oops, your comment was empty." +msgstr "" + +#: mediagoblin/user_pages/views.py:161 +msgid "Your comment has been posted!" +msgstr "" + +#: mediagoblin/user_pages/views.py:183 +msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:148 -msgid "Comment posted!" +#: mediagoblin/user_pages/views.py:190 +msgid "The media was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:181 +#: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." msgstr "Du tänker radera en annan användares media. Var försiktig." diff --git a/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.mo Binary files differindex b0d8d3fc..cd9fab9f 100644 --- a/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.po index 289bddb5..f7bbd6ac 100644 --- a/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.po @@ -8,9 +8,9 @@ msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" "Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n" -"POT-Creation-Date: 2011-11-01 23:14-0500\n" -"PO-Revision-Date: 2011-11-03 14:08+0000\n" -"Last-Translator: veeven <veeven@gmail.com>\n" +"POT-Creation-Date: 2011-12-04 10:24-0600\n" +"PO-Revision-Date: 2011-12-04 16:23+0000\n" +"Last-Translator: cwebber <cwebber@dustycloud.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -19,6 +19,10 @@ msgstr "" "Language: te\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" +#: mediagoblin/processing.py:143 +msgid "Invalid file given for media type." +msgstr "" + #: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:49 msgid "Username" msgstr "వాడà±à°•à°°à°¿ పేరà±" @@ -52,7 +56,7 @@ msgid "Sorry, a user with that name already exists." msgstr "" #: mediagoblin/auth/views.py:77 -msgid "Sorry, that email address has already been taken." +msgid "Sorry, a user with that email address already exists." msgstr "" #: mediagoblin/auth/views.py:179 @@ -65,11 +69,19 @@ msgstr "" msgid "The verification key or user id is incorrect" msgstr "" -#: mediagoblin/auth/views.py:207 +#: mediagoblin/auth/views.py:203 +msgid "You must be logged in so we know who to send the email to!" +msgstr "" + +#: mediagoblin/auth/views.py:211 +msgid "You've already verified your email address!" +msgstr "" + +#: mediagoblin/auth/views.py:224 msgid "Resent your verification email." msgstr "" -#: mediagoblin/auth/views.py:248 +#: mediagoblin/auth/views.py:265 msgid "" "Could not send password recovery email as your username is inactive or your " "account's email address has not been verified." @@ -83,41 +95,61 @@ msgstr "శీరà±à°·à°¿à°•" msgid "Tags" msgstr "" -#: mediagoblin/edit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 +msgid "Seperate tags by commas." +msgstr "" + +#: mediagoblin/edit/forms.py:33 msgid "Slug" msgstr "" -#: mediagoblin/edit/forms.py:32 +#: mediagoblin/edit/forms.py:34 msgid "The slug can't be empty" msgstr "" -#: mediagoblin/edit/forms.py:33 +#: mediagoblin/edit/forms.py:35 msgid "" "The title part of this media's URL. You usually don't need to change this." msgstr "" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "Bio" msgstr "" -#: mediagoblin/edit/forms.py:43 +#: mediagoblin/edit/forms.py:45 msgid "Website" msgstr "" -#: mediagoblin/edit/views.py:64 +#: mediagoblin/edit/forms.py:49 +msgid "Old password" +msgstr "" + +#: mediagoblin/edit/forms.py:52 +msgid "New Password" +msgstr "" + +#: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." msgstr "" -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:86 msgid "You are editing another user's media. Proceed with caution." msgstr "" -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:156 msgid "You are editing a user's profile. Proceed with caution." msgstr "" -#: mediagoblin/process_media/errors.py:44 -msgid "Invalid file given for media type." +#: mediagoblin/edit/views.py:171 +msgid "Wrong password" +msgstr "" + +#: mediagoblin/edit/views.py:192 +msgid "Profile edited!" +msgstr "" + +#: mediagoblin/media_types/__init__.py:65 +msgid "Could not find any file extension in \"{filename}\"" msgstr "" #: mediagoblin/submit/forms.py:25 @@ -128,16 +160,16 @@ msgstr "" msgid "Description of this work" msgstr "" -#: mediagoblin/submit/views.py:46 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "" -#: mediagoblin/submit/views.py:49 -msgid "The file doesn't seem to be an image!" +#: mediagoblin/submit/views.py:127 +msgid "Woohoo! Submitted!" msgstr "" -#: mediagoblin/submit/views.py:121 -msgid "Woohoo! Submitted!" +#: mediagoblin/submit/views.py:133 +msgid "Invalid file type." msgstr "" #: mediagoblin/templates/mediagoblin/404.html:21 @@ -158,29 +190,29 @@ msgstr "" msgid "Image of 404 goblin stressing out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:22 -msgid "GNU MediaGoblin" -msgstr "" - -#: mediagoblin/templates/mediagoblin/base.html:47 +#: mediagoblin/templates/mediagoblin/base.html:49 msgid "MediaGoblin logo" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:52 +#: mediagoblin/templates/mediagoblin/base.html:54 msgid "Submit media" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:63 -msgid "verify your email!" +#: mediagoblin/templates/mediagoblin/base.html:65 +msgid "Verify your email!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/base.html:72 +msgid "log out" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:73 +#: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 -#: mediagoblin/templates/mediagoblin/auth/login.html:35 +#: mediagoblin/templates/mediagoblin/auth/login.html:45 msgid "Log in" msgstr "" -#: mediagoblin/templates/mediagoblin/base.html:89 +#: mediagoblin/templates/mediagoblin/base.html:91 msgid "" "Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a " "href=\"http://gnu.org/\">GNU</a> project" @@ -191,57 +223,34 @@ msgid "Explore" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:27 -msgid "Hi there, media lover! MediaGoblin is..." +msgid "Hi there, welcome to this MediaGoblin site!" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:29 -msgid "The perfect place for your media!" +#: mediagoblin/templates/mediagoblin/root.html:28 +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:30 +#: mediagoblin/templates/mediagoblin/root.html:29 msgid "" -"A place for people to collaborate and show off original and derived " -"creations!" +"To add your own media, place comments, save your favourites and more, you " +"can log in with your MediaGoblin account." msgstr "" #: mediagoblin/templates/mediagoblin/root.html:31 -msgid "" -"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project, " -"after all.)" +msgid "Don't have one yet? It's easy!" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:32 -msgid "" -"Aiming to make the world a better place through decentralization and " -"(eventually, coming soon!) federation!" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "" -"Built for extensibility. (Multiple media types coming soon to the software," -" including video support!)" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:34 -msgid "" -"Powered by people like you. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve this" -" software!</a>)" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Excited to join us?" -msgstr "" - -#: mediagoblin/templates/mediagoblin/root.html:39 #, python-format msgid "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n" +"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" " or\n" -" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:53 +#: mediagoblin/templates/mediagoblin/root.html:44 msgid "Most recent media" msgstr "" @@ -249,8 +258,17 @@ msgstr "" msgid "Enter your new password" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29 -msgid "Enter your username or email" +#: mediagoblin/templates/mediagoblin/auth/change_fp.html:33 +#: mediagoblin/templates/mediagoblin/submit/start.html:30 +msgid "Submit" +msgstr "దాఖలౠచెయà±à°¯à°¿" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27 +msgid "Recover password" +msgstr "" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 +msgid "Send instructions" msgstr "" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 @@ -280,22 +298,18 @@ msgstr "" msgid "Logging in failed!" msgstr "à°ªà±à°°à°µà±‡à°¶à°‚ విఫలమయà±à°¯à°¿à°‚ది!" -#: mediagoblin/templates/mediagoblin/auth/login.html:43 +#: mediagoblin/templates/mediagoblin/auth/login.html:35 msgid "Don't have an account yet?" msgstr "మీకౠఇంకా ఖాతా లేదా?" -#: mediagoblin/templates/mediagoblin/auth/login.html:46 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 msgid "Create one here!" msgstr "" -#: mediagoblin/templates/mediagoblin/auth/login.html:49 +#: mediagoblin/templates/mediagoblin/auth/login.html:42 msgid "Forgot your password?" msgstr "మీ సంకేతపదానà±à°¨à°¿ మరà±à°šà°¿à°ªà±‹à°¯à°¾à°°à°¾?" -#: mediagoblin/templates/mediagoblin/auth/login.html:52 -msgid "Change it!" -msgstr "" - #: mediagoblin/templates/mediagoblin/auth/register.html:27 msgid "Create an account!" msgstr "" @@ -335,26 +349,53 @@ msgstr "మారà±à°ªà±à°²à°¨à± à°à°¦à±à°°à°ªà°°à°šà±" msgid "Editing %(username)s's profile" msgstr "" -#: mediagoblin/templates/mediagoblin/listings/tag.html:31 -msgid "Media tagged with:" +#: mediagoblin/templates/mediagoblin/listings/tag.html:30 +#: mediagoblin/templates/mediagoblin/listings/tag.html:35 +#, python-format +msgid "Media tagged with: %(tag_name)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:19 +msgid "Original" msgstr "" #: mediagoblin/templates/mediagoblin/submit/start.html:26 msgid "Submit yer media" msgstr "" -#: mediagoblin/templates/mediagoblin/submit/start.html:30 -msgid "Submit" -msgstr "దాఖలౠచెయà±à°¯à°¿" +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 +#, python-format +msgid "%(username)s's media" +msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32 +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:37 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:32 -msgid "Sorry, no such user found." +#: mediagoblin/templates/mediagoblin/user_pages/media.html:57 +#, python-format +msgid "By <a href=\"%(user_url)s\">%(username)s</a> on %(date)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:67 +msgid "Post a comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:85 +msgid "at" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +msgid "Post comment!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:124 +msgid "Edit" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:130 +msgid "Delete" msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 @@ -387,75 +428,80 @@ msgstr "" msgid "These uploads failed to process:" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:39 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 +#, python-format +msgid "%(username)s's profile" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 +msgid "Sorry, no such user found." +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 msgid "Email verification needed" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:42 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 msgid "Almost done! Your account still needs to be activated." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 msgid "" "An email should arrive in a few moments with instructions on how to do so." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:51 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 msgid "In case it doesn't:" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:54 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 msgid "Resend verification email" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "" "Someone has registered an account with this username, but it still has to be" " activated." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:68 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 #, python-format msgid "" "If you are that person but you've lost your verification email, you can <a " "href=\"%(login_url)s\">log in</a> and resend it." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:78 -#, python-format -msgid "%(username)s's profile" -msgstr "" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:85 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 msgid "Here's a spot to tell others about yourself." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:108 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:101 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:119 msgid "Edit profile" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:107 msgid "This user hasn't filled in their profile (yet)." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:122 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:133 #, python-format msgid "View all of %(username)s's media" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:135 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:146 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:152 msgid "Add media" msgstr "" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:147 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:158 msgid "There doesn't seem to be any media here yet..." msgstr "" @@ -475,6 +521,18 @@ msgstr "" msgid "Older" msgstr "" +#: mediagoblin/templates/mediagoblin/utils/pagination.html:50 +msgid "Go to page:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:20 +msgid "Tagged with" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:25 +msgid "and" +msgstr "" + #: mediagoblin/user_pages/forms.py:24 msgid "Comment" msgstr "à°µà±à°¯à°¾à°–à±à°¯" @@ -483,15 +541,23 @@ msgstr "à°µà±à°¯à°¾à°–à±à°¯" msgid "I am sure I want to delete this" msgstr "" -#: mediagoblin/user_pages/views.py:142 -msgid "Empty comments are not allowed." +#: mediagoblin/user_pages/views.py:155 +msgid "Oops, your comment was empty." +msgstr "" + +#: mediagoblin/user_pages/views.py:161 +msgid "Your comment has been posted!" +msgstr "" + +#: mediagoblin/user_pages/views.py:183 +msgid "You deleted the media." msgstr "" -#: mediagoblin/user_pages/views.py:148 -msgid "Comment posted!" +#: mediagoblin/user_pages/views.py:190 +msgid "The media was not deleted because you didn't check that you were sure." msgstr "" -#: mediagoblin/user_pages/views.py:181 +#: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." msgstr "" diff --git a/mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.mo b/mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.mo Binary files differindex e3751aeb..6dda94b7 100644 --- a/mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.mo +++ b/mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.mo diff --git a/mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.po index c664adbe..70622590 100644 --- a/mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/zh_TW/LC_MESSAGES/mediagoblin.po @@ -9,8 +9,8 @@ msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" "Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n" -"POT-Creation-Date: 2011-11-01 23:14-0500\n" -"PO-Revision-Date: 2011-11-02 04:13+0000\n" +"POT-Creation-Date: 2011-12-04 10:24-0600\n" +"PO-Revision-Date: 2011-12-04 16:23+0000\n" "Last-Translator: cwebber <cwebber@dustycloud.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" @@ -20,6 +20,10 @@ msgstr "" "Language: zh_TW\n" "Plural-Forms: nplurals=1; plural=0\n" +#: mediagoblin/processing.py:143 +msgid "Invalid file given for media type." +msgstr "指定錯誤的媒體類別ï¼" + #: mediagoblin/auth/forms.py:25 mediagoblin/auth/forms.py:49 msgid "Username" msgstr "使用者å稱" @@ -53,8 +57,8 @@ msgid "Sorry, a user with that name already exists." msgstr "抱æ‰, 這個使用者å稱已經å˜åœ¨." #: mediagoblin/auth/views.py:77 -msgid "Sorry, that email address has already been taken." -msgstr "抱æ‰ï¼Œé€™å€‹é›»å郵件已經被其他人使用了。" +msgid "Sorry, a user with that email address already exists." +msgstr "抱æ‰ï¼Œæ¤é›»å郵件已被註冊了。" #: mediagoblin/auth/views.py:179 msgid "" @@ -66,11 +70,19 @@ msgstr "ä½ çš„é›»å郵件ä½å€å·²è¢«èªè‰. ä½ ç¾åœ¨å°±å¯ä»¥ç™»å…¥, ç·¨è¼¯ä½ msgid "The verification key or user id is incorrect" msgstr "èªè‰ç¢¼æˆ–是使用者帳號錯誤" -#: mediagoblin/auth/views.py:207 +#: mediagoblin/auth/views.py:203 +msgid "You must be logged in so we know who to send the email to!" +msgstr "ä½ å¿…é ˆç™»å…¥ï¼Œæˆ‘å€‘æ‰çŸ¥é“ä¿¡è¦é€çµ¦èª°ï¼" + +#: mediagoblin/auth/views.py:211 +msgid "You've already verified your email address!" +msgstr "ä½ çš„é›»å郵件已經確èªäº†ï¼" + +#: mediagoblin/auth/views.py:224 msgid "Resent your verification email." msgstr "é‡é€èªè‰ä¿¡." -#: mediagoblin/auth/views.py:248 +#: mediagoblin/auth/views.py:265 msgid "" "Could not send password recovery email as your username is inactive or your " "account's email address has not been verified." @@ -84,42 +96,62 @@ msgstr "標題" msgid "Tags" msgstr "標籤" -#: mediagoblin/edit/forms.py:31 +#: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 +msgid "Seperate tags by commas." +msgstr "" + +#: mediagoblin/edit/forms.py:33 msgid "Slug" msgstr "自訂å—串" -#: mediagoblin/edit/forms.py:32 +#: mediagoblin/edit/forms.py:34 msgid "The slug can't be empty" msgstr "自訂å—串ä¸èƒ½ç©ºç™½" -#: mediagoblin/edit/forms.py:33 +#: mediagoblin/edit/forms.py:35 msgid "" "The title part of this media's URL. You usually don't need to change this." msgstr "æ¤åª’體網å€çš„åç¨±ã€‚ä½ é€šå¸¸ä¸éœ€è¦è®Šå‹•這個的。" -#: mediagoblin/edit/forms.py:40 +#: mediagoblin/edit/forms.py:42 msgid "Bio" msgstr "自我介紹" -#: mediagoblin/edit/forms.py:43 +#: mediagoblin/edit/forms.py:45 msgid "Website" msgstr "網站" -#: mediagoblin/edit/views.py:64 +#: mediagoblin/edit/forms.py:49 +msgid "Old password" +msgstr "舊的密碼" + +#: mediagoblin/edit/forms.py:52 +msgid "New Password" +msgstr "新的密碼" + +#: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." msgstr "這個自訂å—串已經被其他人用了" -#: mediagoblin/edit/views.py:85 +#: mediagoblin/edit/views.py:86 msgid "You are editing another user's media. Proceed with caution." msgstr "ä½ æ£åœ¨ç·¨è¼¯ä»–人的媒體檔案. 請謹慎處ç†." -#: mediagoblin/edit/views.py:155 +#: mediagoblin/edit/views.py:156 msgid "You are editing a user's profile. Proceed with caution." msgstr "ä½ æ£åœ¨ç·¨è¼¯ä¸€ä½ç”¨æˆ¶çš„æª”案. 請謹慎處ç†." -#: mediagoblin/process_media/errors.py:44 -msgid "Invalid file given for media type." -msgstr "指定錯誤的媒體類別ï¼" +#: mediagoblin/edit/views.py:171 +msgid "Wrong password" +msgstr "密碼錯誤" + +#: mediagoblin/edit/views.py:192 +msgid "Profile edited!" +msgstr "個人資料已被編輯了ï¼" + +#: mediagoblin/media_types/__init__.py:65 +msgid "Could not find any file extension in \"{filename}\"" +msgstr "找ä¸åˆ°ä»»ä½• \"{filename}\" 的附檔å。" #: mediagoblin/submit/forms.py:25 msgid "File" @@ -129,18 +161,18 @@ msgstr "檔案" msgid "Description of this work" msgstr "這個作å“çš„æè¿°" -#: mediagoblin/submit/views.py:46 +#: mediagoblin/submit/views.py:49 msgid "You must provide a file." msgstr "ä½ å¿…é ˆæä¾›ä¸€å€‹æª”案" -#: mediagoblin/submit/views.py:49 -msgid "The file doesn't seem to be an image!" -msgstr "æª”æ¡ˆä¼¼ä¹Žä¸æ˜¯ä¸€å€‹åœ–片喔!" - -#: mediagoblin/submit/views.py:121 +#: mediagoblin/submit/views.py:127 msgid "Woohoo! Submitted!" msgstr "呼呼! é€å‡ºåŽ»åš•!" +#: mediagoblin/submit/views.py:133 +msgid "Invalid file type." +msgstr "䏿£ç¢ºçš„æª”æ¡ˆæ ¼å¼" + #: mediagoblin/templates/mediagoblin/404.html:21 msgid "Oops!" msgstr "糟糕ï¼" @@ -159,29 +191,29 @@ msgstr "å¦‚æžœä½ ç¢ºå®šé€™å€‹ä½å€æ˜¯æ£ç¢ºçš„ï¼Œæˆ–è¨±ä½ åœ¨æ‰¾çš„ç¶²é 已經 msgid "Image of 404 goblin stressing out" msgstr "Image of 404 goblin stressing out" -#: mediagoblin/templates/mediagoblin/base.html:22 -msgid "GNU MediaGoblin" -msgstr "GNU MediaGoblin" - -#: mediagoblin/templates/mediagoblin/base.html:47 +#: mediagoblin/templates/mediagoblin/base.html:49 msgid "MediaGoblin logo" msgstr "MediaGoblin 標誌" -#: mediagoblin/templates/mediagoblin/base.html:52 +#: mediagoblin/templates/mediagoblin/base.html:54 msgid "Submit media" msgstr "éžäº¤åª’é«”" -#: mediagoblin/templates/mediagoblin/base.html:63 -msgid "verify your email!" -msgstr "ç¢ºèªæ‚¨çš„é›»å郵件!" +#: mediagoblin/templates/mediagoblin/base.html:65 +msgid "Verify your email!" +msgstr "確èªä½ 的電å郵件" + +#: mediagoblin/templates/mediagoblin/base.html:72 +msgid "log out" +msgstr "登出" -#: mediagoblin/templates/mediagoblin/base.html:73 +#: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 -#: mediagoblin/templates/mediagoblin/auth/login.html:35 +#: mediagoblin/templates/mediagoblin/auth/login.html:45 msgid "Log in" msgstr "登入" -#: mediagoblin/templates/mediagoblin/base.html:89 +#: mediagoblin/templates/mediagoblin/base.html:91 msgid "" "Powered by <a href=\"http://mediagoblin.org\">MediaGoblin</a>, a <a " "href=\"http://gnu.org/\">GNU</a> project" @@ -194,62 +226,37 @@ msgid "Explore" msgstr "探索" #: mediagoblin/templates/mediagoblin/root.html:27 -msgid "Hi there, media lover! MediaGoblin is..." -msgstr "å—¨ï¼å¤šåª’體檔案愛好者ï¼MediaGoblin是..." +msgid "Hi there, welcome to this MediaGoblin site!" +msgstr "å˜¿ï¼æ¡è¿Žä¾†åˆ° 媒體怪ç¸(MediaGoblin) 網站" -#: mediagoblin/templates/mediagoblin/root.html:29 -msgid "The perfect place for your media!" -msgstr "ä½ çš„åª’é«”æª”æ¡ˆçš„æœ€ä½³æ‰€åœ¨ï¼" +#: mediagoblin/templates/mediagoblin/root.html:28 +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." +msgstr "" -#: mediagoblin/templates/mediagoblin/root.html:30 +#: mediagoblin/templates/mediagoblin/root.html:29 msgid "" -"A place for people to collaborate and show off original and derived " -"creations!" -msgstr "這是一個å¯ä»¥è®“人們共åŒå±•示他們的創作ã€è¡ç”Ÿä½œå“的地方ï¼" +"To add your own media, place comments, save your favourites and more, you " +"can log in with your MediaGoblin account." +msgstr "ä½ å¯ä»¥ç”¨ åª’é«”æ€ªç¸ å¸³è™Ÿç™»å…¥ï¼ŒåŠ å…¥ä½ è‡ªå·±çš„åª’é«”æª”æ¡ˆï¼ŒåŠ å…¥è©•èªžï¼ŒæŠŠä½ çš„æœ€æ„›å„²å˜èµ·ä¾†ã€‚" #: mediagoblin/templates/mediagoblin/root.html:31 -msgid "" -"Free, as in freedom. (We’re a <a href=\"http://gnu.org\">GNU</a> project, " -"after all.)" -msgstr "å…費但是我們更é‡è¦–自由 (畢竟我們是個 <a href=\"http://gnu.org\">GNU</a> 專案)" +msgid "Don't have one yet? It's easy!" +msgstr "還沒有嗎?其實éžå¸¸ç°¡å–®ï¼" #: mediagoblin/templates/mediagoblin/root.html:32 -msgid "" -"Aiming to make the world a better place through decentralization and " -"(eventually, coming soon!) federation!" -msgstr "目的是è¦é€éŽåˆ†æ•£å¼ä¸”自由的方å¼è®“這個世界更美好ï¼(總有一天,它很快會到來的ï¼)" - -#: mediagoblin/templates/mediagoblin/root.html:33 -msgid "" -"Built for extensibility. (Multiple media types coming soon to the software," -" including video support!)" -msgstr "天生的擴充性。(軟體將支æ´å¤šç¨®å¤šåª’é«”æ ¼å¼, 也支æ´å½±éŸ³æª”案ï¼)" - -#: mediagoblin/templates/mediagoblin/root.html:34 -msgid "" -"Powered by people like you. (<a " -"href=\"http://mediagoblin.org/pages/join.html\">You can help us improve this" -" software!</a>)" -msgstr "" -"ç”±åƒä½ 一樣的人們製作 (<a " -"href=\"http://mediagoblin.org/pages/join.html\">ä½ å¯ä»¥å¹«æˆ‘們改進軟體!</a>)" - -#: mediagoblin/templates/mediagoblin/root.html:38 -msgid "Excited to join us?" -msgstr "è¿«ä¸äºŸå¾…想è¦åŠ å…¥æˆ‘å€‘ï¼Ÿ" - -#: mediagoblin/templates/mediagoblin/root.html:39 #, python-format msgid "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">Create a free account</a>\n" +"<a class=\"button_action_highlight\" href=\"%(register_url)s\">Create an account at this site</a>\n" " or\n" -" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Set up MediaGoblin on your own server</a>" msgstr "" -"<a class=\"header_submit_highlight\" href=\"%(register_url)s\">建立一個å…費帳號</a>\n" +"<a class=\"button_action_highlight\" href=\"%(register_url)s\">在這網站建立帳號</a>\n" " 或是\n" -" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">åœ¨ä½ çš„ä¼ºæœå™¨ä¸Šè¨ç«‹ MediaGoblin</a>" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">建立一個自己的媒體怪ç¸(MedaiGoblin)</a>" -#: mediagoblin/templates/mediagoblin/root.html:53 +#: mediagoblin/templates/mediagoblin/root.html:44 msgid "Most recent media" msgstr "最新的媒體" @@ -257,9 +264,18 @@ msgstr "最新的媒體" msgid "Enter your new password" msgstr "è¼¸å…¥ä½ çš„æ–°å¯†ç¢¼" -#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:29 -msgid "Enter your username or email" -msgstr "è¼¸å…¥ä½ çš„å¸³è™Ÿæˆ–æ˜¯é›»å郵件" +#: mediagoblin/templates/mediagoblin/auth/change_fp.html:33 +#: mediagoblin/templates/mediagoblin/submit/start.html:30 +msgid "Submit" +msgstr "é€å‡º" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:27 +msgid "Recover password" +msgstr "找回密碼" + +#: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 +msgid "Send instructions" +msgstr "é€å‡ºæŒ‡ç¤º" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 msgid "Your password has been changed. Try to log in now." @@ -295,22 +311,18 @@ msgstr "" msgid "Logging in failed!" msgstr "登入失敗ï¼" -#: mediagoblin/templates/mediagoblin/auth/login.html:43 +#: mediagoblin/templates/mediagoblin/auth/login.html:35 msgid "Don't have an account yet?" msgstr "還沒有帳號嗎?" -#: mediagoblin/templates/mediagoblin/auth/login.html:46 +#: mediagoblin/templates/mediagoblin/auth/login.html:36 msgid "Create one here!" msgstr "在這裡建立一個å§!" -#: mediagoblin/templates/mediagoblin/auth/login.html:49 +#: mediagoblin/templates/mediagoblin/auth/login.html:42 msgid "Forgot your password?" msgstr "忘了密碼嗎?" -#: mediagoblin/templates/mediagoblin/auth/login.html:52 -msgid "Change it!" -msgstr "變更ï¼" - #: mediagoblin/templates/mediagoblin/auth/register.html:27 msgid "Create an account!" msgstr "建立一個帳號!" @@ -355,27 +367,54 @@ msgstr "儲å˜è®Šæ›´" msgid "Editing %(username)s's profile" msgstr "編輯 %(username)s'的檔案ä¸" -#: mediagoblin/templates/mediagoblin/listings/tag.html:31 -msgid "Media tagged with:" -msgstr "媒體檔案被標籤為:" +#: mediagoblin/templates/mediagoblin/listings/tag.html:30 +#: mediagoblin/templates/mediagoblin/listings/tag.html:35 +#, python-format +msgid "Media tagged with: %(tag_name)s" +msgstr "æ¤åª’體被標è˜ç‚ºï¼š%(tag_name)s" + +#: mediagoblin/templates/mediagoblin/media_displays/video.html:19 +msgid "Original" +msgstr "原始的" #: mediagoblin/templates/mediagoblin/submit/start.html:26 msgid "Submit yer media" msgstr "éžäº¤ä½ 的媒體檔案" -#: mediagoblin/templates/mediagoblin/submit/start.html:30 -msgid "Submit" -msgstr "é€å‡º" +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:30 +#, python-format +msgid "%(username)s's media" +msgstr "%(username)s的媒體" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:32 +#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:37 #, python-format msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" msgstr "<a href=\"%(user_url)s\">%(username)s</a>的媒體檔案" -#: mediagoblin/templates/mediagoblin/user_pages/gallery.html:52 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:32 -msgid "Sorry, no such user found." -msgstr "抱æ‰ï¼Œæ‰¾ä¸åˆ°é€™å€‹ä½¿ç”¨è€…." +#: mediagoblin/templates/mediagoblin/user_pages/media.html:57 +#, python-format +msgid "By <a href=\"%(user_url)s\">%(username)s</a> on %(date)s" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:67 +msgid "Post a comment" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:85 +msgid "at" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:102 +msgid "Post comment!" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:124 +msgid "Edit" +msgstr "" + +#: mediagoblin/templates/mediagoblin/user_pages/media.html:130 +msgid "Delete" +msgstr "" #: mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html:30 #, python-format @@ -407,75 +446,80 @@ msgstr "沒有æ£åœ¨è™•ç†ä¸çš„媒體" msgid "These uploads failed to process:" msgstr "無法處ç†é€™äº›æ›´æ–°" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:39 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:59 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:31 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:89 +#, python-format +msgid "%(username)s's profile" +msgstr "%(username)s的個人檔案" + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:43 +msgid "Sorry, no such user found." +msgstr "抱æ‰ï¼Œæ‰¾ä¸åˆ°é€™å€‹ä½¿ç”¨è€…." + +#: mediagoblin/templates/mediagoblin/user_pages/user.html:50 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:70 msgid "Email verification needed" msgstr "需è¦èªè‰é›»å郵件" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:42 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:53 msgid "Almost done! Your account still needs to be activated." msgstr "幾乎完æˆäº†ï¼ä½†ä½ 的帳號ä»ç„¶éœ€è¦è¢«å•Ÿç”¨ã€‚" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:47 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:58 msgid "" "An email should arrive in a few moments with instructions on how to do so." msgstr "馬上會有一å°é›»åéƒµä»¶å‘Šè¨´ä½ å¦‚ä½•åš." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:51 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 msgid "In case it doesn't:" msgstr "å‡è¨å®ƒç„¡æ³•:" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:54 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:65 msgid "Resend verification email" msgstr "é‡é€èªè‰ä¿¡" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:62 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:73 msgid "" "Someone has registered an account with this username, but it still has to be" " activated." msgstr "有人用了這個帳號登錄了,但是這個帳號ä»éœ€è¦è¢«å•Ÿç”¨ã€‚" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:68 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:79 #, python-format msgid "" "If you are that person but you've lost your verification email, you can <a " "href=\"%(login_url)s\">log in</a> and resend it." msgstr "å¦‚æžœä½ å°±æ˜¯é‚£å€‹äºº, 但是éºå¤±äº†èªè‰ä¿¡, ä½ å¯ä»¥<a href=\"%(login_url)s\">登入</a> 然後é‡é€ä¸€æ¬¡." -#: mediagoblin/templates/mediagoblin/user_pages/user.html:78 -#, python-format -msgid "%(username)s's profile" -msgstr "%(username)s的個人檔案" - -#: mediagoblin/templates/mediagoblin/user_pages/user.html:85 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 msgid "Here's a spot to tell others about yourself." msgstr "é€™æ˜¯ä¸€å€‹åœ°æ–¹ï¼Œèƒ½è®“ä½ å‘他人介紹自己。" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:90 -#: mediagoblin/templates/mediagoblin/user_pages/user.html:108 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:101 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:119 msgid "Edit profile" msgstr "編輯個人檔案" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:96 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:107 msgid "This user hasn't filled in their profile (yet)." msgstr "這個使用者還沒(來得åŠ)填寫個人檔案。" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:122 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:133 #, python-format msgid "View all of %(username)s's media" msgstr "查看%(username)s的全部媒體檔案" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:135 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:146 msgid "" "This is where your media will appear, but you don't seem to have added " "anything yet." msgstr "é€™å€‹åœ°æ–¹æ˜¯ä½ çš„åª’é«”æª”æ¡ˆæœƒå‡ºç¾çš„åœ°æ–¹ï¼Œä½†æ˜¯ä½ ä¼¼ä¹Žé‚„æ²’æœ‰åŠ å…¥ä»»ä½•æ±è¥¿ã€‚" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:141 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:152 msgid "Add media" msgstr "新增媒體檔案" -#: mediagoblin/templates/mediagoblin/user_pages/user.html:147 +#: mediagoblin/templates/mediagoblin/user_pages/user.html:158 msgid "There doesn't seem to be any media here yet..." msgstr "似乎還沒有任何的媒體檔案..." @@ -495,6 +539,18 @@ msgstr "新一點" msgid "Older" msgstr "舊一點" +#: mediagoblin/templates/mediagoblin/utils/pagination.html:50 +msgid "Go to page:" +msgstr "" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:20 +msgid "Tagged with" +msgstr "被標籤為" + +#: mediagoblin/templates/mediagoblin/utils/tags.html:25 +msgid "and" +msgstr "且" + #: mediagoblin/user_pages/forms.py:24 msgid "Comment" msgstr "è©•è«–" @@ -503,15 +559,23 @@ msgstr "è©•è«–" msgid "I am sure I want to delete this" msgstr "我確定我想è¦åˆªé™¤" -#: mediagoblin/user_pages/views.py:142 -msgid "Empty comments are not allowed." +#: mediagoblin/user_pages/views.py:155 +msgid "Oops, your comment was empty." msgstr "" -#: mediagoblin/user_pages/views.py:148 -msgid "Comment posted!" +#: mediagoblin/user_pages/views.py:161 +msgid "Your comment has been posted!" msgstr "" -#: mediagoblin/user_pages/views.py:181 +#: mediagoblin/user_pages/views.py:183 +msgid "You deleted the media." +msgstr "ä½ å·²åˆªé™¤æ¤åª’體檔案。" + +#: mediagoblin/user_pages/views.py:190 +msgid "The media was not deleted because you didn't check that you were sure." +msgstr "æ¤åª’é«”æª”æ¡ˆå°šæœªè¢«åˆªé™¤å› ç‚ºä½ é‚„æ²’æœ‰ç¢ºèªä½ 真的è¦åˆªé™¤ã€‚" + +#: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." msgstr "ä½ åœ¨åˆªé™¤å…¶ä»–äººçš„åª’é«”æª”æ¡ˆã€‚è«‹å°å¿ƒè™•ç†å–”。" diff --git a/mediagoblin/init/__init__.py b/mediagoblin/init/__init__.py index b7f52595..08a0618d 100644 --- a/mediagoblin/init/__init__.py +++ b/mediagoblin/init/__init__.py @@ -29,8 +29,12 @@ from mediagoblin.workbench import WorkbenchManager from mediagoblin.storage import storage_system_from_config -class Error(Exception): pass -class ImproperlyConfigured(Error): pass +class Error(Exception): + pass + + +class ImproperlyConfigured(Error): + pass def setup_global_and_app_config(config_path): @@ -76,8 +80,8 @@ def setup_database(): "in fact they appear to be from the future?!") setup_globals( - db_connection = connection, - database = db) + db_connection=connection, + database=db) return connection, db @@ -99,10 +103,10 @@ def get_jinja_loader(user_template_path=None): def get_staticdirector(app_config): - if app_config.has_key('direct_remote_path'): + if 'direct_remote_path' in app_config: return staticdirect.RemoteStaticDirect( app_config['direct_remote_path'].strip()) - elif app_config.has_key('direct_remote_paths'): + elif 'direct_remote_paths' in app_config: direct_remote_path_lines = app_config[ 'direct_remote_paths'].strip().splitlines() return staticdirect.MultiRemoteStaticDirect( @@ -126,8 +130,8 @@ def setup_storage(): queue_store = storage_system_from_config(global_config[key_long]) setup_globals( - public_store = public_store, - queue_store = queue_store) + public_store=public_store, + queue_store=queue_store) return public_store, queue_store @@ -137,7 +141,7 @@ def setup_workbench(): workbench_manager = WorkbenchManager(app_config['workbench_path']) - setup_globals(workbench_manager = workbench_manager) + setup_globals(workbench_manager=workbench_manager) def setup_beaker_cache(): diff --git a/mediagoblin/init/celery/__init__.py b/mediagoblin/init/celery/__init__.py index c58b1305..1eb21d7a 100644 --- a/mediagoblin/init/celery/__init__.py +++ b/mediagoblin/init/celery/__init__.py @@ -18,7 +18,7 @@ import os import sys -MANDATORY_CELERY_IMPORTS = ['mediagoblin.process_media'] +MANDATORY_CELERY_IMPORTS = ['mediagoblin.processing'] DEFAULT_SETTINGS_MODULE = 'mediagoblin.init.celery.dummy_settings_module' @@ -40,25 +40,25 @@ def setup_celery_from_config(app_config, global_config, - set_environ: if set, this will CELERY_CONFIG_MODULE to the settings_module """ - if global_config.has_key('celery'): + if 'celery' in global_config: celery_conf = global_config['celery'] else: celery_conf = {} - + celery_settings = {} # set up mongodb stuff celery_settings['CELERY_RESULT_BACKEND'] = 'mongodb' - if not celery_settings.has_key('BROKER_BACKEND'): + if 'BROKER_BACKEND' not in celery_settings: celery_settings['BROKER_BACKEND'] = 'mongodb' celery_mongo_settings = {} - if app_config.has_key('db_host'): + if 'db_host' in app_config: celery_mongo_settings['host'] = app_config['db_host'] if celery_settings['BROKER_BACKEND'] == 'mongodb': celery_settings['BROKER_HOST'] = app_config['db_host'] - if app_config.has_key('db_port'): + if 'db_port' in app_config: celery_mongo_settings['port'] = app_config['db_port'] if celery_settings['BROKER_BACKEND'] == 'mongodb': celery_settings['BROKER_PORT'] = app_config['db_port'] @@ -84,6 +84,6 @@ def setup_celery_from_config(app_config, global_config, for key, value in celery_settings.iteritems(): setattr(this_module, key, value) - + if set_environ: os.environ['CELERY_CONFIG_MODULE'] = settings_module diff --git a/mediagoblin/init/celery/from_celery.py b/mediagoblin/init/celery/from_celery.py index 3e5adb98..05669b67 100644 --- a/mediagoblin/init/celery/from_celery.py +++ b/mediagoblin/init/celery/from_celery.py @@ -44,7 +44,7 @@ def setup_self(check_environ_for_conf=True, module_name=OUR_MODULENAME, if not os.path.exists(mgoblin_conf_file): raise IOError( "MEDIAGOBLIN_CONFIG not set or file does not exist") - + # By setting the environment variable here we should ensure that # this is the module that gets set up. os.environ['CELERY_CONFIG_MODULE'] = module_name diff --git a/mediagoblin/init/config.py b/mediagoblin/init/config.py index 029a0956..ae232e91 100644 --- a/mediagoblin/init/config.py +++ b/mediagoblin/init/config.py @@ -73,7 +73,7 @@ def read_mediagoblin_config(config_path, config_spec=CONFIG_SPEC_PATH): # For now the validator just works with the default functions, # but in the future if we want to add additional validation/configuration # functions we'd add them to validator.functions here. - # + # # See also: # http://www.voidspace.org.uk/python/validate.html#adding-functions validator = Validator() diff --git a/mediagoblin/listings/routing.py b/mediagoblin/listings/routing.py index b72bd015..234f2595 100644 --- a/mediagoblin/listings/routing.py +++ b/mediagoblin/listings/routing.py @@ -25,4 +25,3 @@ tag_routes = [ Route('mediagoblin.listings.tag_atom_feed', "/{tag}/atom/", controller="mediagoblin.listings.views:tag_atom_feed"), ] - diff --git a/mediagoblin/listings/views.py b/mediagoblin/listings/views.py index 01aad803..6b83ffcf 100644 --- a/mediagoblin/listings/views.py +++ b/mediagoblin/listings/views.py @@ -47,7 +47,7 @@ def tag_listing(request, page): {u'state': u'processed', u'tags.slug': tag_slug}) cursor = cursor.sort('created', DESCENDING) - + pagination = Pagination(page, cursor) media_entries = pagination() @@ -64,6 +64,7 @@ def tag_listing(request, page): ATOM_DEFAULT_NR_OF_UPDATED_ITEMS = 15 + def tag_atom_feed(request): """ generates the atom feed with the tag images @@ -85,7 +86,7 @@ def tag_atom_feed(request): feed.add(entry.get('title'), entry.get('description_html'), content_type='html', - author=entry.uploader()['username'], + author=entry.get_uploader().username, updated=entry.get('created'), url=entry.url_for_self(request.urlgen)) diff --git a/mediagoblin/meddleware/__init__.py b/mediagoblin/meddleware/__init__.py new file mode 100644 index 00000000..7ba70d87 --- /dev/null +++ b/mediagoblin/meddleware/__init__.py @@ -0,0 +1,32 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +ENABLED_MEDDLEWARE = ( + 'mediagoblin.meddleware.noop:NoOpMeddleware', + 'mediagoblin.meddleware.csrf:CsrfMeddleware', + ) + + +class BaseMeddleware(object): + + def __init__(self, mg_app): + self.app = mg_app + + def process_request(self, request, controller): + pass + + def process_response(self, request, response): + pass diff --git a/mediagoblin/middleware/csrf.py b/mediagoblin/meddleware/csrf.py index 7a5e352e..a4e4e5c6 100644 --- a/mediagoblin/middleware/csrf.py +++ b/mediagoblin/meddleware/csrf.py @@ -21,6 +21,7 @@ from webob.exc import HTTPForbidden from wtforms import Form, HiddenField, validators from mediagoblin import mg_globals +from mediagoblin.meddleware import BaseMeddleware # Use the system (hardware-based) random number generator if it exists. # -- this optimization is lifted from Django @@ -30,6 +31,13 @@ else: getrandbits = random.getrandbits +def csrf_exempt(func): + """Decorate a Controller to exempt it from CSRF protection.""" + + func.csrf_enabled = False + return func + + class CsrfForm(Form): """Simple form to handle rendering a CSRF token and confirming it is included in the POST.""" @@ -42,13 +50,16 @@ def render_csrf_form_token(request): """Render the CSRF token in a format suitable for inclusion in a form.""" + if 'CSRF_TOKEN' not in request.environ: + return None + form = CsrfForm(csrf_token=request.environ['CSRF_TOKEN']) return form.csrf_token -class CsrfMiddleware(object): - """CSRF Protection Middleware +class CsrfMeddleware(BaseMeddleware): + """CSRF Protection Meddleware Adds a CSRF Cookie to responses and verifies that it is present and matches the form token for non-safe requests. @@ -57,10 +68,7 @@ class CsrfMiddleware(object): CSRF_KEYLEN = 64 SAFE_HTTP_METHODS = ("GET", "HEAD", "OPTIONS", "TRACE") - def __init__(self, mg_app): - self.app = mg_app - - def process_request(self, request): + def process_request(self, request, controller): """For non-safe requests, confirm that the tokens are present and match. """ @@ -77,9 +85,11 @@ class CsrfMiddleware(object): # if this is a non-"safe" request (ie, one that could have # side effects), confirm that the CSRF tokens are present and # valid - if request.method not in self.SAFE_HTTP_METHODS \ - and ('gmg.verify_csrf' in request.environ or - 'paste.testing' not in request.environ): + if (getattr(controller, 'csrf_enabled', True) and + request.method not in self.SAFE_HTTP_METHODS and + ('gmg.verify_csrf' in request.environ or + 'paste.testing' not in request.environ) + ): return self.verify_tokens(request) @@ -98,7 +108,7 @@ class CsrfMiddleware(object): httponly=True) # update the Vary header - response.vary = (response.vary or []) + ['Cookie'] + response.vary = (getattr(response, 'vary', None) or []) + ['Cookie'] def _make_token(self, request): """Generate a new token to use for CSRF protection.""" diff --git a/mediagoblin/middleware/noop.py b/mediagoblin/meddleware/noop.py index 28380232..f5376494 100644 --- a/mediagoblin/middleware/noop.py +++ b/mediagoblin/meddleware/noop.py @@ -14,12 +14,13 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -class NoOpMiddleware(object): - def __init__(self, mg_app): - self.app = mg_app +from mediagoblin.meddleware import BaseMeddleware - def process_request(self, request): + +class NoOpMeddleware(BaseMeddleware): + + def process_request(self, request, controller): pass def process_response(self, request, response): diff --git a/mediagoblin/media_types/__init__.py b/mediagoblin/media_types/__init__.py new file mode 100644 index 00000000..6f94c714 --- /dev/null +++ b/mediagoblin/media_types/__init__.py @@ -0,0 +1,84 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os +import sys + +from mediagoblin import mg_globals +from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ + + +class FileTypeNotSupported(Exception): + pass + +class InvalidFileType(Exception): + pass + + +def get_media_types(): + """ + Generator, yields the available media types + """ + for media_type in mg_globals.app_config['media_types']: + yield media_type + + +def get_media_managers(): + ''' + Generator, yields all enabled media managers + ''' + for media_type in get_media_types(): + __import__(media_type) + + yield media_type, sys.modules[media_type].MEDIA_MANAGER + + +def get_media_manager(_media_type): + ''' + Get the MEDIA_MANAGER based on a media type string + + Example:: + get_media_type('mediagoblin.media_types.image') + ''' + if not _media_type: + return False + + for media_type, manager in get_media_managers(): + if media_type in _media_type: + return manager + + # Nope? Then raise an error + raise FileTypeNotSupported( + "MediaManager not in enabled types. Check media_types in config?") + + +def get_media_type_and_manager(filename): + ''' + Get the media type and manager based on a filename + ''' + for media_type, manager in get_media_managers(): + if filename.find('.') > 0: + # Get the file extension + ext = os.path.splitext(filename)[1].lower() + else: + raise InvalidFileType( + _('Could not find any file extension in "{filename}"').format( + filename=filename)) + + # Omit the dot from the extension and match it against + # the media manager + if ext[1:] in manager['accepted_extensions']: + return media_type, manager diff --git a/mediagoblin/media_types/image/__init__.py b/mediagoblin/media_types/image/__init__.py new file mode 100644 index 00000000..3b63d8eb --- /dev/null +++ b/mediagoblin/media_types/image/__init__.py @@ -0,0 +1,26 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +from mediagoblin.media_types.image.processing import process_image + + +MEDIA_MANAGER = { + "human_readable": "Image", + "processor": process_image, # alternately a string, + # 'mediagoblin.media_types.image.processing'? + "display_template": "mediagoblin/media_displays/image.html", + "default_thumb": "images/media_thumbs/image.jpg", + "accepted_extensions": ["jpg", "jpeg", "png", "gif", "tiff"]} diff --git a/mediagoblin/media_types/image/processing.py b/mediagoblin/media_types/image/processing.py new file mode 100644 index 00000000..e493eb2b --- /dev/null +++ b/mediagoblin/media_types/image/processing.py @@ -0,0 +1,109 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import Image +import os + +from mediagoblin import mg_globals as mgg + +from mediagoblin.processing import BadMediaFail, \ + create_pub_filepath, THUMB_SIZE, MEDIUM_SIZE + +################################ +# Media processing initial steps +################################ + + +def process_image(entry): + """ + Code to process an image + """ + workbench = mgg.workbench_manager.create_workbench() + # Conversions subdirectory to avoid collisions + conversions_subdir = os.path.join( + workbench.dir, 'conversions') + os.mkdir(conversions_subdir) + + queued_filepath = entry['queued_media_file'] + queued_filename = workbench.localized_file( + mgg.queue_store, queued_filepath, + 'source') + + filename_bits = os.path.splitext(queued_filename) + basename = os.path.split(filename_bits[0])[1] + extension = filename_bits[1].lower() + + try: + thumb = Image.open(queued_filename) + except IOError: + raise BadMediaFail() + + thumb.thumbnail(THUMB_SIZE, Image.ANTIALIAS) + + # Copy the thumb to the conversion subdir, then remotely. + thumb_filename = 'thumbnail' + extension + thumb_filepath = create_pub_filepath(entry, thumb_filename) + tmp_thumb_filename = os.path.join( + conversions_subdir, thumb_filename) + with file(tmp_thumb_filename, 'w') as thumb_file: + thumb.save(thumb_file) + mgg.public_store.copy_local_to_storage( + tmp_thumb_filename, thumb_filepath) + + # If the size of the original file exceeds the specified size of a `medium` + # file, a `medium.jpg` files is created and later associated with the media + # entry. + medium = Image.open(queued_filename) + medium_processed = False + + if medium.size[0] > MEDIUM_SIZE[0] or medium.size[1] > MEDIUM_SIZE[1]: + medium.thumbnail(MEDIUM_SIZE, Image.ANTIALIAS) + + medium_filename = 'medium' + extension + medium_filepath = create_pub_filepath(entry, medium_filename) + tmp_medium_filename = os.path.join( + conversions_subdir, medium_filename) + + with file(tmp_medium_filename, 'w') as medium_file: + medium.save(medium_file) + + mgg.public_store.copy_local_to_storage( + tmp_medium_filename, medium_filepath) + + medium_processed = True + + # we have to re-read because unlike PIL, not everything reads + # things in string representation :) + queued_file = file(queued_filename, 'rb') + + with queued_file: + #create_pub_filepath(entry, queued_filepath[-1]) + original_filepath = create_pub_filepath(entry, basename + extension) + + with mgg.public_store.get_file(original_filepath, 'wb') \ + as original_file: + original_file.write(queued_file.read()) + + mgg.queue_store.delete_file(queued_filepath) + entry['queued_media_file'] = [] + media_files_dict = entry.setdefault('media_files', {}) + media_files_dict['thumb'] = thumb_filepath + media_files_dict['original'] = original_filepath + if medium_processed: + media_files_dict['medium'] = medium_filepath + + # clean up workbench + workbench.destroy_self() diff --git a/mediagoblin/media_types/video/__init__.py b/mediagoblin/media_types/video/__init__.py new file mode 100644 index 00000000..a970ab01 --- /dev/null +++ b/mediagoblin/media_types/video/__init__.py @@ -0,0 +1,27 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +from mediagoblin.media_types.video.processing import process_video + + +MEDIA_MANAGER = { + "human_readable": "Video", + "processor": process_video, # alternately a string, + # 'mediagoblin.media_types.image.processing'? + "display_template": "mediagoblin/media_displays/video.html", + "default_thumb": "images/media_thumbs/video.jpg", + "accepted_extensions": [ + "mp4", "mov", "webm", "avi", "3gp", "3gpp", "mkv", "ogv", "ogg"]} diff --git a/mediagoblin/media_types/video/devices/web-advanced.json b/mediagoblin/media_types/video/devices/web-advanced.json new file mode 100644 index 00000000..ce1d22ff --- /dev/null +++ b/mediagoblin/media_types/video/devices/web-advanced.json @@ -0,0 +1,505 @@ +{ + "make": "Generic", + "model": "Web Browser (Advanced)", + "description": "Media for World Wide Web", + "version": "0.1", + "author": { + "name": "Dionisio E Alonso", + "email": "dealonso@gmail.com" + }, + "icon": "file://web.svg", + "default": "WebM 480p", + "presets": [ + { + "name": "H.264 720p", + "extension": "mp4", + "container": "qtmux", + "vcodec": { + "name": "x264enc", + "container": "qtmux", + "width": [ + 960, 1280 + ], + "height": [ + 720, 720 + ], + "rate": [ + 1, 30 + ], + "passes": [ + "pass=qual quantizer=23 subme=6 cabac=0 threads=0" + ] + }, + "acodec": { + "name": "faac", + "container": "qtmux", + "width": [ + 8, 24 + ], + "depth": [ + 8, 24 + ], + "rate": [ + 8000, 96000 + ], + "channels": [ + 1, 2 + ], + "passes": [ + "bitrate=131072 profile=LC" + ] + } + }, + { + "name": "WebM 720p", + "extension": "webm", + "container": "webmmux", + "icon": "file://web-webm.svg", + "vcodec": { + "name": "vp8enc", + "container": "webmmux", + "width": [ + 960, 1280 + ], + "height": [ + 720, 720 + ], + "rate": [ + 1, 30 + ], + "passes": [ + "quality=5.75 threads=%(threads)s speed=2" + ] + }, + "acodec": { + "name": "vorbisenc", + "container": "webmmux", + "width": [ + 8, 32 + ], + "depth": [ + 8, 24 + ], + "rate": [ + 8000, 96000 + ], + "channels": [ + 1, 2 + ], + "passes": [ + "quality=0.3" + ] + } + }, + { + "name": "Flash Video 720p", + "extension": "flv", + "icon": "file://web-flv.png", + "container": "flvmux", + "vcodec": { + "name": "x264enc", + "container": "flvmux", + "width": [ + 960, 1280 + ], + "height": [ + 720, 720 + ], + "rate": [ + 1, 30 + ], + "passes": [ + "pass=qual quantizer=23 subme=6 cabac=0 threads=0" + ] + }, + "acodec": { + "name": "faac", + "container": "flvmux", + "width": [ + 8, 24 + ], + "depth": [ + 8, 24 + ], + "rate": [ + 8000, 96000 + ], + "channels": [ + 1, 2 + ], + "passes": [ + "bitrate=131072 profile=LC" + ] + } + }, + + { + "name": "H.264 576p", + "extension": "mp4", + "container": "qtmux", + "vcodec": { + "name": "x264enc", + "container": "qtmux", + "width": [ + 768, 1024 + ], + "height": [ + 576, 576 + ], + "rate": [ + 1, 30 + ], + "passes": [ + "pass=qual quantizer=23 subme=6 cabac=0 threads=0" + ] + }, + "acodec": { + "name": "faac", + "container": "qtmux", + "width": [ + 8, 24 + ], + "depth": [ + 8, 24 + ], + "rate": [ + 8000, 96000 + ], + "channels": [ + 1, 2 + ], + "passes": [ + "bitrate=131072 profile=LC" + ] + } + }, + { + "name": "WebM 576p", + "extension": "webm", + "container": "webmmux", + "icon": "file://web-webm.svg", + "vcodec": { + "name": "vp8enc", + "container": "webmmux", + "width": [ + 768, 1024 + ], + "height": [ + 576, 576 + ], + "rate": [ + 1, 30 + ], + "passes": [ + "quality=5.75 threads=%(threads)s speed=2" + ] + }, + "acodec": { + "name": "vorbisenc", + "container": "webmmux", + "width": [ + 8, 32 + ], + "depth": [ + 8, 24 + ], + "rate": [ + 8000, 96000 + ], + "channels": [ + 1, 2 + ], + "passes": [ + "quality=0.3" + ] + } + }, + { + "name": "Flash Video 576p", + "extension": "flv", + "icon": "file://web-flv.png", + "container": "flvmux", + "vcodec": { + "name": "x264enc", + "container": "flvmux", + "width": [ + 768, 1024 + ], + "height": [ + 576, 576 + ], + "rate": [ + 1, 30 + ], + "passes": [ + "pass=qual quantizer=23 subme=6 cabac=0 threads=0" + ] + }, + "acodec": { + "name": "faac", + "container": "flvmux", + "width": [ + 8, 24 + ], + "depth": [ + 8, 24 + ], + "rate": [ + 8000, 96000 + ], + "channels": [ + 1, 2 + ], + "passes": [ + "bitrate=131072 profile=LC" + ] + } + }, + + { + "name": "H.264 480p", + "extension": "mp4", + "container": "qtmux", + "vcodec": { + "name": "x264enc", + "container": "qtmux", + "width": [ + 640, 854 + ], + "height": [ + 480, 480 + ], + "rate": [ + 1, 30 + ], + "passes": [ + "pass=qual quantizer=23 subme=6 cabac=0 threads=0" + ] + }, + "acodec": { + "name": "faac", + "container": "qtmux", + "width": [ + 8, 24 + ], + "depth": [ + 8, 24 + ], + "rate": [ + 8000, 96000 + ], + "channels": [ + 1, 2 + ], + "passes": [ + "bitrate=131072 profile=LC" + ] + } + }, + { + "name": "WebM 480p", + "extension": "webm", + "container": "webmmux", + "icon": "file://web-webm.svg", + "vcodec": { + "name": "vp8enc", + "container": "webmmux", + "width": [ + 640, 854 + ], + "height": [ + 480, 480 + ], + "rate": [ + 1, 30 + ], + "passes": [ + "quality=5.75 threads=%(threads)s speed=2" + ] + }, + "acodec": { + "name": "vorbisenc", + "container": "webmmux", + "width": [ + 8, 32 + ], + "depth": [ + 8, 24 + ], + "rate": [ + 8000, 96000 + ], + "channels": [ + 1, 2 + ], + "passes": [ + "quality=0.3" + ] + } + }, + { + "name": "Flash Video 480p", + "extension": "flv", + "icon": "file://web-flv.png", + "container": "flvmux", + "vcodec": { + "name": "x264enc", + "container": "flvmux", + "width": [ + 640, 854 + ], + "height": [ + 480, 480 + ], + "rate": [ + 1, 30 + ], + "passes": [ + "pass=qual quantizer=23 subme=6 cabac=0 threads=0" + ] + }, + "acodec": { + "name": "faac", + "container": "flvmux", + "width": [ + 8, 24 + ], + "depth": [ + 8, 24 + ], + "rate": [ + 8000, 96000 + ], + "channels": [ + 1, 2 + ], + "passes": [ + "bitrate=131072 profile=LC" + ] + } + }, + + { + "name": "H.264 360p", + "extension": "mp4", + "container": "qtmux", + "vcodec": { + "name": "x264enc", + "container": "qtmux", + "width": [ + 480, 640 + ], + "height": [ + 360, 360 + ], + "rate": [ + 1, 30 + ], + "passes": [ + "pass=qual quantizer=23 subme=6 cabac=0 threads=0" + ] + }, + "acodec": { + "name": "faac", + "container": "qtmux", + "width": [ + 8, 24 + ], + "depth": [ + 8, 24 + ], + "rate": [ + 8000, 96000 + ], + "channels": [ + 1, 2 + ], + "passes": [ + "bitrate=131072 profile=LC" + ] + } + }, + { + "name": "WebM 360p", + "extension": "webm", + "container": "webmmux", + "icon": "file://web-webm.svg", + "vcodec": { + "name": "vp8enc", + "container": "webmmux", + "width": [ + 480, 640 + ], + "height": [ + 360, 360 + ], + "rate": [ + 1, 30 + ], + "passes": [ + "quality=5.75 threads=%(threads)s speed=2" + ] + }, + "acodec": { + "name": "vorbisenc", + "container": "webmmux", + "width": [ + 8, 32 + ], + "depth": [ + 8, 24 + ], + "rate": [ + 8000, 96000 + ], + "channels": [ + 1, 2 + ], + "passes": [ + "quality=0.3" + ] + } + }, + { + "name": "Flash Video 360p", + "extension": "flv", + "icon": "file://web-flv.png", + "container": "flvmux", + "vcodec": { + "name": "x264enc", + "container": "flvmux", + "width": [ + 480, 640 + ], + "height": [ + 360, 360 + ], + "rate": [ + 1, 30 + ], + "passes": [ + "pass=qual quantizer=23 subme=6 cabac=0 threads=0" + ] + }, + "acodec": { + "name": "faac", + "container": "flvmux", + "width": [ + 8, 24 + ], + "depth": [ + 8, 24 + ], + "rate": [ + 8000, 96000 + ], + "channels": [ + 1, 2 + ], + "passes": [ + "bitrate=131072 profile=LC" + ] + } + } + ] +} diff --git a/mediagoblin/media_types/video/devices/web-flv.png b/mediagoblin/media_types/video/devices/web-flv.png Binary files differnew file mode 100644 index 00000000..b75699f4 --- /dev/null +++ b/mediagoblin/media_types/video/devices/web-flv.png diff --git a/mediagoblin/media_types/video/devices/web-webm.svg b/mediagoblin/media_types/video/devices/web-webm.svg new file mode 100644 index 00000000..4e5b3e97 --- /dev/null +++ b/mediagoblin/media_types/video/devices/web-webm.svg @@ -0,0 +1,259 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="48px" + height="48px" + id="svg2816" + version="1.1" + inkscape:version="0.47 r22583" + sodipodi:docname="web-webm.svg"> + <defs + id="defs2818"> + <linearGradient + id="linearGradient3656"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop3658" /> + <stop + style="stop-color:#000000;stop-opacity:0;" + offset="1" + id="stop3660" /> + </linearGradient> + <linearGradient + id="linearGradient3632"> + <stop + style="stop-color:#ffffff;stop-opacity:0.54901963;" + offset="0" + id="stop3634" /> + <stop + style="stop-color:#ffffff;stop-opacity:0;" + offset="1" + id="stop3636" /> + </linearGradient> + <linearGradient + id="linearGradient3622"> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="0" + id="stop3624" /> + <stop + style="stop-color:#d3d7cf;stop-opacity:1;" + offset="1" + id="stop3626" /> + </linearGradient> + <linearGradient + id="linearGradient3600"> + <stop + style="stop-color:#8ae234;stop-opacity:1;" + offset="0" + id="stop3602" /> + <stop + style="stop-color:#4e9a06;stop-opacity:1;" + offset="1" + id="stop3604" /> + </linearGradient> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 24 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="48 : 24 : 1" + inkscape:persp3d-origin="24 : 16 : 1" + id="perspective2824" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3600" + id="linearGradient3606" + x1="20.256382" + y1="2.546674" + x2="20.256382" + y2="46.881901" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3622" + id="linearGradient3628" + x1="21.2349" + y1="7.948472" + x2="21.2349" + y2="40.191879" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3632" + id="linearGradient3638" + x1="6.4826794" + y1="4.543263" + x2="25.363527" + y2="35.227882" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0,-0.35355339)" /> + <inkscape:perspective + id="perspective3693" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3600-5" + id="linearGradient3606-9" + x1="20.256382" + y1="2.546674" + x2="20.256382" + y2="46.881901" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient3600-5"> + <stop + style="stop-color:#8ae234;stop-opacity:1;" + offset="0" + id="stop3602-7" /> + <stop + style="stop-color:#4e9a06;stop-opacity:1;" + offset="1" + id="stop3604-2" /> + </linearGradient> + <filter + inkscape:collect="always" + id="filter3731"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="0.82730657" + id="feGaussianBlur3733" /> + </filter> + <inkscape:perspective + id="perspective3749" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective3782" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="8" + inkscape:cx="20.51741" + inkscape:cy="22.534228" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:grid-bbox="true" + inkscape:document-units="px" + showguides="true" + inkscape:guide-bbox="true" + inkscape:window-width="1099" + inkscape:window-height="834" + inkscape:window-x="801" + inkscape:window-y="106" + inkscape:window-maximized="0"> + <inkscape:grid + type="xygrid" + id="grid3608" /> + </sodipodi:namedview> + <metadata + id="metadata2821"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <path + sodipodi:type="star" + style="fill:#000000;fill-opacity:0.2869955;stroke:none;filter:url(#filter3731)" + id="path3598-4" + sodipodi:sides="3" + sodipodi:cx="13.857143" + sodipodi:cy="24.714287" + sodipodi:r1="25.596954" + sodipodi:r2="12.798477" + sodipodi:arg1="0" + sodipodi:arg2="1.0471976" + inkscape:flatsided="false" + inkscape:rounded="0" + inkscape:randomized="0" + d="M 39.454098,24.714287 20.256381,35.798093 1.0586662,46.8819 l 0,-22.167614 0,-22.1676119 19.1977168,11.0838069 19.197715,11.083806 z" + transform="matrix(1.0537808,0,0,1.0537808,3.6163385,-1.9600717)" /> + <path + sodipodi:type="star" + style="fill:url(#linearGradient3606);fill-opacity:1;stroke:#366a04;stroke-width:1.05497880999999993;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-linejoin:round" + id="path3598" + sodipodi:sides="3" + sodipodi:cx="13.857143" + sodipodi:cy="24.714287" + sodipodi:r1="25.596954" + sodipodi:r2="12.798477" + sodipodi:arg1="0" + sodipodi:arg2="1.0471976" + inkscape:flatsided="false" + inkscape:rounded="0" + inkscape:randomized="0" + d="M 39.454098,24.714287 20.256381,35.798093 1.0586662,46.8819 l 0,-22.167614 0,-22.1676119 19.1977168,11.0838069 19.197715,11.083806 z" + transform="matrix(0.94788634,0,0,0.94788634,5.0257749,0.56128794)" /> + <path + style="fill:url(#linearGradient3628);stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" + d="m 6.5304575,9.646791 8.7347075,20.091724 4.674611,-18.160553 4.525987,2.612472 3.885316,12.559503 4.403755,-7.765833 1.744319,1.009296 -2.127799,9.211229 -6.155446,3.554753 -4.028978,-9.439016 -2.255629,13.086534 -5.852703,3.373025 -7.5584205,-9.989634 0.01028,-20.1435 z" + id="path3620" + sodipodi:nodetypes="cccccccccccccc" /> + <path + style="fill:none;stroke:url(#linearGradient3638);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 6.9826793,42.785087 0,-38.0953773 32.9068657,18.9987873" + id="path3630" + sodipodi:nodetypes="ccc" /> + <path + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.15686275" + d="M 6.6184028,8.6135689 15.026019,28.134068 19.45616,10.995613" + id="path3739" + sodipodi:nodetypes="ccc" /> + <path + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.15686275" + d="m 25.081121,14.552251 3.345117,11.020499 3.93014,-6.825955" + id="path3739-5" + sodipodi:nodetypes="ccc" /> + <path + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.15686275" + d="m 6.6291261,30.85266 7.0710679,9.280777" + id="path3772" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.15686275" + d="m 34.736621,20.290253 -2.032932,8.794642" + id="path3772-6" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.15686275" + d="m 20.594485,35.934991 1.811961,-10.650796 3.270369,7.778174" + id="path3796" + sodipodi:nodetypes="ccc" /> + </g> +</svg> diff --git a/mediagoblin/media_types/video/devices/web.svg b/mediagoblin/media_types/video/devices/web.svg new file mode 100644 index 00000000..c0c68244 --- /dev/null +++ b/mediagoblin/media_types/video/devices/web.svg @@ -0,0 +1,982 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="48px"
+ height="48px"
+ id="svg3440"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/apps"
+ sodipodi:docname="internet-web-browser.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <defs
+ id="defs3">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 24 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="48 : 24 : 1"
+ inkscape:persp3d-origin="24 : 16 : 1"
+ id="perspective156" />
+ <linearGradient
+ id="linearGradient4750">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop4752" />
+ <stop
+ style="stop-color:#fefefe;stop-opacity:1.0000000;"
+ offset="0.37931034"
+ id="stop4758" />
+ <stop
+ style="stop-color:#1d1d1d;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop4754" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient4350">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop4352" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop4354" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4126">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop4128" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.16494845;"
+ offset="1.0000000"
+ id="stop4130" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient4114">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop4116" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop4118" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3962">
+ <stop
+ style="stop-color:#d3e9ff;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop3964" />
+ <stop
+ style="stop-color:#d3e9ff;stop-opacity:1.0000000;"
+ offset="0.15517241"
+ id="stop4134" />
+ <stop
+ style="stop-color:#4074ae;stop-opacity:1.0000000;"
+ offset="0.75000000"
+ id="stop4346" />
+ <stop
+ style="stop-color:#36486c;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop3966" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3962"
+ id="radialGradient3968"
+ gradientTransform="scale(0.999989,1.000011)"
+ cx="18.247644"
+ cy="15.716079"
+ fx="18.247644"
+ fy="15.716079"
+ r="29.993349"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4114"
+ id="radialGradient4120"
+ gradientTransform="scale(1.643990,0.608276)"
+ cx="15.115514"
+ cy="63.965388"
+ fx="15.115514"
+ fy="63.965388"
+ r="12.289036"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4126"
+ id="radialGradient4132"
+ gradientTransform="scale(0.999989,1.000011)"
+ cx="15.601279"
+ cy="12.142302"
+ fx="15.601279"
+ fy="12.142302"
+ r="43.526714"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4350"
+ id="radialGradient4356"
+ gradientTransform="scale(1.179536,0.847791)"
+ cx="11.826907"
+ cy="10.476453"
+ fx="11.826907"
+ fy="10.476453"
+ r="32.664848"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4750"
+ id="radialGradient4756"
+ gradientTransform="scale(1.036822,0.964486)"
+ cx="18.633780"
+ cy="17.486208"
+ fx="18.934305"
+ fy="17.810213"
+ r="40.692665"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1460"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1462"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1466"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1468"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1470"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1474"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1476"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1478"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1482"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1484"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1486"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1490"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1492"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1494"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1498"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1500"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1502"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1506"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1508"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1510"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1514"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1516"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1518"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1522"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1524"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1526"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1528"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1530"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1532"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1534"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1536"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1538"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1540"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1542"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1544"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1546"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1550"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1552"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1554"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ <radialGradient
+ r="40.692665"
+ fy="17.810213"
+ fx="18.934305"
+ cy="17.486208"
+ cx="18.633780"
+ gradientTransform="scale(1.036822,0.964486)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1558"
+ xlink:href="#linearGradient4750"
+ inkscape:collect="always" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="0.17254902"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="9.8994949"
+ inkscape:cx="25.799661"
+ inkscape:cy="24.622653"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:grid-bbox="true"
+ inkscape:document-units="px"
+ inkscape:window-width="1440"
+ inkscape:window-height="823"
+ inkscape:window-x="0"
+ inkscape:window-y="30"
+ inkscape:showpageshadow="false" />
+ <metadata
+ id="metadata4">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Globe</dc:title>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Jakub Steiner</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:contributor>
+ <cc:Agent>
+ <dc:title>Tuomas Kuosmanen</dc:title>
+ </cc:Agent>
+ </dc:contributor>
+ <cc:license
+ rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+ <dc:source>http://jimmac.musichall.cz</dc:source>
+ <dc:subject>
+ <rdf:Bag>
+ <rdf:li>globe</rdf:li>
+ <rdf:li>international</rdf:li>
+ <rdf:li>web</rdf:li>
+ <rdf:li>www</rdf:li>
+ <rdf:li>internet</rdf:li>
+ <rdf:li>network</rdf:li>
+ </rdf:Bag>
+ </dc:subject>
+ </cc:Work>
+ <cc:License
+ rdf:about="http://creativecommons.org/licenses/publicdomain/">
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Reproduction" />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Distribution" />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="layer1"
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer">
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#radialGradient4120);fill-opacity:1.0000000;stroke:none;stroke-opacity:1.0000000"
+ id="path4112"
+ sodipodi:cx="24.849752"
+ sodipodi:cy="38.908627"
+ sodipodi:rx="20.203051"
+ sodipodi:ry="7.4751287"
+ d="M 45.052803 38.908627 A 20.203051 7.4751287 0 1 1 4.6467018,38.908627 A 20.203051 7.4751287 0 1 1 45.052803 38.908627 z"
+ transform="matrix(1.000000,0.000000,0.000000,1.243244,0.000000,-10.27241)" />
+ <path
+ style="fill:url(#radialGradient3968);fill-opacity:1.0000000;fill-rule:nonzero;stroke:#39396c;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 43.959853,23.485499 C 43.959853,34.195217 35.277750,42.877222 24.569505,42.877222 C 13.860279,42.877222 5.1786663,34.195119 5.1786663,23.485499 C 5.1786663,12.776272 13.860279,4.0951517 24.569505,4.0951517 C 35.277750,4.0951517 43.959853,12.776272 43.959853,23.485499 L 43.959853,23.485499 z "
+ id="path3214" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.42159382;fill:url(#radialGradient4356);fill-opacity:1.0000000;stroke:none;stroke-opacity:1.0000000"
+ id="path4348"
+ sodipodi:cx="17.778685"
+ sodipodi:cy="15.271057"
+ sodipodi:rx="12.929953"
+ sodipodi:ry="9.2934036"
+ d="M 30.708637 15.271057 A 12.929953 9.2934036 0 1 1 4.8487320,15.271057 A 12.929953 9.2934036 0 1 1 30.708637 15.271057 z"
+ transform="matrix(0.835938,0.000000,0.000000,1.000000,9.886868,0.000000)" />
+ <g
+ id="g4136"
+ style="fill:#000000;fill-opacity:0.71345031;fill-rule:nonzero;stroke:none;stroke-miterlimit:4.0000000"
+ transform="matrix(0.982371,0.000000,0.000000,0.982371,0.121079,0.232914)">
+ <g
+ id="g4138">
+ <g
+ id="g4142">
+ <path
+ d="M 44.071300,20.714400 C 44.071300,20.977100 44.071300,20.714400 44.071300,20.714400 L 43.526400,21.331600 C 43.192400,20.938000 42.817400,20.607000 42.436600,20.261300 L 41.600700,20.384300 L 40.837000,19.521000 L 40.837000,20.589400 L 41.491300,21.084500 L 41.926800,21.577700 L 42.508800,20.919500 C 42.655300,21.193900 42.799800,21.468300 42.945300,21.742700 L 42.945300,22.565000 L 42.290000,23.305200 L 41.090800,24.128400 L 40.182600,25.034700 L 39.600600,24.374500 L 39.891600,23.634300 L 39.310500,22.976100 L 38.329100,20.878400 L 37.493200,19.933100 L 37.274400,20.179200 L 37.602500,21.372600 L 38.219700,22.071800 C 38.572200,23.089400 38.920900,24.062000 39.383800,25.034700 C 40.101600,25.034700 40.778300,24.958500 41.491200,24.868700 L 41.491200,25.444900 L 40.619100,27.584100 L 39.819300,28.488400 L 39.165000,29.888800 C 39.165000,30.656400 39.165000,31.424000 39.165000,32.191500 L 39.383800,33.097800 L 39.020500,33.508000 L 38.219700,34.002100 L 37.383800,34.701300 L 38.075200,35.482600 L 37.129900,36.306800 L 37.311500,36.840000 L 35.893500,38.445500 L 34.949200,38.445500 L 34.149400,38.939600 L 33.639600,38.939600 L 33.639600,38.281400 L 33.422800,36.963000 C 33.141500,36.136800 32.848600,35.316500 32.550700,34.496200 C 32.550700,33.890700 32.586800,33.291100 32.623000,32.685700 L 32.987300,31.863400 L 32.477500,30.875100 L 32.514600,29.517700 L 31.823200,28.736400 L 32.168900,27.605500 L 31.606400,26.967300 L 30.624000,26.967300 L 30.296900,26.597200 L 29.315500,27.214900 L 28.916100,26.761300 L 28.006900,27.543000 C 27.389700,26.843300 26.771500,26.144100 26.153400,25.444900 L 25.426800,23.716400 L 26.081100,22.730100 L 25.717800,22.319000 L 26.516600,20.425400 C 27.172900,19.609000 27.858400,18.825800 28.551800,18.039700 L 29.788100,17.710600 L 31.169000,17.546500 L 32.114300,17.793600 L 33.459000,19.150000 L 33.931700,18.615800 L 34.585000,18.533800 L 35.821300,18.944900 L 36.766600,18.944900 L 37.420900,18.368700 L 37.711900,17.957600 L 37.056600,17.546500 L 35.965800,17.464500 C 35.663100,17.044600 35.381800,16.603200 35.022400,16.230100 L 34.658100,16.394200 L 34.512600,17.464500 L 33.858300,16.724300 L 33.713800,15.900100 L 32.987200,15.325900 L 32.695200,15.325900 L 33.422700,16.148200 L 33.131700,16.888400 L 32.550600,17.052500 L 32.913900,16.312300 L 32.258600,15.984200 L 31.678500,15.326000 L 30.586700,15.572100 L 30.442200,15.900200 L 29.787900,16.312300 L 29.424600,17.217600 L 28.516400,17.669700 L 28.116000,17.217600 L 27.680500,17.217600 L 27.680500,15.736200 L 28.625800,15.242100 L 29.352400,15.242100 L 29.205900,14.666900 L 28.625800,14.090700 L 29.606300,13.884600 L 30.151200,13.268400 L 30.586700,12.527200 L 31.387500,12.527200 L 31.168700,11.952000 L 31.678500,11.622900 L 31.678500,12.281100 L 32.768300,12.527200 L 33.858100,11.622900 L 33.931300,11.210800 L 34.875600,10.553100 C 34.533800,10.595600 34.192000,10.626800 33.858000,10.717700 L 33.858000,9.9766000 L 34.221300,9.1538000 L 33.858000,9.1538000 L 33.059600,9.8940000 L 32.840800,10.305600 L 33.059600,10.882300 L 32.695300,11.868600 L 32.114200,11.539500 L 31.606400,10.964300 L 30.805600,11.539500 L 30.514600,10.223600 L 31.895500,9.3188000 L 31.895500,8.8247000 L 32.768500,8.2490000 L 34.149400,7.9194000 L 35.094700,8.2490000 L 36.838800,8.5781000 L 36.403300,9.0713000 L 35.458000,9.0713000 L 36.403300,10.058600 L 37.129900,9.2363000 L 37.350600,8.8745000 C 37.350600,8.8745000 40.137700,11.372500 41.730500,14.105000 C 43.323300,16.838400 44.071300,20.060100 44.071300,20.714400 z "
+ id="path4144" />
+ </g>
+ </g>
+ <g
+ id="g4146">
+ <g
+ id="g4150">
+ <path
+ d="M 26.070300,9.2363000 L 25.997100,9.7295000 L 26.506900,10.058600 L 27.378000,9.4829000 L 26.942500,8.9892000 L 26.360500,9.3188000 L 26.070500,9.2363000"
+ id="path4152" />
+ </g>
+ </g>
+ <g
+ id="g4154">
+ <g
+ id="g4158">
+ <path
+ d="M 26.870100,5.8633000 L 24.979500,5.1226000 L 22.799800,5.3692000 L 20.109400,6.1094000 L 19.600600,6.6035000 L 21.272500,7.7549000 L 21.272500,8.4131000 L 20.618200,9.0713000 L 21.491200,10.800300 L 22.071300,10.470200 L 22.799800,9.3188000 C 23.922800,8.9716000 24.929700,8.5781000 25.997100,8.0844000 L 26.870100,5.8632000"
+ id="path4160" />
+ </g>
+ </g>
+ <g
+ id="g4162">
+ <g
+ id="g4166">
+ <path
+ d="M 28.833000,12.774900 L 28.542000,12.033700 L 28.032200,12.198700 L 28.178700,13.103000 L 28.833000,12.774900"
+ id="path4168" />
+ </g>
+ </g>
+ <g
+ id="g4170">
+ <g
+ id="g4174">
+ <path
+ d="M 29.123000,12.608900 L 28.977500,13.597200 L 29.777300,13.432200 L 30.358400,12.857000 L 29.849600,12.362900 C 29.678700,11.907800 29.482400,11.483000 29.268500,11.046500 L 28.833000,11.046500 L 28.833000,11.539700 L 29.123000,11.868800 L 29.123000,12.609000"
+ id="path4176" />
+ </g>
+ </g>
+ <g
+ id="g4178">
+ <g
+ id="g4182">
+ <path
+ d="M 18.365200,28.242200 L 17.783200,27.089900 L 16.692900,26.843300 L 16.111400,25.280800 L 14.657800,25.444900 L 13.422400,24.540600 L 12.113300,25.692000 L 12.113300,25.873600 C 11.717300,25.759300 11.230500,25.743700 10.877900,25.526900 L 10.586900,24.704600 L 10.586900,23.799300 L 9.7148000,23.881300 C 9.7876000,23.305100 9.8598000,22.729900 9.9331000,22.153800 L 9.4238000,22.153800 L 8.9155000,22.812000 L 8.4062000,23.058100 L 7.6791000,22.647900 L 7.6063000,21.742600 L 7.7518000,20.755300 L 8.8426000,19.933000 L 9.7147000,19.933000 L 9.8597000,19.438900 L 10.950000,19.685000 L 11.749800,20.673300 L 11.895300,19.026800 L 13.276600,17.875400 L 13.785400,16.641000 L 14.803000,16.229900 L 15.384500,15.407600 L 16.692600,15.159600 L 17.347400,14.173300 C 16.693100,14.173300 16.038800,14.173300 15.384500,14.173300 L 16.620300,13.597100 L 17.491900,13.597100 L 18.728200,13.185000 L 18.873700,12.692800 L 18.437200,12.280700 L 17.928400,12.115700 L 18.073900,11.622500 L 17.710600,10.882300 L 16.838000,11.210400 L 16.983500,10.552700 L 15.965900,9.9765000 L 15.166600,11.374400 L 15.238900,11.868500 L 14.439600,12.198600 L 13.930300,13.267900 L 13.712500,12.280600 L 12.331200,11.704400 L 12.112900,10.964200 L 13.930300,9.8939000 L 14.730100,9.1537000 L 14.802900,8.2489000 L 14.366900,8.0018000 L 13.785400,7.9193000 L 13.422100,8.8246000 C 13.422100,8.8246000 12.814200,8.9437000 12.657900,8.9823000 C 10.661800,10.821700 6.6286000,14.792400 5.6916000,22.288500 C 5.7287000,22.462300 6.3708000,23.470100 6.3708000,23.470100 L 7.8972000,24.374400 L 9.4236000,24.786500 L 10.078400,25.609700 L 11.095500,26.349900 L 11.677000,26.267900 L 12.113000,26.464200 L 12.113000,26.597000 L 11.531900,28.160000 L 11.095400,28.818200 L 11.240900,29.148300 L 10.877600,30.380700 L 12.186200,32.767400 L 13.494300,33.919700 L 14.076300,34.742000 L 14.003100,36.470500 L 14.439600,37.456800 L 14.003100,39.349400 C 14.003100,39.349400 13.968900,39.337700 14.024600,39.527100 C 14.080800,39.716600 16.353700,40.978300 16.498200,40.870900 C 16.642200,40.761500 16.765300,40.665800 16.765300,40.665800 L 16.620300,40.255600 L 17.201400,39.679400 L 17.419700,39.103200 L 18.365000,38.773100 L 19.091600,36.962600 L 18.873800,36.470400 L 19.381600,35.730200 L 20.472400,35.482200 L 21.054400,34.165800 L 20.908900,32.521300 L 21.781000,31.286900 L 21.926500,30.052500 C 20.733100,29.460700 19.549500,28.851300 18.365000,28.242000"
+ id="path4184" />
+ </g>
+ </g>
+ <g
+ id="g4186">
+ <g
+ id="g4190">
+ <path
+ d="M 16.765600,9.5649000 L 17.492200,10.058600 L 18.074200,10.058600 L 18.074200,9.4829000 L 17.347600,9.1538000 L 16.765600,9.5649000"
+ id="path4192" />
+ </g>
+ </g>
+ <g
+ id="g4194">
+ <g
+ id="g4198">
+ <path
+ d="M 14.876000,8.9072000 L 14.512200,9.8120000 L 15.239300,9.8120000 L 15.603100,8.9892000 C 15.916600,8.7675000 16.228600,8.5444000 16.547900,8.3310000 L 17.275000,8.5781000 C 17.759400,8.9072000 18.243800,9.2363000 18.728600,9.5649000 L 19.456100,8.9072000 L 18.655800,8.5781000 L 18.292000,7.8374000 L 16.911100,7.6728000 L 16.838300,7.2612000 L 16.184000,7.4262000 L 15.893600,8.0020000 L 15.529800,7.2613000 L 15.384800,7.5904000 L 15.457600,8.4132000 L 14.876000,8.9072000"
+ id="path4200" />
+ </g>
+ </g>
+ <g
+ id="g4202">
+ <g
+ style="opacity:0.75000000"
+ id="g4204">
+ <path
+ id="path4206"
+ d="" />
+ </g>
+ <g
+ id="g4208">
+ <path
+ id="path4210"
+ d="" />
+ </g>
+ </g>
+ <g
+ id="g4212">
+ <g
+ style="opacity:0.75000000"
+ id="g4214">
+ <path
+ id="path4216"
+ d="" />
+ </g>
+ <g
+ id="g4218">
+ <path
+ id="path4220"
+ d="" />
+ </g>
+ </g>
+ <g
+ id="g4222">
+ <g
+ id="g4226">
+ <path
+ d="M 17.492200,6.8496000 L 17.856000,6.5210000 L 18.583100,6.3564000 C 19.081100,6.1142000 19.581100,5.9511000 20.109500,5.7802000 L 19.819500,5.2865000 L 18.881000,5.4213000 L 18.437600,5.8632000 L 17.706600,5.9692000 L 17.056700,6.2744000 L 16.740800,6.4272000 L 16.547900,6.6855000 L 17.492200,6.8496000"
+ id="path4228" />
+ </g>
+ </g>
+ <g
+ id="g4230">
+ <g
+ id="g4234">
+ <path
+ d="M 18.728500,14.666500 L 19.165000,14.008300 L 18.510200,13.515100 L 18.728500,14.666500"
+ id="path4236" />
+ </g>
+ </g>
+ </g>
+ <g
+ id="g3216"
+ style="color:#000000;fill:url(#radialGradient1460);fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:1.0179454;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+ transform="matrix(0.982371,0.000000,0.000000,0.982371,-8.095179e-2,3.088300e-2)">
+ <g
+ id="g3218"
+ style="color:#000000;fill:url(#radialGradient1462);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible">
+ <g
+ id="g3222"
+ style="color:#000000;fill:url(#radialGradient1466);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible">
+ <path
+ d="M 44.071300,20.714400 C 44.071300,20.977100 44.071300,20.714400 44.071300,20.714400 L 43.526400,21.331600 C 43.192400,20.938000 42.817400,20.607000 42.436600,20.261300 L 41.600700,20.384300 L 40.837000,19.521000 L 40.837000,20.589400 L 41.491300,21.084500 L 41.926800,21.577700 L 42.508800,20.919500 C 42.655300,21.193900 42.799800,21.468300 42.945300,21.742700 L 42.945300,22.565000 L 42.290000,23.305200 L 41.090800,24.128400 L 40.182600,25.034700 L 39.600600,24.374500 L 39.891600,23.634300 L 39.310500,22.976100 L 38.329100,20.878400 L 37.493200,19.933100 L 37.274400,20.179200 L 37.602500,21.372600 L 38.219700,22.071800 C 38.572200,23.089400 38.920900,24.062000 39.383800,25.034700 C 40.101600,25.034700 40.778300,24.958500 41.491200,24.868700 L 41.491200,25.444900 L 40.619100,27.584100 L 39.819300,28.488400 L 39.165000,29.888800 C 39.165000,30.656400 39.165000,31.424000 39.165000,32.191500 L 39.383800,33.097800 L 39.020500,33.508000 L 38.219700,34.002100 L 37.383800,34.701300 L 38.075200,35.482600 L 37.129900,36.306800 L 37.311500,36.840000 L 35.893500,38.445500 L 34.949200,38.445500 L 34.149400,38.939600 L 33.639600,38.939600 L 33.639600,38.281400 L 33.422800,36.963000 C 33.141500,36.136800 32.848600,35.316500 32.550700,34.496200 C 32.550700,33.890700 32.586800,33.291100 32.623000,32.685700 L 32.987300,31.863400 L 32.477500,30.875100 L 32.514600,29.517700 L 31.823200,28.736400 L 32.168900,27.605500 L 31.606400,26.967300 L 30.624000,26.967300 L 30.296900,26.597200 L 29.315500,27.214900 L 28.916100,26.761300 L 28.006900,27.543000 C 27.389700,26.843300 26.771500,26.144100 26.153400,25.444900 L 25.426800,23.716400 L 26.081100,22.730100 L 25.717800,22.319000 L 26.516600,20.425400 C 27.172900,19.609000 27.858400,18.825800 28.551800,18.039700 L 29.788100,17.710600 L 31.169000,17.546500 L 32.114300,17.793600 L 33.459000,19.150000 L 33.931700,18.615800 L 34.585000,18.533800 L 35.821300,18.944900 L 36.766600,18.944900 L 37.420900,18.368700 L 37.711900,17.957600 L 37.056600,17.546500 L 35.965800,17.464500 C 35.663100,17.044600 35.381800,16.603200 35.022400,16.230100 L 34.658100,16.394200 L 34.512600,17.464500 L 33.858300,16.724300 L 33.713800,15.900100 L 32.987200,15.325900 L 32.695200,15.325900 L 33.422700,16.148200 L 33.131700,16.888400 L 32.550600,17.052500 L 32.913900,16.312300 L 32.258600,15.984200 L 31.678500,15.326000 L 30.586700,15.572100 L 30.442200,15.900200 L 29.787900,16.312300 L 29.424600,17.217600 L 28.516400,17.669700 L 28.116000,17.217600 L 27.680500,17.217600 L 27.680500,15.736200 L 28.625800,15.242100 L 29.352400,15.242100 L 29.205900,14.666900 L 28.625800,14.090700 L 29.606300,13.884600 L 30.151200,13.268400 L 30.586700,12.527200 L 31.387500,12.527200 L 31.168700,11.952000 L 31.678500,11.622900 L 31.678500,12.281100 L 32.768300,12.527200 L 33.858100,11.622900 L 33.931300,11.210800 L 34.875600,10.553100 C 34.533800,10.595600 34.192000,10.626800 33.858000,10.717700 L 33.858000,9.9766000 L 34.221300,9.1538000 L 33.858000,9.1538000 L 33.059600,9.8940000 L 32.840800,10.305600 L 33.059600,10.882300 L 32.695300,11.868600 L 32.114200,11.539500 L 31.606400,10.964300 L 30.805600,11.539500 L 30.514600,10.223600 L 31.895500,9.3188000 L 31.895500,8.8247000 L 32.768500,8.2490000 L 34.149400,7.9194000 L 35.094700,8.2490000 L 36.838800,8.5781000 L 36.403300,9.0713000 L 35.458000,9.0713000 L 36.403300,10.058600 L 37.129900,9.2363000 L 37.350600,8.8745000 C 37.350600,8.8745000 40.137700,11.372500 41.730500,14.105000 C 43.323300,16.838400 44.071300,20.060100 44.071300,20.714400 z "
+ id="path3224"
+ style="color:#000000;fill:url(#radialGradient1468);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible" />
+ </g>
+ </g>
+ <g
+ id="g3226"
+ style="color:#000000;fill:url(#radialGradient1470);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible">
+ <g
+ id="g3230"
+ style="color:#000000;fill:url(#radialGradient1474);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible">
+ <path
+ d="M 26.070300,9.2363000 L 25.997100,9.7295000 L 26.506900,10.058600 L 27.378000,9.4829000 L 26.942500,8.9892000 L 26.360500,9.3188000 L 26.070500,9.2363000"
+ id="path3232"
+ style="color:#000000;fill:url(#radialGradient1476);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible" />
+ </g>
+ </g>
+ <g
+ id="g3234"
+ style="color:#000000;fill:url(#radialGradient1478);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible">
+ <g
+ id="g3238"
+ style="color:#000000;fill:url(#radialGradient1482);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible">
+ <path
+ d="M 26.870100,5.8633000 L 24.979500,5.1226000 L 22.799800,5.3692000 L 20.109400,6.1094000 L 19.600600,6.6035000 L 21.272500,7.7549000 L 21.272500,8.4131000 L 20.618200,9.0713000 L 21.491200,10.800300 L 22.071300,10.470200 L 22.799800,9.3188000 C 23.922800,8.9716000 24.929700,8.5781000 25.997100,8.0844000 L 26.870100,5.8632000"
+ id="path3240"
+ style="color:#000000;fill:url(#radialGradient1484);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible" />
+ </g>
+ </g>
+ <g
+ id="g3242"
+ style="color:#000000;fill:url(#radialGradient1486);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible">
+ <g
+ id="g3246"
+ style="color:#000000;fill:url(#radialGradient1490);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible">
+ <path
+ d="M 28.833000,12.774900 L 28.542000,12.033700 L 28.032200,12.198700 L 28.178700,13.103000 L 28.833000,12.774900"
+ id="path3248"
+ style="color:#000000;fill:url(#radialGradient1492);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible" />
+ </g>
+ </g>
+ <g
+ id="g3250"
+ style="color:#000000;fill:url(#radialGradient1494);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible">
+ <g
+ id="g3254"
+ style="color:#000000;fill:url(#radialGradient1498);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible">
+ <path
+ d="M 29.123000,12.608900 L 28.977500,13.597200 L 29.777300,13.432200 L 30.358400,12.857000 L 29.849600,12.362900 C 29.678700,11.907800 29.482400,11.483000 29.268500,11.046500 L 28.833000,11.046500 L 28.833000,11.539700 L 29.123000,11.868800 L 29.123000,12.609000"
+ id="path3256"
+ style="color:#000000;fill:url(#radialGradient1500);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible" />
+ </g>
+ </g>
+ <g
+ id="g3258"
+ style="color:#000000;fill:url(#radialGradient1502);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible">
+ <g
+ id="g3262"
+ style="color:#000000;fill:url(#radialGradient1506);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible">
+ <path
+ d="M 18.365200,28.242200 L 17.783200,27.089900 L 16.692900,26.843300 L 16.111400,25.280800 L 14.657800,25.444900 L 13.422400,24.540600 L 12.113300,25.692000 L 12.113300,25.873600 C 11.717300,25.759300 11.230500,25.743700 10.877900,25.526900 L 10.586900,24.704600 L 10.586900,23.799300 L 9.7148000,23.881300 C 9.7876000,23.305100 9.8598000,22.729900 9.9331000,22.153800 L 9.4238000,22.153800 L 8.9155000,22.812000 L 8.4062000,23.058100 L 7.6791000,22.647900 L 7.6063000,21.742600 L 7.7518000,20.755300 L 8.8426000,19.933000 L 9.7147000,19.933000 L 9.8597000,19.438900 L 10.950000,19.685000 L 11.749800,20.673300 L 11.895300,19.026800 L 13.276600,17.875400 L 13.785400,16.641000 L 14.803000,16.229900 L 15.384500,15.407600 L 16.692600,15.159600 L 17.347400,14.173300 C 16.693100,14.173300 16.038800,14.173300 15.384500,14.173300 L 16.620300,13.597100 L 17.491900,13.597100 L 18.728200,13.185000 L 18.873700,12.692800 L 18.437200,12.280700 L 17.928400,12.115700 L 18.073900,11.622500 L 17.710600,10.882300 L 16.838000,11.210400 L 16.983500,10.552700 L 15.965900,9.9765000 L 15.166600,11.374400 L 15.238900,11.868500 L 14.439600,12.198600 L 13.930300,13.267900 L 13.712500,12.280600 L 12.331200,11.704400 L 12.112900,10.964200 L 13.930300,9.8939000 L 14.730100,9.1537000 L 14.802900,8.2489000 L 14.366900,8.0018000 L 13.785400,7.9193000 L 13.422100,8.8246000 C 13.422100,8.8246000 12.814200,8.9437000 12.657900,8.9823000 C 10.661800,10.821700 6.6286000,14.792400 5.6916000,22.288500 C 5.7287000,22.462300 6.3708000,23.470100 6.3708000,23.470100 L 7.8972000,24.374400 L 9.4236000,24.786500 L 10.078400,25.609700 L 11.095500,26.349900 L 11.677000,26.267900 L 12.113000,26.464200 L 12.113000,26.597000 L 11.531900,28.160000 L 11.095400,28.818200 L 11.240900,29.148300 L 10.877600,30.380700 L 12.186200,32.767400 L 13.494300,33.919700 L 14.076300,34.742000 L 14.003100,36.470500 L 14.439600,37.456800 L 14.003100,39.349400 C 14.003100,39.349400 13.968900,39.337700 14.024600,39.527100 C 14.080800,39.716600 16.353700,40.978300 16.498200,40.870900 C 16.642200,40.761500 16.765300,40.665800 16.765300,40.665800 L 16.620300,40.255600 L 17.201400,39.679400 L 17.419700,39.103200 L 18.365000,38.773100 L 19.091600,36.962600 L 18.873800,36.470400 L 19.381600,35.730200 L 20.472400,35.482200 L 21.054400,34.165800 L 20.908900,32.521300 L 21.781000,31.286900 L 21.926500,30.052500 C 20.733100,29.460700 19.549500,28.851300 18.365000,28.242000"
+ id="path3264"
+ style="color:#000000;fill:url(#radialGradient1508);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible" />
+ </g>
+ </g>
+ <g
+ id="g3266"
+ style="color:#000000;fill:url(#radialGradient1510);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible">
+ <g
+ id="g3270"
+ style="color:#000000;fill:url(#radialGradient1514);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible">
+ <path
+ d="M 16.765600,9.5649000 L 17.492200,10.058600 L 18.074200,10.058600 L 18.074200,9.4829000 L 17.347600,9.1538000 L 16.765600,9.5649000"
+ id="path3272"
+ style="color:#000000;fill:url(#radialGradient1516);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible" />
+ </g>
+ </g>
+ <g
+ id="g3274"
+ style="color:#000000;fill:url(#radialGradient1518);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible">
+ <g
+ id="g3278"
+ style="color:#000000;fill:url(#radialGradient1522);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible">
+ <path
+ d="M 14.876000,8.9072000 L 14.512200,9.8120000 L 15.239300,9.8120000 L 15.603100,8.9892000 C 15.916600,8.7675000 16.228600,8.5444000 16.547900,8.3310000 L 17.275000,8.5781000 C 17.759400,8.9072000 18.243800,9.2363000 18.728600,9.5649000 L 19.456100,8.9072000 L 18.655800,8.5781000 L 18.292000,7.8374000 L 16.911100,7.6728000 L 16.838300,7.2612000 L 16.184000,7.4262000 L 15.893600,8.0020000 L 15.529800,7.2613000 L 15.384800,7.5904000 L 15.457600,8.4132000 L 14.876000,8.9072000"
+ id="path3280"
+ style="color:#000000;fill:url(#radialGradient1524);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible" />
+ </g>
+ </g>
+ <g
+ id="g3282"
+ style="color:#000000;fill:url(#radialGradient1526);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible">
+ <g
+ style="opacity:0.75000000;color:#000000;fill:url(#radialGradient1528);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+ id="g3284">
+ <path
+ d=""
+ style="color:#000000;fill:url(#radialGradient1530);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+ id="path3286" />
+ </g>
+ <g
+ id="g3288"
+ style="color:#000000;fill:url(#radialGradient1532);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible">
+ <path
+ d=""
+ id="path3290"
+ style="color:#000000;fill:url(#radialGradient1534);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible" />
+ </g>
+ </g>
+ <g
+ id="g3292"
+ style="color:#000000;fill:url(#radialGradient1536);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible">
+ <g
+ style="opacity:0.75000000;color:#000000;fill:url(#radialGradient1538);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+ id="g3294">
+ <path
+ d=""
+ style="color:#000000;fill:url(#radialGradient1540);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+ id="path3296" />
+ </g>
+ <g
+ id="g3298"
+ style="color:#000000;fill:url(#radialGradient1542);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible">
+ <path
+ d=""
+ id="path3300"
+ style="color:#000000;fill:url(#radialGradient1544);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible" />
+ </g>
+ </g>
+ <g
+ id="g3302"
+ style="color:#000000;fill:url(#radialGradient1546);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible">
+ <g
+ id="g3306"
+ style="color:#000000;fill:url(#radialGradient1550);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible">
+ <path
+ d="M 17.492200,6.8496000 L 17.856000,6.5210000 L 18.583100,6.3564000 C 19.081100,6.1142000 19.581100,5.9511000 20.109500,5.7802000 L 19.819500,5.2865000 L 18.881000,5.4213000 L 18.437600,5.8632000 L 17.706600,5.9692000 L 17.056700,6.2744000 L 16.740800,6.4272000 L 16.547900,6.6855000 L 17.492200,6.8496000"
+ id="path3308"
+ style="color:#000000;fill:url(#radialGradient1552);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible" />
+ </g>
+ </g>
+ <g
+ id="g3310"
+ style="color:#000000;fill:url(#radialGradient1554);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible">
+ <g
+ id="g3314"
+ style="color:#000000;fill:url(#radialGradient1558);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible">
+ <path
+ d="M 18.728500,14.666500 L 19.165000,14.008300 L 18.510200,13.515100 L 18.728500,14.666500"
+ id="path3316"
+ style="color:#000000;fill:url(#radialGradient4756);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible" />
+ </g>
+ </g>
+ </g>
+ <path
+ style="fill:none;fill-opacity:1.0000000;fill-rule:nonzero;stroke:url(#radialGradient4132);stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 42.975093,23.485534 C 42.975093,33.651354 34.733915,41.892440 24.569493,41.892440 C 14.404139,41.892440 6.1634261,33.651261 6.1634261,23.485534 C 6.1634261,13.320180 14.404139,5.0799340 24.569493,5.0799340 C 34.733915,5.0799340 42.975093,13.320180 42.975093,23.485534 L 42.975093,23.485534 z "
+ id="path4122" />
+ </g>
+</svg>
diff --git a/mediagoblin/media_types/video/processing.py b/mediagoblin/media_types/video/processing.py new file mode 100644 index 00000000..7d261226 --- /dev/null +++ b/mediagoblin/media_types/video/processing.py @@ -0,0 +1,119 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import tempfile +import logging +import os + +from mediagoblin import mg_globals as mgg +from mediagoblin.processing import mark_entry_failed, \ + THUMB_SIZE, MEDIUM_SIZE, create_pub_filepath +from . import transcoders + +logging.basicConfig() + +_log = logging.getLogger(__name__) +_log.setLevel(logging.DEBUG) + + +def process_video(entry): + """ + Code to process a video + + Much of this code is derived from the arista-transcoder script in + the arista PyPI package and changed to match the needs of + MediaGoblin + + This function sets up the arista video encoder in some kind of new thread + and attaches callbacks to that child process, hopefully, the + entry-complete callback will be called when the video is done. + """ + video_config = mgg.global_config['media_type:mediagoblin.media_types.video'] + + workbench = mgg.workbench_manager.create_workbench() + + queued_filepath = entry['queued_media_file'] + queued_filename = workbench.localized_file( + mgg.queue_store, queued_filepath, + 'source') + + medium_filepath = create_pub_filepath( + entry, + '{original}-640p.webm'.format( + original=os.path.splitext( + queued_filepath[-1])[0] # Select the + )) + + thumbnail_filepath = create_pub_filepath( + entry, 'thumbnail.jpg') + + + # Create a temporary file for the video destination + tmp_dst = tempfile.NamedTemporaryFile() + + with tmp_dst: + # Transcode queued file to a VP8/vorbis file that fits in a 640x640 square + transcoder = transcoders.VideoTranscoder(queued_filename, tmp_dst.name) + + # Push transcoded video to public storage + _log.debug('Saving medium...') + mgg.public_store.get_file(medium_filepath, 'wb').write( + tmp_dst.read()) + _log.debug('Saved medium') + + entry['media_files']['webm_640'] = medium_filepath + + # Save the width and height of the transcoded video + entry.media_data['video'] = { + u'width': transcoder.dst_data.videowidth, + u'height': transcoder.dst_data.videoheight} + + # Create a temporary file for the video thumbnail + tmp_thumb = tempfile.NamedTemporaryFile() + + with tmp_thumb: + # Create a thumbnail.jpg that fits in a 180x180 square + transcoders.VideoThumbnailer(queued_filename, tmp_thumb.name) + + # Push the thumbnail to public storage + _log.debug('Saving thumbnail...') + mgg.public_store.get_file(thumbnail_filepath, 'wb').write( + tmp_thumb.read()) + _log.debug('Saved thumbnail') + + entry['media_files']['thumb'] = thumbnail_filepath + + if video_config['keep_original']: + # Push original file to public storage + queued_file = file(queued_filename, 'rb') + + with queued_file: + original_filepath = create_pub_filepath( + entry, + queued_filepath[-1]) + + with mgg.public_store.get_file(original_filepath, 'wb') as \ + original_file: + _log.debug('Saving original...') + original_file.write(queued_file.read()) + _log.debug('Saved original') + + entry['media_files']['original'] = original_filepath + + mgg.queue_store.delete_file(queued_filepath) + + # Save the MediaEntry + entry.save() diff --git a/mediagoblin/media_types/video/transcoders.py b/mediagoblin/media_types/video/transcoders.py new file mode 100644 index 00000000..7071b887 --- /dev/null +++ b/mediagoblin/media_types/video/transcoders.py @@ -0,0 +1,658 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +from __future__ import division + +import os +os.putenv('GST_DEBUG_DUMP_DOT_DIR', '/tmp') + +import sys +import logging +import pdb +import urllib + +_log = logging.getLogger(__name__) +logging.basicConfig() +_log.setLevel(logging.DEBUG) + +CPU_COUNT = 2 +try: + import multiprocessing + try: + CPU_COUNT = multiprocessing.cpu_count() + except NotImplementedError: + _log.warning('multiprocessing.cpu_count not implemented') + pass +except ImportError: + _log.warning('Could not import multiprocessing, defaulting to 2 CPU cores') + pass + +try: + import gtk +except: + raise Exception('Could not find pygtk') + +try: + import gobject + gobject.threads_init() +except: + raise Exception('gobject could not be found') + +try: + import pygst + pygst.require('0.10') + import gst + from gst.extend import discoverer +except: + raise Exception('gst/pygst 0.10 could not be found') + + +class VideoThumbnailer: + # Declaration of thumbnailer states + STATE_NULL = 0 + STATE_HALTING = 1 + STATE_PROCESSING = 2 + + # The current thumbnailer state + state = STATE_NULL + + # This will contain the thumbnailing pipeline + thumbnail_pipeline = None + + buffer_probes = {} + + def __init__(self, source_path, dest_path): + ''' + Set up playbin pipeline in order to get video properties. + + Initializes and runs the gobject.MainLoop() + ''' + self.errors = [] + + self.source_path = source_path + self.dest_path = dest_path + + self.loop = gobject.MainLoop() + + # Set up the playbin. It will be used to discover certain + # properties of the input file + self.playbin = gst.element_factory_make('playbin') + + self.videosink = gst.element_factory_make('fakesink', 'videosink') + self.playbin.set_property('video-sink', self.videosink) + + self.audiosink = gst.element_factory_make('fakesink', 'audiosink') + self.playbin.set_property('audio-sink', self.audiosink) + + self.bus = self.playbin.get_bus() + self.bus.add_signal_watch() + self.watch_id = self.bus.connect('message', self._on_bus_message) + + self.playbin.set_property('uri', 'file:{0}'.format( + urllib.pathname2url(self.source_path))) + + self.playbin.set_state(gst.STATE_PAUSED) + + self.run() + + def run(self): + self.loop.run() + + def _on_bus_message(self, bus, message): + _log.debug(' BUS MESSAGE: {0}'.format(message)) + + if message.type == gst.MESSAGE_ERROR: + gobject.idle_add(self._on_bus_error) + + elif message.type == gst.MESSAGE_STATE_CHANGED: + # The pipeline state has changed + # Parse state changing data + _prev, state, _pending = message.parse_state_changed() + + _log.debug('State changed: {0}'.format(state)) + + if state == gst.STATE_PAUSED: + if message.src == self.playbin: + gobject.idle_add(self._on_bus_paused) + + def _on_bus_paused(self): + ''' + Set up thumbnailing pipeline + ''' + current_video = self.playbin.get_property('current-video') + + if current_video == 0: + _log.debug('Found current video from playbin') + else: + _log.error('Could not get any current video from playbin!') + + self.duration = self._get_duration(self.playbin) + _log.info('Video length: {0}'.format(self.duration / gst.SECOND)) + + _log.info('Setting up thumbnailing pipeline') + self.thumbnail_pipeline = gst.parse_launch( + 'filesrc location="{0}" ! decodebin ! ' + 'ffmpegcolorspace ! videoscale ! ' + 'video/x-raw-rgb,depth=24,bpp=24,pixel-aspect-ratio=1/1,width=180 ! ' + 'fakesink signal-handoffs=True'.format(self.source_path)) + + self.thumbnail_bus = self.thumbnail_pipeline.get_bus() + self.thumbnail_bus.add_signal_watch() + self.thumbnail_watch_id = self.thumbnail_bus.connect( + 'message', self._on_thumbnail_bus_message) + + self.thumbnail_pipeline.set_state(gst.STATE_PAUSED) + + #gobject.timeout_add(3000, self._on_timeout) + + return False + + def _on_thumbnail_bus_message(self, bus, message): + _log.debug('Thumbnail bus called, message: {0}'.format(message)) + + if message.type == gst.MESSAGE_ERROR: + _log.error(message) + gobject.idle_add(self._on_bus_error) + + if message.type == gst.MESSAGE_STATE_CHANGED: + _prev, state, _pending = message.parse_state_changed() + + if (state == gst.STATE_PAUSED and + not self.state == self.STATE_PROCESSING and + message.src == self.thumbnail_pipeline): + _log.info('Pipeline paused, processing') + self.state = self.STATE_PROCESSING + + for sink in self.thumbnail_pipeline.sinks(): + name = sink.get_name() + factoryname = sink.get_factory().get_name() + + if factoryname == 'fakesink': + sinkpad = sink.get_pad('sink') + + self.buffer_probes[name] = sinkpad.add_buffer_probe( + self.buffer_probe_handler, name) + + _log.info('Added buffer probe') + + break + + # Apply the wadsworth constant, fallback to 1 second + seek_amount = max(self.duration / 100 * 30, 1 * gst.SECOND) + + _log.debug('seek amount: {0}'.format(seek_amount)) + + seek_result = self.thumbnail_pipeline.seek( + 1.0, + gst.FORMAT_TIME, + gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_ACCURATE, + gst.SEEK_TYPE_SET, + seek_amount, + gst.SEEK_TYPE_NONE, + 0) + + if not seek_result: + self.errors.append('COULD_NOT_SEEK') + _log.error('Couldn\'t seek! result: {0}'.format( + seek_result)) + _log.info(message) + self.shutdown() + else: + pass + #self.thumbnail_pipeline.set_state(gst.STATE_PAUSED) + #pdb.set_trace() + + def buffer_probe_handler_real(self, pad, buff, name): + ''' + Capture buffers as gdk_pixbufs when told to. + ''' + try: + caps = buff.caps + if caps is None: + _log.error('No caps passed to buffer probe handler!') + self.shutdown() + return False + + _log.debug('caps: {0}'.format(caps)) + + filters = caps[0] + width = filters["width"] + height = filters["height"] + + pixbuf = gtk.gdk.pixbuf_new_from_data( + buff.data, gtk.gdk.COLORSPACE_RGB, False, 8, + width, height, width * 3) + + # NOTE: 200x136 is sort of arbitrary. it's larger than what + # the ui uses at the time of this writing. + # new_width, new_height = scaled_size((width, height), (200, 136)) + + #pixbuf = pixbuf.scale_simple( + #new_width, new_height, gtk.gdk.INTERP_BILINEAR) + + pixbuf.save(self.dest_path, 'jpeg') + _log.info('Saved thumbnail') + del pixbuf + self.shutdown() + except gst.QueryError: + pass + return False + + def buffer_probe_handler(self, pad, buff, name): + ''' + Proxy function for buffer_probe_handler_real + ''' + gobject.idle_add( + lambda: self.buffer_probe_handler_real(pad, buff, name)) + + return True + + def _get_duration(self, pipeline, retries=0): + ''' + Get the duration of a pipeline. + + Retries 5 times. + ''' + if retries == 5: + return 0 + + try: + return pipeline.query_duration(gst.FORMAT_TIME)[0] + except gst.QueryError: + return self._get_duration(pipeline, retries + 1) + + def _on_timeout(self): + _log.error('TIMEOUT! DROP EVERYTHING!') + self.shutdown() + + def _on_bus_error(self, *args): + _log.error('AHAHAHA! Error! args: {0}'.format(args)) + + def shutdown(self): + ''' + Tell gobject to call __halt when the mainloop is idle. + ''' + _log.info('Shutting down') + self.__halt() + + def __halt(self): + ''' + Halt all pipelines and shut down the main loop + ''' + _log.info('Halting...') + self.state = self.STATE_HALTING + + self.__disconnect() + + gobject.idle_add(self.__halt_final) + + def __disconnect(self): + _log.debug('Disconnecting...') + if not self.playbin is None: + self.playbin.set_state(gst.STATE_NULL) + for sink in self.playbin.sinks(): + name = sink.get_name() + factoryname = sink.get_factory().get_name() + + _log.debug('Disconnecting {0}'.format(name)) + + if factoryname == "fakesink": + pad = sink.get_pad("sink") + pad.remove_buffer_probe(self.buffer_probes[name]) + del self.buffer_probes[name] + + self.playbin = None + + if self.bus is not None: + self.bus.disconnect(self.watch_id) + self.bus = None + + + def __halt_final(self): + _log.info('Done') + if self.errors: + _log.error(','.join(self.errors)) + + self.loop.quit() + + +class VideoTranscoder: + ''' + Video transcoder + + Transcodes the SRC video file to a VP8 WebM video file at DST + + - Does the same thing as VideoThumbnailer, but produces a WebM vp8 + and vorbis video file. + - The VideoTranscoder exceeds the VideoThumbnailer in the way + that it was refined afterwards and therefore is done more + correctly. + ''' + def __init__(self, src, dst, **kwargs): + _log.info('Initializing VideoTranscoder...') + + self.loop = gobject.MainLoop() + self.source_path = src + self.destination_path = dst + + # Options + self.destination_dimensions = kwargs.get('dimensions') or (640, 640) + self._progress_callback = kwargs.get('progress_callback') or None + + if not type(self.destination_dimensions) == tuple: + raise Exception('dimensions must be tuple: (width, height)') + + self._setup() + self._run() + + def _setup(self): + self._setup_discover() + self._setup_pipeline() + + def _run(self): + _log.info('Discovering...') + self.discoverer.discover() + _log.info('Done') + + _log.debug('Initializing MainLoop()') + self.loop.run() + + def _setup_discover(self): + _log.debug('Setting up discoverer') + self.discoverer = discoverer.Discoverer(self.source_path) + + # Connect self.__discovered to the 'discovered' event + self.discoverer.connect('discovered', self.__discovered) + + def __discovered(self, data, is_media): + ''' + Callback for media discoverer. + ''' + if not is_media: + self.__stop() + raise Exception('Could not discover {0}'.format(self.source_path)) + + _log.debug('__discovered, data: {0}'.format(data.__dict__)) + + self.data = data + + # Launch things that should be done after discovery + self._link_elements() + self.__setup_videoscale_capsfilter() + + # Tell the transcoding pipeline to start running + self.pipeline.set_state(gst.STATE_PLAYING) + _log.info('Transcoding...') + + def _setup_pipeline(self): + _log.debug('Setting up transcoding pipeline') + # Create the pipeline bin. + self.pipeline = gst.Pipeline('VideoTranscoderPipeline') + + # Create all GStreamer elements, starting with + # filesrc & decoder + self.filesrc = gst.element_factory_make('filesrc', 'filesrc') + self.filesrc.set_property('location', self.source_path) + self.pipeline.add(self.filesrc) + + self.decoder = gst.element_factory_make('decodebin2', 'decoder') + self.decoder.connect('new-decoded-pad', self._on_dynamic_pad) + self.pipeline.add(self.decoder) + + # Video elements + self.videoqueue = gst.element_factory_make('queue', 'videoqueue') + self.pipeline.add(self.videoqueue) + + self.videorate = gst.element_factory_make('videorate', 'videorate') + self.pipeline.add(self.videorate) + + self.ffmpegcolorspace = gst.element_factory_make( + 'ffmpegcolorspace', 'ffmpegcolorspace') + self.pipeline.add(self.ffmpegcolorspace) + + self.videoscale = gst.element_factory_make('ffvideoscale', 'videoscale') + #self.videoscale.set_property('method', 2) # I'm not sure this works + #self.videoscale.set_property('add-borders', 0) + self.pipeline.add(self.videoscale) + + self.capsfilter = gst.element_factory_make('capsfilter', 'capsfilter') + self.pipeline.add(self.capsfilter) + + self.vp8enc = gst.element_factory_make('vp8enc', 'vp8enc') + self.vp8enc.set_property('quality', 6) + self.vp8enc.set_property('threads', 2) + self.pipeline.add(self.vp8enc) + + # Audio elements + self.audioqueue = gst.element_factory_make('queue', 'audioqueue') + self.pipeline.add(self.audioqueue) + + self.audiorate = gst.element_factory_make('audiorate', 'audiorate') + self.audiorate.set_property('tolerance', 80000000) + self.pipeline.add(self.audiorate) + + self.audioconvert = gst.element_factory_make('audioconvert', 'audioconvert') + self.pipeline.add(self.audioconvert) + + self.audiocapsfilter = gst.element_factory_make('capsfilter', 'audiocapsfilter') + audiocaps = ['audio/x-raw-float'] + self.audiocapsfilter.set_property( + 'caps', + gst.caps_from_string( + ','.join(audiocaps))) + self.pipeline.add(self.audiocapsfilter) + + self.vorbisenc = gst.element_factory_make('vorbisenc', 'vorbisenc') + self.vorbisenc.set_property('quality', 1) + self.pipeline.add(self.vorbisenc) + + # WebMmux & filesink + self.webmmux = gst.element_factory_make('webmmux', 'webmmux') + self.pipeline.add(self.webmmux) + + self.filesink = gst.element_factory_make('filesink', 'filesink') + self.filesink.set_property('location', self.destination_path) + self.pipeline.add(self.filesink) + + # Progressreport + self.progressreport = gst.element_factory_make( + 'progressreport', 'progressreport') + # Update every second + self.progressreport.set_property('update-freq', 1) + self.progressreport.set_property('silent', True) + self.pipeline.add(self.progressreport) + + def _link_elements(self): + ''' + Link all the elements + + This code depends on data from the discoverer and is called + from __discovered + ''' + _log.debug('linking elements') + # Link the filesrc element to the decoder. The decoder then emits + # 'new-decoded-pad' which links decoded src pads to either a video + # or audio sink + self.filesrc.link(self.decoder) + + # Link all the video elements in a row to webmmux + gst.element_link_many( + self.videoqueue, + self.videorate, + self.ffmpegcolorspace, + self.videoscale, + self.capsfilter, + self.vp8enc, + self.webmmux) + + if self.data.is_audio: + # Link all the audio elements in a row to webmux + gst.element_link_many( + self.audioqueue, + self.audiorate, + self.audioconvert, + self.audiocapsfilter, + self.vorbisenc, + self.webmmux) + + gst.element_link_many( + self.webmmux, + self.progressreport, + self.filesink) + + # Setup the message bus and connect _on_message to the pipeline + self._setup_bus() + + + def _on_dynamic_pad(self, dbin, pad, islast): + ''' + Callback called when ``decodebin2`` has a pad that we can connect to + ''' + # Intersect the capabilities of the video sink and the pad src + # Then check if they have no common capabilities. + if self.ffmpegcolorspace.get_pad_template('sink')\ + .get_caps().intersect(pad.get_caps()).is_empty(): + # It is NOT a video src pad. + pad.link(self.audioqueue.get_pad('sink')) + else: + # It IS a video src pad. + pad.link(self.videoqueue.get_pad('sink')) + + def _setup_bus(self): + self.bus = self.pipeline.get_bus() + self.bus.add_signal_watch() + self.bus.connect('message', self._on_message) + + def __setup_videoscale_capsfilter(self): + ''' + Sets up the output format (width, height) for the video + ''' + caps = ['video/x-raw-yuv', 'pixel-aspect-ratio=1/1', 'framerate=30/1'] + + if self.data.videoheight > self.data.videowidth: + # Whoa! We have ourselves a portrait video! + caps.append('height={0}'.format( + self.destination_dimensions[1])) + else: + # It's a landscape, phew, how normal. + caps.append('width={0}'.format( + self.destination_dimensions[0])) + + self.capsfilter.set_property( + 'caps', + gst.caps_from_string( + ','.join(caps))) + + def _on_message(self, bus, message): + _log.debug((bus, message, message.type)) + + t = message.type + + if t == gst.MESSAGE_EOS: + self._discover_dst_and_stop() + _log.info('Done') + + elif t == gst.MESSAGE_ELEMENT: + if message.structure.get_name() == 'progress': + data = dict(message.structure) + + if self._progress_callback: + self._progress_callback(data) + + _log.info('{percent}% done...'.format( + percent=data.get('percent'))) + _log.debug(data) + + elif t == gst.MESSAGE_ERROR: + _log.error((bus, message)) + self.__stop() + + def _discover_dst_and_stop(self): + self.dst_discoverer = discoverer.Discoverer(self.destination_path) + + self.dst_discoverer.connect('discovered', self.__dst_discovered) + + self.dst_discoverer.discover() + + + def __dst_discovered(self, data, is_media): + self.dst_data = data + + self.__stop() + + def __stop(self): + _log.debug(self.loop) + + # Stop executing the pipeline + self.pipeline.set_state(gst.STATE_NULL) + + # This kills the loop, mercifully + gobject.idle_add(self.__stop_mainloop) + + def __stop_mainloop(self): + ''' + Wrapper for gobject.MainLoop.quit() + + This wrapper makes us able to see if self.loop.quit has been called + ''' + _log.info('Terminating MainLoop') + + self.loop.quit() + + +if __name__ == '__main__': + os.nice(19) + from optparse import OptionParser + + parser = OptionParser( + usage='%prog [-v] -a [ video | thumbnail ] SRC DEST') + + parser.add_option('-a', '--action', + dest='action', + help='One of "video" or "thumbnail"') + + parser.add_option('-v', + dest='verbose', + action='store_true', + help='Output debug information') + + parser.add_option('-q', + dest='quiet', + action='store_true', + help='Dear program, please be quiet unless *error*') + + (options, args) = parser.parse_args() + + if options.verbose: + _log.setLevel(logging.DEBUG) + else: + _log.setLevel(logging.INFO) + + if options.quiet: + _log.setLevel(logging.ERROR) + + _log.debug(args) + + if not len(args) == 2: + parser.print_help() + sys.exit() + + if options.action == 'thumbnail': + VideoThumbnailer(*args) + elif options.action == 'video': + def cb(data): + print('I\'m a callback!') + transcoder = VideoTranscoder(*args, progress_callback=cb) diff --git a/mediagoblin/messages.py b/mediagoblin/messages.py index dc82fbf6..054d46c0 100644 --- a/mediagoblin/messages.py +++ b/mediagoblin/messages.py @@ -20,11 +20,13 @@ SUCCESS = 'success' WARNING = 'warning' ERROR = 'error' + def add_message(request, level, text): messages = request.session.setdefault('messages', []) messages.append({'level': level, 'text': text}) request.session.save() + def fetch_messages(request, clear_from_session=True): messages = request.session.get('messages') if messages and clear_from_session: diff --git a/mediagoblin/process_media/errors.py b/mediagoblin/process_media/errors.py deleted file mode 100644 index 8003ffaf..00000000 --- a/mediagoblin/process_media/errors.py +++ /dev/null @@ -1,44 +0,0 @@ -# GNU MediaGoblin -- federated, autonomous media hosting -# Copyright (C) 2011 MediaGoblin contributors. See AUTHORS. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ - -class BaseProcessingFail(Exception): - """ - Base exception that all other processing failure messages should - subclass from. - - You shouldn't call this itself; instead you should subclass it - and provid the exception_path and general_message applicable to - this error. - """ - general_message = u'' - - @property - def exception_path(self): - return u"%s:%s" % ( - self.__class__.__module__, self.__class__.__name__) - - def __init__(self, **metadata): - self.metadata = metadata or {} - - -class BadMediaFail(BaseProcessingFail): - """ - Error that should be raised when an inappropriate file was given - for the media type specified. - """ - general_message = _(u'Invalid file given for media type.') diff --git a/mediagoblin/process_media/__init__.py b/mediagoblin/processing.py index 2b9eed6e..7dd5cc7d 100644 --- a/mediagoblin/process_media/__init__.py +++ b/mediagoblin/processing.py @@ -14,14 +14,14 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -import Image - from celery.task import Task -from celery import registry from mediagoblin.db.util import ObjectId from mediagoblin import mg_globals as mgg -from mediagoblin.process_media.errors import BaseProcessingFail, BadMediaFail + +from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ + +from mediagoblin.media_types import get_media_manager THUMB_SIZE = 180, 180 @@ -31,7 +31,7 @@ MEDIUM_SIZE = 640, 640 def create_pub_filepath(entry, filename): return mgg.public_store.get_unique_filepath( ['media_entries', - unicode(entry['_id']), + unicode(entry._id), filename]) @@ -41,6 +41,8 @@ def create_pub_filepath(entry, filename): class ProcessMedia(Task): """ + DEPRECATED -- This now resides in the individual media plugins + Pass this entry off for processing. """ def run(self, media_id): @@ -53,10 +55,14 @@ class ProcessMedia(Task): # Try to process, and handle expected errors. try: - process_image(entry) + #__import__(entry.media_type) + manager = get_media_manager(entry.media_type) + manager['processor'](entry) except BaseProcessingFail, exc: - mark_entry_failed(entry[u'_id'], exc) + mark_entry_failed(entry._id, exc) return + except ImportError, exc: + mark_entry_failed(entry[u'_id'], exc) entry['state'] = u'processed' entry.save() @@ -65,25 +71,23 @@ class ProcessMedia(Task): """ If the processing failed we should mark that in the database. - Assuming that the exception raised is a subclass of BaseProcessingFail, - we can use that to get more information about the failure and store that - for conveying information to users about the failure, etc. + Assuming that the exception raised is a subclass of + BaseProcessingFail, we can use that to get more information + about the failure and store that for conveying information to + users about the failure, etc. """ entry_id = args[0] mark_entry_failed(entry_id, exc) -process_media = registry.tasks[ProcessMedia.name] - - def mark_entry_failed(entry_id, exc): """ Mark a media entry as having failed in its conversion. - Uses the exception that was raised to mark more information. If the - exception is a derivative of BaseProcessingFail then we can store extra - information that can be useful for users telling them why their media failed - to process. + Uses the exception that was raised to mark more information. If + the exception is a derivative of BaseProcessingFail then we can + store extra information that can be useful for users telling them + why their media failed to process. Args: - entry_id: The id of the media entry @@ -111,69 +115,29 @@ def mark_entry_failed(entry_id, exc): u'fail_metadata': {}}}) -def process_image(entry): - """ - Code to process an image +class BaseProcessingFail(Exception): """ - workbench = mgg.workbench_manager.create_workbench() - - queued_filepath = entry['queued_media_file'] - queued_filename = workbench.localized_file( - mgg.queue_store, queued_filepath, - 'source') - - try: - thumb = Image.open(queued_filename) - except IOError: - raise BadMediaFail() + Base exception that all other processing failure messages should + subclass from. - thumb.thumbnail(THUMB_SIZE, Image.ANTIALIAS) - # ensure color mode is compatible with jpg - if thumb.mode != "RGB": - thumb = thumb.convert("RGB") - - thumb_filepath = create_pub_filepath(entry, 'thumbnail.jpg') - thumb_file = mgg.public_store.get_file(thumb_filepath, 'w') - - with thumb_file: - thumb.save(thumb_file, "JPEG", quality=90) - - # If the size of the original file exceeds the specified size of a `medium` - # file, a `medium.jpg` files is created and later associated with the media - # entry. - medium = Image.open(queued_filename) - medium_processed = False - - if medium.size[0] > MEDIUM_SIZE[0] or medium.size[1] > MEDIUM_SIZE[1]: - medium.thumbnail(MEDIUM_SIZE, Image.ANTIALIAS) - - if medium.mode != "RGB": - medium = medium.convert("RGB") - - medium_filepath = create_pub_filepath(entry, 'medium.jpg') - medium_file = mgg.public_store.get_file(medium_filepath, 'w') - - with medium_file: - medium.save(medium_file, "JPEG", quality=90) - medium_processed = True - - # we have to re-read because unlike PIL, not everything reads - # things in string representation :) - queued_file = file(queued_filename, 'rb') + You shouldn't call this itself; instead you should subclass it + and provid the exception_path and general_message applicable to + this error. + """ + general_message = u'' - with queued_file: - original_filepath = create_pub_filepath(entry, queued_filepath[-1]) + @property + def exception_path(self): + return u"%s:%s" % ( + self.__class__.__module__, self.__class__.__name__) - with mgg.public_store.get_file(original_filepath, 'wb') as original_file: - original_file.write(queued_file.read()) + def __init__(self, **metadata): + self.metadata = metadata or {} - mgg.queue_store.delete_file(queued_filepath) - entry['queued_media_file'] = [] - media_files_dict = entry.setdefault('media_files', {}) - media_files_dict['thumb'] = thumb_filepath - media_files_dict['original'] = original_filepath - if medium_processed: - media_files_dict['medium'] = medium_filepath - # clean up workbench - workbench.destroy_self() +class BadMediaFail(BaseProcessingFail): + """ + Error that should be raised when an inappropriate file was given + for the media type specified. + """ + general_message = _(u'Invalid file given for media type.') diff --git a/mediagoblin/static/css/base.css b/mediagoblin/static/css/base.css index afd10207..2a78006d 100644 --- a/mediagoblin/static/css/base.css +++ b/mediagoblin/static/css/base.css @@ -96,30 +96,7 @@ input, textarea { a.mediagoblin_logo{ color: #fff; font-weight: bold; -} - -.header_submit, .header_submit_highlight{ - color: #272727; - background-color: #aaa; - background-image: -webkit-gradient(linear, left top, left bottom, from(##D2D2D2), to(#aaa)); - background-image: -webkit-linear-gradient(top, #D2D2D2, #aaa); - background-image: -moz-linear-gradient(top, #D2D2D2, #aaa); - background-image: -ms-linear-gradient(top, #D2D2D2, #aaa); - background-image: -o-linear-gradient(top, #D2D2D2, #aaa); - background-image: linear-gradient(top, #D2D2D2, #aaa); - box-shadow: 0px 0px 4px #000; - border-radius: 3px; - margin: 8px; - padding: 3px 8px; - text-decoration: none; - border: medium none; - font-style: normal; - font-weight: bold; - font-size: 1em; -} - -.header_submit_highlight{ -background-image: -moz-linear-gradient(center top , rgb(134, 212, 177), rgb(109, 173, 144)); + margin-right: 8px; } .mediagoblin_footer { @@ -141,7 +118,28 @@ background-image: -moz-linear-gradient(center top , rgb(134, 212, 177), rgb(109, /* common website elements */ -.button, .cancel_link { +.button_action, .button_action_highlight { + display: inline-block; + color: #c3c3c3; + background-color: #363636; + border: 1px solid; + border-color: #464646 #2B2B2B #252525; + border-radius: 4px; + padding: 3px 8px; + font-size: 16px; + text-decoration: none; + font-style: normal; + font-weight: bold; + cursor: pointer; +} + +.button_action_highlight { + background-color: #86D4B1; + border-color: #A2DEC3 #6CAA8E #5C9179; + color: #283F35; +} + +.button_form, .cancel_link { height: 32px; min-width: 99px; background-color: #86d4b1; @@ -174,22 +172,34 @@ background-image: -moz-linear-gradient(center top , rgb(134, 212, 177), rgb(109, background-image: linear-gradient(top, #D2D2D2, #aaa); } -.pagination{ +.pagination { text-align: center; } -.pagination_arrow{ +.pagination_arrow { margin: 5px; } -.empty_space{ - background-color: #222; +.empty_space { + background-image: url("../images/empty_back.png"); font-style: italic; text-align: center; height: 160px; padding-top: 70px; } +.right_align { + float: right; +} + +textarea#comment_content { + width: 634px; + height: 90px; + border: none; + background-color: #f1f1f1; + padding: 3px; +} + /* forms */ .form_box { @@ -212,7 +222,11 @@ text-align: center; width: 100%; } -.form_field_label,.form_field_input { +.form_field_input { + margin-bottom: 10px; +} + +.form_field_label { margin-bottom: 4px; } @@ -272,24 +286,28 @@ text-align: center; /* media detail */ -h2.media_title{ +h2.media_title { margin-bottom: 0px; } -p.media_uploader{ +p.media_specs { font-size: 0.9em; + border-top: 1px solid #222; + border-bottom: 1px solid #222; + padding: 10px 0px; + color: #888; } /* icons */ -img.media_icon{ +img.media_icon { margin: 0 4px; vertical-align: sub; } /* navigation */ -.navigation_button{ +.navigation_button { width: 135px; display: block; float: left; @@ -297,18 +315,14 @@ img.media_icon{ background-color: #1d1d1d; border: 1px solid; border-color: #2c2c2c #232323 #1a1a1a; - border-radius: 3px; + border-radius: 4px; text-decoration: none; - padding: 8px 0px 14px; - font-size: 2em; + padding: 12px 0 16px; + font-size: 1.4em; margin: 0 0 20px } -p.navigation_button{ - color: #272727; -} - -.navigation_left{ +.navigation_left { margin-right: 6px; } diff --git a/mediagoblin/static/images/empty_back.png b/mediagoblin/static/images/empty_back.png Binary files differnew file mode 100644 index 00000000..3522ddd3 --- /dev/null +++ b/mediagoblin/static/images/empty_back.png diff --git a/mediagoblin/static/images/icon_delete.png b/mediagoblin/static/images/icon_delete.png Binary files differdeleted file mode 100644 index 9d76a5db..00000000 --- a/mediagoblin/static/images/icon_delete.png +++ /dev/null diff --git a/mediagoblin/static/images/icon_edit.png b/mediagoblin/static/images/icon_edit.png Binary files differdeleted file mode 100644 index 480c73ad..00000000 --- a/mediagoblin/static/images/icon_edit.png +++ /dev/null diff --git a/mediagoblin/static/images/media_thumbs/video.jpg b/mediagoblin/static/images/media_thumbs/video.jpg Binary files differnew file mode 100644 index 00000000..841dc796 --- /dev/null +++ b/mediagoblin/static/images/media_thumbs/video.jpg diff --git a/mediagoblin/static/images/navigation_end.png b/mediagoblin/static/images/navigation_end.png Binary files differdeleted file mode 100644 index b2f27296..00000000 --- a/mediagoblin/static/images/navigation_end.png +++ /dev/null diff --git a/mediagoblin/static/images/navigation_left.png b/mediagoblin/static/images/navigation_left.png Binary files differdeleted file mode 100644 index d1645120..00000000 --- a/mediagoblin/static/images/navigation_left.png +++ /dev/null diff --git a/mediagoblin/static/images/navigation_right.png b/mediagoblin/static/images/navigation_right.png Binary files differdeleted file mode 100644 index d4caa7b8..00000000 --- a/mediagoblin/static/images/navigation_right.png +++ /dev/null diff --git a/mediagoblin/static/images/pagination_left.png b/mediagoblin/static/images/pagination_left.png Binary files differdeleted file mode 100644 index 56a26596..00000000 --- a/mediagoblin/static/images/pagination_left.png +++ /dev/null diff --git a/mediagoblin/static/images/pagination_right.png b/mediagoblin/static/images/pagination_right.png Binary files differdeleted file mode 100644 index 84f8abba..00000000 --- a/mediagoblin/static/images/pagination_right.png +++ /dev/null diff --git a/mediagoblin/static/js/extlib/jquery.js b/mediagoblin/static/js/extlib/jquery.js new file mode 120000 index 00000000..d78f5cc3 --- /dev/null +++ b/mediagoblin/static/js/extlib/jquery.js @@ -0,0 +1 @@ +../../../../extlib/jquery/jquery.js
\ No newline at end of file diff --git a/mediagoblin/staticdirect.py b/mediagoblin/staticdirect.py index 58175881..c6d2b374 100644 --- a/mediagoblin/staticdirect.py +++ b/mediagoblin/staticdirect.py @@ -21,24 +21,24 @@ import urlparse # Staticdirect infrastructure. # Borrowed largely from cc.engine # by Chris Webber & Creative Commons -# +# # This needs documentation! #################################### import pkg_resources import urlparse + class StaticDirect(object): def __init__(self): self.cache = {} def __call__(self, filepath): - if self.cache.has_key(filepath): + if filepath in self.cache: return self.cache[filepath] static_direction = self.cache[filepath] = self.get(filepath) return static_direction - def get(self, filepath): # should be implemented by the individual staticdirector diff --git a/mediagoblin/storage/__init__.py b/mediagoblin/storage/__init__.py index 9e592b9e..0840614b 100644 --- a/mediagoblin/storage/__init__.py +++ b/mediagoblin/storage/__init__.py @@ -169,6 +169,18 @@ class StorageInterface(object): with file(dest_path, 'wb') as dest_file: dest_file.write(source_file.read()) + def copy_local_to_storage(self, filename, filepath): + """ + Copy this file from locally to the storage system. + + This is kind of the opposite of copy_locally. It's likely you + could override this method with something more appropriate to + your storage system. + """ + with self.get_file(filepath, 'wb') as dest_file: + with file(filename, 'rb') as source_file: + dest_file.write(source_file.read()) + ########### # Utilities diff --git a/mediagoblin/storage/cloudfiles.py b/mediagoblin/storage/cloudfiles.py index b1dd9450..51b73579 100644 --- a/mediagoblin/storage/cloudfiles.py +++ b/mediagoblin/storage/cloudfiles.py @@ -27,6 +27,7 @@ from mediagoblin.storage import StorageInterface, clean_listy_filepath import cloudfiles import mimetypes + class CloudFilesStorage(StorageInterface): ''' OpenStack/Rackspace Cloud's Swift/CloudFiles support @@ -97,8 +98,14 @@ class CloudFilesStorage(StorageInterface): def delete_file(self, filepath): # TODO: Also delete unused directories if empty (safely, with # checks to avoid race conditions). - self.container.delete_object( - self._resolve_filepath(filepath)) + try: + self.container.delete_object( + self._resolve_filepath(filepath)) + except cloudfiles.container.ResponseError: + pass + finally: + pass + def file_url(self, filepath): return '/'.join([ diff --git a/mediagoblin/storage/filestorage.py b/mediagoblin/storage/filestorage.py index 22d6eb5a..a904865f 100644 --- a/mediagoblin/storage/filestorage.py +++ b/mediagoblin/storage/filestorage.py @@ -20,6 +20,7 @@ from mediagoblin.storage import ( NoWebServing) import os +import shutil import urlparse @@ -76,3 +77,16 @@ class BasicFileStorage(StorageInterface): def get_local_path(self, filepath): return self._resolve_filepath(filepath) + + def copy_local_to_storage(self, filename, filepath): + """ + Copy this file from locally to the storage system. + """ + # Make directories if necessary + if len(filepath) > 1: + directory = self._resolve_filepath(filepath[:-1]) + if not os.path.exists(directory): + os.makedirs(directory) + + shutil.copy( + filename, self.get_local_path(filepath)) diff --git a/mediagoblin/submit/__init__.py b/mediagoblin/submit/__init__.py index 576bd0f5..ba347c69 100644 --- a/mediagoblin/submit/__init__.py +++ b/mediagoblin/submit/__init__.py @@ -13,5 +13,3 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. - - diff --git a/mediagoblin/submit/forms.py b/mediagoblin/submit/forms.py index 25d6e304..ad420771 100644 --- a/mediagoblin/submit/forms.py +++ b/mediagoblin/submit/forms.py @@ -30,4 +30,6 @@ class SubmitStartForm(wtforms.Form): _('Description of this work')) tags = wtforms.TextField( _('Tags'), - [tag_length_validator]) + [tag_length_validator], + description=_( + "Seperate tags by commas.")) diff --git a/mediagoblin/submit/security.py b/mediagoblin/submit/security.py index 9d62a36e..6708baf7 100644 --- a/mediagoblin/submit/security.py +++ b/mediagoblin/submit/security.py @@ -16,9 +16,9 @@ from mimetypes import guess_type - ALLOWED = ['image/jpeg', 'image/png', 'image/tiff', 'image/gif'] + def check_filetype(posted_file): if not guess_type(posted_file.filename)[0] in ALLOWED: return False diff --git a/mediagoblin/submit/views.py b/mediagoblin/submit/views.py index 7134235e..4e4c7c43 100644 --- a/mediagoblin/submit/views.py +++ b/mediagoblin/submit/views.py @@ -19,6 +19,8 @@ import uuid from os.path import splitext from cgi import FieldStorage +from celery import registry + from werkzeug.utils import secure_filename from mediagoblin.db.util import ObjectId @@ -27,8 +29,9 @@ from mediagoblin.tools.translate import pass_to_ugettext as _ from mediagoblin.tools.response import render_to_response, redirect from mediagoblin.decorators import require_active_login from mediagoblin.submit import forms as submit_forms, security -from mediagoblin.process_media import process_media, mark_entry_failed +from mediagoblin.processing import mark_entry_failed, ProcessMedia from mediagoblin.messages import add_message, SUCCESS +from mediagoblin.media_types import get_media_type_and_manager, InvalidFileType @require_active_login @@ -39,89 +42,95 @@ def submit_start(request): submit_form = submit_forms.SubmitStartForm(request.POST) if request.method == 'POST' and submit_form.validate(): - if not (request.POST.has_key('file') + if not ('file' in request.POST and isinstance(request.POST['file'], FieldStorage) and request.POST['file'].file): submit_form.file.errors.append( _(u'You must provide a file.')) - elif not security.check_filetype(request.POST['file']): - submit_form.file.errors.append( - _(u"The file doesn't seem to be an image!")) else: - filename = request.POST['file'].filename - - # create entry and save in database - entry = request.db.MediaEntry() - entry['_id'] = ObjectId() - entry['title'] = ( - unicode(request.POST['title']) - or unicode(splitext(filename)[0])) - - entry['description'] = unicode(request.POST.get('description')) - entry['description_html'] = cleaned_markdown_conversion( - entry['description']) - - entry['media_type'] = u'image' # heh - entry['uploader'] = request.user['_id'] - - # Process the user's folksonomy "tags" - entry['tags'] = convert_to_tag_list_of_dicts( - request.POST.get('tags')) - - # Generate a slug from the title - entry.generate_slug() - - # Now store generate the queueing related filename - queue_filepath = request.app.queue_store.get_unique_filepath( - ['media_entries', - unicode(entry['_id']), - secure_filename(filename)]) - - # queue appropriately - queue_file = request.app.queue_store.get_file( - queue_filepath, 'wb') - - with queue_file: - queue_file.write(request.POST['file'].file.read()) - - # Add queued filename to the entry - entry['queued_media_file'] = queue_filepath - - # We generate this ourselves so we know what the taks id is for - # retrieval later. - # (If we got it off the task's auto-generation, there'd be a risk of - # a race condition when we'd save after sending off the task) - task_id = unicode(uuid.uuid4()) - entry['queued_task_id'] = task_id - - # Save now so we have this data before kicking off processing - entry.save(validate=True) - - # Pass off to processing - # - # (... don't change entry after this point to avoid race - # conditions with changes to the document via processing code) try: - process_media.apply_async( - [unicode(entry['_id'])], {}, - task_id=task_id) - except BaseException as exc: - # The purpose of this section is because when running in "lazy" - # or always-eager-with-exceptions-propagated celery mode that - # the failure handling won't happen on Celery end. Since we - # expect a lot of users to run things in this way we have to - # capture stuff here. - # - # ... not completely the diaper pattern because the exception is - # re-raised :) - mark_entry_failed(entry[u'_id'], exc) - # re-raise the exception - raise + filename = request.POST['file'].filename + media_type, media_manager = get_media_type_and_manager(filename) + + # create entry and save in database + entry = request.db.MediaEntry() + entry['_id'] = ObjectId() + entry.media_type = unicode(media_type) + entry.title = ( + unicode(request.POST['title']) + or unicode(splitext(filename)[0])) + + entry.description = unicode(request.POST.get('description')) + entry.description_html = cleaned_markdown_conversion( + entry.description) + + entry.uploader = request.user._id + + # Process the user's folksonomy "tags" + entry['tags'] = convert_to_tag_list_of_dicts( + request.POST.get('tags')) + + # Generate a slug from the title + entry.generate_slug() - add_message(request, SUCCESS, _('Woohoo! Submitted!')) - return redirect(request, "mediagoblin.user_pages.user_home", - user = request.user['username']) + # Now store generate the queueing related filename + queue_filepath = request.app.queue_store.get_unique_filepath( + ['media_entries', + unicode(entry._id), + secure_filename(filename)]) + + # queue appropriately + queue_file = request.app.queue_store.get_file( + queue_filepath, 'wb') + + with queue_file: + queue_file.write(request.POST['file'].file.read()) + + # Add queued filename to the entry + entry['queued_media_file'] = queue_filepath + + # We generate this ourselves so we know what the taks id is for + # retrieval later. + + # (If we got it off the task's auto-generation, there'd be + # a risk of a race condition when we'd save after sending + # off the task) + task_id = unicode(uuid.uuid4()) + entry['queued_task_id'] = task_id + + # Save now so we have this data before kicking off processing + entry.save(validate=True) + + # Pass off to processing + # + # (... don't change entry after this point to avoid race + # conditions with changes to the document via processing code) + process_media = registry.tasks[ProcessMedia.name] + try: + process_media.apply_async( + [unicode(entry._id)], {}, + task_id=task_id) + except BaseException as exc: + # The purpose of this section is because when running in "lazy" + # or always-eager-with-exceptions-propagated celery mode that + # the failure handling won't happen on Celery end. Since we + # expect a lot of users to run things in this way we have to + # capture stuff here. + # + # ... not completely the diaper pattern because the + # exception is re-raised :) + mark_entry_failed(entry._id, exc) + # re-raise the exception + raise + + add_message(request, SUCCESS, _('Woohoo! Submitted!')) + + return redirect(request, "mediagoblin.user_pages.user_home", + user=request.user.username) + except InvalidFileType, exc: + submit_form.file.errors.append( + _(u'Invalid file type.')) return render_to_response( request, diff --git a/mediagoblin/templates/mediagoblin/auth/change_fp.html b/mediagoblin/templates/mediagoblin/auth/change_fp.html index 53186cec..03a6583b 100644 --- a/mediagoblin/templates/mediagoblin/auth/change_fp.html +++ b/mediagoblin/templates/mediagoblin/auth/change_fp.html @@ -26,11 +26,11 @@ {{ csrf_token }} <div class="grid_6 prefix_1 suffix_1 form_box"> - <h1>{% trans %}Enter your new password{% endtrans %}</h1> + <h1>{% trans %}Set your new password{% endtrans %}</h1> {{ wtforms_util.render_divs(cp_form) }} <div class="form_submit_buttons"> - <input type="submit" value="submit" class="button"/> + <input type="submit" value="{% trans %}Set password{% endtrans %}" class="button_form"/> </div> </div> diff --git a/mediagoblin/templates/mediagoblin/auth/forgot_password.html b/mediagoblin/templates/mediagoblin/auth/forgot_password.html index 9b821426..41940742 100644 --- a/mediagoblin/templates/mediagoblin/auth/forgot_password.html +++ b/mediagoblin/templates/mediagoblin/auth/forgot_password.html @@ -27,7 +27,7 @@ <h1>{% trans %}Recover password{% endtrans %}</h1> {{ wtforms_util.render_divs(fp_form) }} <div class="form_submit_buttons"> - <input type="submit" value="{% trans %}Send instructions{% endtrans %}" class="button"/> + <input type="submit" value="{% trans %}Send instructions{% endtrans %}" class="button_form"/> </div> </div> </form> diff --git a/mediagoblin/templates/mediagoblin/auth/login.html b/mediagoblin/templates/mediagoblin/auth/login.html index 756f67c0..c3807e5f 100644 --- a/mediagoblin/templates/mediagoblin/auth/login.html +++ b/mediagoblin/templates/mediagoblin/auth/login.html @@ -42,10 +42,10 @@ {% trans %}Forgot your password?{% endtrans %}</a> </p> <div class="form_submit_buttons"> - <input type="submit" value="{% trans %}Log in{% endtrans %}" class="button"/> + <input type="submit" value="{% trans %}Log in{% endtrans %}" class="button_form"/> </div> {% if next %} - <input type="hidden" name="next" value="{{ next }}" class="button" + <input type="hidden" name="next" value="{{ next }}" class="button_form" style="display: none;"/> {% endif %} </div> diff --git a/mediagoblin/templates/mediagoblin/auth/register.html b/mediagoblin/templates/mediagoblin/auth/register.html index 25b68058..bded1d7e 100644 --- a/mediagoblin/templates/mediagoblin/auth/register.html +++ b/mediagoblin/templates/mediagoblin/auth/register.html @@ -19,6 +19,26 @@ {% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} +{% block mediagoblin_head %} + <script> + $(document).ready(function(){ + $("#password").after('<input type="text" value="" name="password_clear" id="password_clear" /><input type="checkbox" id="password_boolean" />Show password'); + $('#password_clear').hide(); + $('#password_boolean').click(function(){ + if($('#password_boolean').prop("checked")) { + $('#password_clear').val($('#password').val()); + $('#password').hide(); + $('#password_clear').show(); + } else { + $('#password').val($('#password_clear').val()); + $('#password_clear').hide(); + $('#password').show(); + }; + }); + }); + </script> +{% endblock mediagoblin_head %} + {% block mediagoblin_content %} <form action="{{ request.urlgen('mediagoblin.auth.register') }}" @@ -29,7 +49,7 @@ {{ csrf_token }} <div class="form_submit_buttons"> <input type="submit" value="{% trans %}Create{% endtrans %}" - class="button" /> + class="button_form" /> </div> </div> </form> diff --git a/mediagoblin/templates/mediagoblin/base.html b/mediagoblin/templates/mediagoblin/base.html index b4c4dcf3..41efbc0d 100644 --- a/mediagoblin/templates/mediagoblin/base.html +++ b/mediagoblin/templates/mediagoblin/base.html @@ -19,7 +19,7 @@ <html> <head> <meta charset="utf-8"> - <title>{% block title %}{% trans %}GNU MediaGoblin{% endtrans %}{% endblock title %}</title> + <title>{% block title %}{{ app_config['html_title'] }}{% endblock %}</title> <link rel="stylesheet" type="text/css" href="{{ request.staticdirect('/css/extlib/reset.css') }}"/> <link rel="stylesheet" type="text/css" @@ -28,12 +28,15 @@ href="{{ request.staticdirect('/css/extlib/960_16_col.css') }}"/> <link rel="stylesheet" type="text/css" href="{{ request.staticdirect('/css/base.css') }}"/> + <link rel="stylesheet" type="text/css" + href="{{ request.staticdirect('/css/video-js.css') }}"/> <link rel="shortcut icon" href="{{ request.staticdirect('/images/goblin.ico') }}" /> + <script type="text/javascript" + src="{{ request.staticdirect('/js/extlib/jquery.js') }}"></script> {% block mediagoblin_head %} {% endblock mediagoblin_head %} </head> - <body> {% block mediagoblin_body %} <div class="mediagoblin_body"> @@ -46,10 +49,10 @@ ><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" + {% if request.user and request.user.status == 'active' %} + <a class="button_action" href="{{ request.urlgen('mediagoblin.submit.start') }}"> - {% trans %}Submit media{% endtrans %} + {% trans %}Add media{% endtrans %} </a> {% endif %} {% block mediagoblin_header_title %}{% endblock %} @@ -58,16 +61,16 @@ {# the following link should only appear when verification is needed #} {% if request.user.status == "needs_email_verification" %} <a href="{{ request.urlgen('mediagoblin.user_pages.user_home', - user=request.user['username']) }}" - class="header_submit"> - {% trans %}verify your email!{% endtrans %}</a> + user=request.user.username) }}" + class="button_action_highlight"> + {% trans %}Verify your email!{% endtrans %}</a> {% endif %} <a href="{{ request.urlgen('mediagoblin.user_pages.user_home', - user= request.user['username']) }}"> - {{ request.user['username'] }}</a> + user= request.user.username) }}"> + {{ request.user.username }}</a> - (<a href="{{ request.urlgen('mediagoblin.auth.logout') }}">log out</a>) + (<a href="{{ request.urlgen('mediagoblin.auth.logout') }}">{% trans %}log out{% endtrans %}</a>) {% else %} <a href="{{ request.urlgen('mediagoblin.auth.login') }}"> {% trans %}Log in{% endtrans %}</a> diff --git a/mediagoblin/templates/mediagoblin/edit/attachments.html b/mediagoblin/templates/mediagoblin/edit/attachments.html index d8b55f58..6a5ab896 100644 --- a/mediagoblin/templates/mediagoblin/edit/attachments.html +++ b/mediagoblin/templates/mediagoblin/edit/attachments.html @@ -20,7 +20,7 @@ {% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} {% block mediagoblin_content %} <form action="{{ request.urlgen('mediagoblin.edit.attachments', - user= media.uploader().username, + user= media.get_uploader().username, media= media._id) }}" method="POST" enctype="multipart/form-data"> <div class="grid_8 prefix_1 suffix_1 edit_box form_box"> @@ -48,7 +48,7 @@ {{ wtforms_util.render_divs(form) }} <div class="form_submit_buttons"> <a href="{{ media.url_for_self(request.urlgen) }}">Cancel</a> - <input type="submit" value="Save changes" class="button" /> + <input type="submit" value="Save changes" class="button_form" /> {{ csrf_token }} </div> </div> diff --git a/mediagoblin/templates/mediagoblin/edit/edit.html b/mediagoblin/templates/mediagoblin/edit/edit.html index b4b3be85..aa46af3d 100644 --- a/mediagoblin/templates/mediagoblin/edit/edit.html +++ b/mediagoblin/templates/mediagoblin/edit/edit.html @@ -22,7 +22,7 @@ {% block mediagoblin_content %} <form action="{{ request.urlgen('mediagoblin.edit.edit_media', - user= media.uploader().username, + user= media.get_uploader().username, media= media._id) }}" method="POST" enctype="multipart/form-data"> <div class="grid_8 prefix_1 suffix_1 edit_box form_box"> @@ -34,7 +34,7 @@ {{ wtforms_util.render_divs(form) }} <div class="form_submit_buttons"> <a href="{{ media.url_for_self(request.urlgen) }}">{% trans %}Cancel{% endtrans %}</a> - <input type="submit" value="{% trans %}Save changes{% endtrans %}" class="button" /> + <input type="submit" value="{% trans %}Save changes{% endtrans %}" class="button_form" /> {{ csrf_token }} </div> </div> diff --git a/mediagoblin/templates/mediagoblin/edit/edit_profile.html b/mediagoblin/templates/mediagoblin/edit/edit_profile.html index 93b2a792..2d5daa95 100644 --- a/mediagoblin/templates/mediagoblin/edit/edit_profile.html +++ b/mediagoblin/templates/mediagoblin/edit/edit_profile.html @@ -22,17 +22,17 @@ {% block mediagoblin_content %} <form action="{{ request.urlgen('mediagoblin.edit.profile') }}?username={{ - user['username'] }}" + user.username }}" method="POST" enctype="multipart/form-data"> <div class="grid_8 prefix_1 suffix_1 edit_box form_box"> <h1> - {%- trans username=user['username'] -%} + {%- trans username=user.username -%} Editing {{ username }}'s profile {%- endtrans %} </h1> {{ wtforms_util.render_divs(form) }} <div class="form_submit_buttons"> - <input type="submit" value="{% trans %}Save changes{% endtrans %}" class="button" /> + <input type="submit" value="{% trans %}Save changes{% endtrans %}" class="button_form" /> {{ csrf_token }} </div> </div> diff --git a/mediagoblin/templates/mediagoblin/listings/tag.html b/mediagoblin/templates/mediagoblin/listings/tag.html index 58863015..f797f72f 100644 --- a/mediagoblin/templates/mediagoblin/listings/tag.html +++ b/mediagoblin/templates/mediagoblin/listings/tag.html @@ -26,9 +26,13 @@ tag=tag_slug) }}"> {% endblock mediagoblin_head %} +{% block title %} + {% trans %}Media tagged with: {{ tag_name }}{% endtrans %} — {{ super() }} +{% endblock %} + {% block mediagoblin_content -%} <h1> - {% trans %}Media tagged with:{% endtrans %} {{ tag_name }} + {% trans %}Media tagged with: {{ tag_name }}{% endtrans %} </h1> <div class="container_16 media_gallery"> diff --git a/mediagoblin/templates/mediagoblin/media_displays/image.html b/mediagoblin/templates/mediagoblin/media_displays/image.html new file mode 100644 index 00000000..ad60fa94 --- /dev/null +++ b/mediagoblin/templates/mediagoblin/media_displays/image.html @@ -0,0 +1 @@ +{% extends 'mediagoblin/user_pages/media.html' %} diff --git a/mediagoblin/templates/mediagoblin/media_displays/video.html b/mediagoblin/templates/mediagoblin/media_displays/video.html new file mode 100644 index 00000000..5ef1a782 --- /dev/null +++ b/mediagoblin/templates/mediagoblin/media_displays/video.html @@ -0,0 +1,25 @@ +{% extends 'mediagoblin/user_pages/media.html' %} +{% block mediagoblin_media %} + <div class="video-player" style="position: relative;"> + <video class="video-js vjs-default-skin" + width="{{ media.media_data.video.width }}" + height="{{ media.media_data.video.height }}" + controls="controls" + preload="auto" + data-setup=""> + <source src="{{ request.app.public_store.file_url( + media['media_files']['webm_640']) }}" + type="video/webm; codecs="vp8, vorbis"" /> + </video> + </div> + {% if 'original' in media.media_files %} + <p> + <a href="{{ request.app.public_store.file_url( + media['media_files']['original']) }}"> + {%- trans -%} + Original + {%- endtrans -%} + </a> + </p> + {% endif %} +{% endblock %} diff --git a/mediagoblin/templates/mediagoblin/root.html b/mediagoblin/templates/mediagoblin/root.html index 43d973d1..0f769f2f 100644 --- a/mediagoblin/templates/mediagoblin/root.html +++ b/mediagoblin/templates/mediagoblin/root.html @@ -25,14 +25,14 @@ {% else %} <div class="grid_11 alpha"> <h1>{% trans %}Hi there, welcome to this MediaGoblin site!{% endtrans %}</h1> - <p>{% trans %}Your finest source for all goblin-related media.{% endtrans %}</p> + <p>{% trans %}This site is running <a href="http://mediagoblin.org">MediaGoblin</a>, an extraordinarily great piece of media hosting software.{% endtrans %}</p> <p>{% trans %}To add your own media, place comments, save your favourites and more, you can log in with your MediaGoblin account.{% endtrans %}</p> {% if allow_registration %} <p>{% trans %}Don't have one yet? It's easy!{% endtrans %}</p> {% trans register_url=request.urlgen('mediagoblin.auth.register') -%} - <a class="header_submit_highlight" href="{{ register_url }}">Create an account at this site</a> + <a class="button_action_highlight" href="{{ register_url }}">Create an account at this site</a> or - <a class="header_submit" href="http://wiki.mediagoblin.org/HackingHowto">Set up MediaGoblin on your own server</a> + <a class="button_action" href="http://wiki.mediagoblin.org/HackingHowto">Set up MediaGoblin on your own server</a> {%- endtrans %} {% endif %} </div> diff --git a/mediagoblin/templates/mediagoblin/submit/start.html b/mediagoblin/templates/mediagoblin/submit/start.html index 29b01181..47914550 100644 --- a/mediagoblin/templates/mediagoblin/submit/start.html +++ b/mediagoblin/templates/mediagoblin/submit/start.html @@ -23,11 +23,11 @@ <form action="{{ request.urlgen('mediagoblin.submit.start') }}" method="POST" enctype="multipart/form-data"> <div class="grid_8 prefix_1 suffix_1 form_box"> - <h1>{% trans %}Submit yer media{% endtrans %}</h1> + <h1>{% trans %}Add your media{% endtrans %}</h1> {{ wtforms_util.render_divs(submit_form) }} <div class="form_submit_buttons"> {{ csrf_token }} - <input type="submit" value="{% trans %}Submit{% endtrans %}" class="button" /> + <input type="submit" value="{% trans %}Add{% endtrans %}" class="button_form" /> </div> </div> </form> diff --git a/mediagoblin/templates/mediagoblin/test_submit.html b/mediagoblin/templates/mediagoblin/test_submit.html index 190b9ac3..38be8efc 100644 --- a/mediagoblin/templates/mediagoblin/test_submit.html +++ b/mediagoblin/templates/mediagoblin/test_submit.html @@ -25,7 +25,7 @@ {{ wtforms_util.render_table(image_form) }} <tr> <td></td> - <td><input type="submit" value="submit" class="button" /></td> + <td><input type="submit" value="submit" class="button_form" /></td> {{ csrf_token }} </tr> </table> diff --git a/mediagoblin/templates/mediagoblin/user_pages/gallery.html b/mediagoblin/templates/mediagoblin/user_pages/gallery.html index df931d9c..b066dd71 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/gallery.html +++ b/mediagoblin/templates/mediagoblin/user_pages/gallery.html @@ -26,29 +26,30 @@ user=user.username) }}"> {% endblock mediagoblin_head %} +{% block title %} + {%- trans username=user.username -%} + {{ username }}'s media + {%- endtrans %} — {{ super() }} +{% endblock %} + {% block mediagoblin_content -%} - {% if user %} - <h1> - {%- trans username=user.username, - user_url=request.urlgen( - 'mediagoblin.user_pages.user_home', - user=user.username) -%} - <a href="{{ user_url }}">{{ username }}</a>'s media - {%- endtrans %} - </h1> + <h1> + {%- trans username=user.username, + user_url=request.urlgen( + 'mediagoblin.user_pages.user_home', + user=user.username) -%} + <a href="{{ user_url }}">{{ username }}</a>'s media + {%- endtrans %} + </h1> - <div class="container_16 media_gallery"> - {{ object_gallery(request, media_entries, pagination) }} - </div> + <div class="container_16 media_gallery"> + {{ object_gallery(request, media_entries, pagination) }} + </div> - <div class="grid_16"> - {% set feed_url = request.urlgen( - 'mediagoblin.user_pages.atom_feed', - user=user.username) %} - {% include "mediagoblin/utils/feed_link.html" %} - </div> - {% else %} - {# This *should* not occur as the view makes sure we pass in a user. #} - <p>{% trans %}Sorry, no such user found.{% endtrans %}<p/> - {% endif %} + <div class="grid_16"> + {% set feed_url = request.urlgen( + 'mediagoblin.user_pages.atom_feed', + user=user.username) %} + {% include "mediagoblin/utils/feed_link.html" %} + </div> {% endblock %} diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html index 17beffb2..2c8c5033 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/media.html +++ b/mediagoblin/templates/mediagoblin/user_pages/media.html @@ -20,13 +20,28 @@ {% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} {% from "mediagoblin/utils/pagination.html" import render_pagination %} +{% block title %}{{ media.title }} — {{ super() }}{% endblock %} + +{% block mediagoblin_head %} + <script> + $(document).ready(function(){ + $('#form_comment').hide(); + $('#button_addcomment').click(function(){ + $(this).fadeOut('fast'); + $('#form_comment').slideDown(function(){ + $('#comment_content').focus(); + }); + }); + }); + </script> +{% endblock mediagoblin_head %} + {% block mediagoblin_content %} - {% if media %} - <div class="grid_11 alpha"> - <div class="media_image_container"> + <div class="grid_11 alpha"> + <div class="media_image_container"> + {% block mediagoblin_media %} {% set display_media = request.app.public_store.file_url( media.get_display_media(media.media_files)) %} - {# if there's a medium file size, that means the medium size # isn't the original... so link to the original! #} @@ -42,127 +57,121 @@ src="{{ display_media }}" alt="Image for {{ media.title }}" /> {% endif %} + {% endblock %} + </div> + <h2 class="media_title"> + {{ media.title }} + </h2> + {% autoescape False %} + <p>{{ media.description_html }}</p> + {% endautoescape %} + <p class="media_specs"> + {% trans date=media.created.strftime("%Y-%m-%d") -%} + Added on {{ date }}. + {%- endtrans %} + {% if media['uploader'] == request.user._id or + request.user['is_admin'] %} + {% set edit_url = request.urlgen('mediagoblin.edit.edit_media', + user= media.get_uploader().username, + media= media._id) %} + <a class="button_action" href="{{ edit_url }}">{% trans %}Edit{% endtrans %}</a> + {% set delete_url = request.urlgen('mediagoblin.user_pages.media_confirm_delete', + user= media.get_uploader().username, + media= media._id) %} + <a class="button_action" href="{{ delete_url }}">{% trans %}Delete{% endtrans %}</a> + {% endif %} + </p> + <h3>{% trans %}23 comments{% endtrans %} + <div class="right_align"> + <a + {% if not request.user %} + href="{{ request.urlgen('mediagoblin.auth.login') }}" + {% endif %} + class="button_action" id="button_addcomment" title="Add a comment"> + {% trans %}Add one{% endtrans %} + </a> </div> - - <h2 class="media_title"> - {{ media.title }} - </h2> - {% autoescape False %} - <p>{{ media.description_html }}</p> - {% endautoescape %} - <p class="media_uploader"> - {% trans date=media.created.strftime("%Y-%m-%d"), - user_url=request.urlgen( - 'mediagoblin.user_pages.user_home', - user=media.uploader().username), - username=media.uploader().username -%} - By <a href="{{ user_url }}">{{ username }}</a> on {{ date }} - {%- endtrans %} - </p> - <h3></h3> + </h3> + {# 0 comments. Be the first to add one! #} {% if request.user %} - <p><a href="#comment_form">{% trans %}Post a comment{% endtrans %}</a></p> + <form action="{{ request.urlgen('mediagoblin.user_pages.media_post_comment', + user= media.get_uploader().username, + media=media._id) }}" method="POST" id="form_comment"> + <p> + {% trans %}Type your comment here. You can use <a href="http://daringfireball.net/projects/markdown/basics" target="_blank">Markdown</a> for formatting.{% endtrans %} + </p> + {{ wtforms_util.render_divs(comment_form) }} + <div class="form_submit_buttons"> + <input type="submit" value="{% trans %}Add this comment{% endtrans %}" class="button_action" /> + {{ csrf_token }} + </div> + </form> {% endif %} {% if comments %} {% for comment in comments %} {% set comment_author = comment.author() %} - {% if pagination.active_id == comment._id %} - <div class="comment_wrapper comment_active" id="comment-{{ comment['_id'] }}"> - <a name="comment" id="comment"></a> + {% if pagination.active_id == comment._id %} + <div class="comment_wrapper comment_active" id="comment-{{ comment._id }}"> + <a name="comment" id="comment"></a> {% else %} - <div class="comment_wrapper" id="comment-{{ comment['_id'] }}"> - {% endif %} - - <div class="comment_content">{% autoescape False %}{{ comment.content_html }} - {% endautoescape %} - <img src="{{ request.staticdirect('/images/icon_comment.png') }}" /> - <a href="{{ request.urlgen('mediagoblin.user_pages.user_home', - user = comment_author['username']) }}"> - {{ comment_author['username'] }}</a> - {% trans %}at{% endtrans %} - <a href="{{ request.urlgen('mediagoblin.user_pages.media_home.view_comment', - comment = comment['_id'], - user = media.uploader().username, - media = media._id) }}#comment"> - {{ comment.created.strftime("%I:%M%p %Y-%m-%d") }} - </a> - </div> - </div> + <div class="comment_wrapper" id="comment-{{ comment._id }}"> + {% endif %} + <div class="comment_content"> + {% autoescape False %} + {{ comment.content_html }} + {% endautoescape %} + <img src="{{ request.staticdirect('/images/icon_comment.png') }}" /> + <a href="{{ request.urlgen('mediagoblin.user_pages.user_home', + user = comment_author.username) }}"> + {{ comment_author.username }} + </a> + {% trans %}at{% endtrans %} + <a href="{{ request.urlgen('mediagoblin.user_pages.media_home.view_comment', + comment = comment._id, + user = media.get_uploader().username, + media = media.slug) }}#comment"> + {{ comment.created.strftime("%I:%M%p %Y-%m-%d") }} + </a> + </div> + </div> {% endfor %} - - {% if request.user %} - <form action="{{ request.urlgen('mediagoblin.user_pages.media_post_comment', - user= media.uploader().username, - media=media._id) }}" method="POST"> - {{ wtforms_util.render_divs(comment_form) }} - <div class="form_submit_buttons"> - <input type="submit" value="{% trans %}Post comment!{% endtrans %}" class="button" /> - {{ csrf_token }} - </div> - </form> - {% endif %} - - {{ render_pagination(request, pagination, - request.urlgen('mediagoblin.user_pages.media_home', - user = media.uploader().username, - media = media._id)) }} - </div> + {{ render_pagination(request, pagination, + request.urlgen('mediagoblin.user_pages.media_home', + user = media.get_uploader().username, + media = media._id)) }} {% endif %} - - <div class="grid_5 omega"> - {% include "mediagoblin/utils/prev_next.html" %} - - {% if media['uploader'] == request.user['_id'] or - request.user['is_admin'] %} - <h3>{% trans %}Actions{% endtrans %}</h3> - <p> - {% set edit_url = request.urlgen('mediagoblin.edit.edit_media', - user= media.uploader().username, - media= media._id) %} - <a href="{{ edit_url }}" - ><img src="{{ request.staticdirect('/images/icon_edit.png') }}" - class="media_icon" /></a> - <a href="{{ edit_url }}">{% trans %}edit{% endtrans %}</a> - </p> - <p> - {% set delete_url = request.urlgen('mediagoblin.user_pages.media_confirm_delete', - user= media.uploader().username, - media= media._id) %} - <a href="{{ delete_url }}" - ><img src="{{ request.staticdirect('/images/icon_delete.png') }}" - class="media_icon" /></a> - <a href="{{ delete_url }}">{% trans %}delete{% endtrans %}</a> - </p> - {% endif %} - - {% if media.attachment_files|count %} - <h3>Attachments</h3> - <ul> - {% for attachment in media.attachment_files %} - <li> - <a href="{{ request.app.public_store.file_url(attachment.filepath) }}"> - {{ attachment.name }} - </a> - </li> - {% endfor %} - </ul> - {% endif %} - - {% if app_config['allow_attachments'] - and (media['uploader'] == request.user['_id'] - or request.user['is_admin']) %} - <p> - <a href="{{ request.urlgen('mediagoblin.edit.attachments', - user=media.uploader().username, - media=media._id) }}">Add attachment</a> - </p> - {% endif %} - - {% if media.tags %} - {% include "mediagoblin/utils/tags.html" %} - {% endif %} - </div> - {% else %} - <p>{% trans %}Sorry, no such media found.{% endtrans %}<p/> - {% endif %} + </div> + <div class="grid_5 omega"> + {% trans user_url=request.urlgen( + 'mediagoblin.user_pages.user_home', + user=media.get_uploader().username), + username=media.get_uploader().username -%} + <p>â– Browsing media by <a href="{{ user_url }}">{{ username }}</a></p> + {%- endtrans %} + {% include "mediagoblin/utils/prev_next.html" %} + {% if media.attachment_files|count %} + <h3>Attachments</h3> + <ul> + {% for attachment in media.attachment_files %} + <li> + <a href="{{ request.app.public_store.file_url(attachment.filepath) }}"> + {{ attachment.name }} + </a> + </li> + {% endfor %} + </ul> + {% endif %} + {% if app_config['allow_attachments'] + and (media.uploader == request.user._id + or request.user.is_admin) %} + <p> + <a href="{{ request.urlgen('mediagoblin.edit.attachments', + user=media.get_uploader().username, + media=media._id) }}">Add attachment</a> + </p> + {% endif %} + {% if media.tags %} + {% include "mediagoblin/utils/tags.html" %} + {% endif %} + </div> {% endblock %} diff --git a/mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html b/mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html index 8da90f79..7c7218ae 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html +++ b/mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html @@ -22,12 +22,12 @@ {% block mediagoblin_content %} <form action="{{ request.urlgen('mediagoblin.user_pages.media_confirm_delete', - user=media.uploader().username, + user=media.get_uploader().username, media=media._id) }}" method="POST" enctype="multipart/form-data"> <div class="grid_8 prefix_1 suffix_1 edit_box form_box"> <h1> - {%- trans title=media['title'] -%} + {%- trans title=media.title -%} Really delete {{ title }}? {%- endtrans %} </h1> @@ -47,7 +47,7 @@ <div class="form_submit_buttons"> {# TODO: This isn't a button really... might do unexpected things :) #} <a class="cancel_link" href="{{ media.url_for_self(request.urlgen) }}">{% trans %}Cancel{% endtrans %}</a> - <input type="submit" value="{% trans %}Delete Permanently{% endtrans %}" class="button" /> + <input type="submit" value="{% trans %}Delete Permanently{% endtrans %}" class="button_form" /> {{ csrf_token }} </div> </div> diff --git a/mediagoblin/templates/mediagoblin/user_pages/processing_panel.html b/mediagoblin/templates/mediagoblin/user_pages/processing_panel.html index 9b4adeb5..a14b0123 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/processing_panel.html +++ b/mediagoblin/templates/mediagoblin/user_pages/processing_panel.html @@ -36,8 +36,8 @@ </tr> {% for media_entry in processing_entries %} <tr> - <td>{{ media_entry['title'] }}</td> - <td>{{ media_entry['created'].strftime("%m-%d-%Y %I:%M %p") }}</td> + <td>{{ media_entry.title }}</td> + <td>{{ media_entry.created.strftime("%m-%d-%Y %I:%M %p") }}</td> <td></td> </tr> {% endfor %} @@ -57,7 +57,7 @@ </tr> {% for media_entry in failed_entries %} <tr> - <td>{{ media_entry['title'] }}</td> + <td>{{ media_entry.title }}</td> <td>{{ media_entry['created'].strftime("%m-%d-%Y %I:%M %p") }}</td> <td>{{ media_entry.get_fail_exception().general_message }}</td> </tr> diff --git a/mediagoblin/templates/mediagoblin/user_pages/user.html b/mediagoblin/templates/mediagoblin/user_pages/user.html index 6d938262..b952e88c 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/user.html +++ b/mediagoblin/templates/mediagoblin/user_pages/user.html @@ -26,6 +26,17 @@ user=user.username) }}"> {% endblock mediagoblin_head %} +{% block title %} + {%- if user -%} + {%- trans username=user.username -%} + {{ username }}'s profile + {%- endtrans %} — {{ super() }} + {%- else -%} + {{ super() }} + {%- endif -%} +{% endblock %} + + {% block mediagoblin_content -%} {# If no user... #} {% if not user %} @@ -51,7 +62,7 @@ <p>{% trans %}In case it doesn't:{% endtrans %}</p> <a href="{{ request.urlgen('mediagoblin.auth.resend_verification') }}" - class="button">{% trans %}Resend verification email{% endtrans %}</a> + class="button_action_highlight">{% trans %}Resend verification email{% endtrans %}</a> </div> {% else %} {# if the user is not you, but still needs to verify their email #} @@ -78,15 +89,15 @@ {%- trans username=user.username %}{{ username }}'s profile{% endtrans -%} </h1> - {% if not user['url'] and not user['bio'] %} - {% if request.user['_id'] == user['_id'] %} + {% if not user.url and not user.bio %} + {% if request.user._id == user._id %} <div class="grid_6 alpha empty_space"> <p> {% trans %}Here's a spot to tell others about yourself.{% endtrans %} </p> <a href="{{ request.urlgen('mediagoblin.edit.profile') }}?username={{ user.username }}" - class="header_submit"> + class="button_action"> {%- trans %}Edit profile{% endtrans -%} </a> </div> @@ -102,7 +113,7 @@ {% else %} <div class="grid_6 alpha"> {% include "mediagoblin/utils/profile.html" %} - {% if request.user['_id'] == user['_id'] or request.user['is_admin'] %} + {% if request.user._id == user._id or request.user.is_admin %} <a href="{{ request.urlgen('mediagoblin.edit.profile') }}?username={{ user.username }}"> {%- trans %}Edit profile{% endtrans -%} @@ -129,14 +140,14 @@ {% include "mediagoblin/utils/feed_link.html" %} </div> {% else %} - {% if request.user['_id'] == user['_id'] %} + {% if request.user._id == user._id %} <div class="grid_10 omega empty_space"> <p> {% trans -%} This is where your media will appear, but you don't seem to have added anything yet. {%- endtrans %} </p> - <a class="header_submit" + <a class="button_action" href="{{ request.urlgen('mediagoblin.submit.start') }}"> {%- trans %}Add media{% endtrans -%} </a> diff --git a/mediagoblin/templates/mediagoblin/utils/object_gallery.html b/mediagoblin/templates/mediagoblin/utils/object_gallery.html index e1b8cc9b..65ff09a4 100644 --- a/mediagoblin/templates/mediagoblin/utils/object_gallery.html +++ b/mediagoblin/templates/mediagoblin/utils/object_gallery.html @@ -33,9 +33,9 @@ <img src="{{ request.app.public_store.file_url( entry['media_files']['thumb']) }}" /> </a> - {% if entry['title'] %} + {% if entry.title %} <br /> - <a href="{{ entry_url }}">{{ entry['title'] }}</a> + <a href="{{ entry_url }}">{{ entry.title }}</a> {% endif %} </td> {% endfor %} diff --git a/mediagoblin/templates/mediagoblin/utils/pagination.html b/mediagoblin/templates/mediagoblin/utils/pagination.html index 84336103..caa79fcc 100644 --- a/mediagoblin/templates/mediagoblin/utils/pagination.html +++ b/mediagoblin/templates/mediagoblin/utils/pagination.html @@ -36,18 +36,16 @@ {% set prev_url = pagination.get_page_url_explicit( base_url, get_params, pagination.page - 1) %} - <a href="{{ prev_url }}"><img class="pagination_arrow" src="{{ request.staticdirect('/images/pagination_left.png') }}" alt="Previous page" /></a> - <a href="{{ prev_url }}">{% trans %}Newer{% endtrans %}</a> + <a href="{{ prev_url }}">{% trans %}↠Newer{% endtrans %}</a> {% endif %} {% if pagination.has_next %} {% set next_url = pagination.get_page_url_explicit( base_url, get_params, pagination.page + 1) %} - <a href="{{ next_url }}">{% trans %}Older{% endtrans %}</a> - <a href="{{ next_url }}"><img class="pagination_arrow" src="{{ request.staticdirect('/images/pagination_right.png') }}" alt="Next page" /></a> + <a href="{{ next_url }}">{% trans %}Older →{% endtrans %}</a> {% endif %} <br /> - Go to page: + {% trans %}Go to page:{% endtrans %} {%- for page in pagination.iter_pages() %} {% if page %} {% if page != pagination.page %} diff --git a/mediagoblin/templates/mediagoblin/utils/prev_next.html b/mediagoblin/templates/mediagoblin/utils/prev_next.html index 75903076..b0c01963 100644 --- a/mediagoblin/templates/mediagoblin/utils/prev_next.html +++ b/mediagoblin/templates/mediagoblin/utils/prev_next.html @@ -25,23 +25,23 @@ {# There are no previous entries for the very first media entry #} {% if prev_entry_url %} <a class="navigation_button navigation_left" href="{{ prev_entry_url }}"> - <img src="{{ request.staticdirect('/images/navigation_left.png') }}" alt="Previous image" /> + ← {% trans %}newer{% endtrans %} </a> {% else %} {# This is the first entry. display greyed-out 'previous' image #} <p class="navigation_button navigation_left"> - <img src="{{ request.staticdirect('/images/navigation_end.png') }}" alt="No previous images" /> + ← {% trans %}newer{% endtrans %} </p> {% endif %} {# Likewise, this could be the very last media entry #} {% if next_entry_url %} <a class="navigation_button" href="{{ next_entry_url }}"> - <img src="{{ request.staticdirect('/images/navigation_right.png') }}" alt="Next image" /> + {% trans %}older{% endtrans %} → </a> {% else %} {# This is the last entry. display greyed-out 'next' image #} <p class="navigation_button"> - <img src="{{ request.staticdirect('/images/navigation_end.png') }}" alt="No following images" /> + {% trans %}older{% endtrans %} → </p> {% endif %} </div> diff --git a/mediagoblin/templates/mediagoblin/utils/tags.html b/mediagoblin/templates/mediagoblin/utils/tags.html index b3211bd9..1f587411 100644 --- a/mediagoblin/templates/mediagoblin/utils/tags.html +++ b/mediagoblin/templates/mediagoblin/utils/tags.html @@ -17,13 +17,25 @@ #} {% block tags_content -%} - <h3>Tags</h3> - <ul class="mediaentry_tags"> + <p>{% trans %}View more media tagged with{% endtrans %} {% for tag in media.tags %} - <li class="tag"> + {% if loop.last %} + {# the 'and' should only appear if there is more than one tag #} + {% if media.tags|length > 1 %} + {% trans %}or{% endtrans %} + {% endif %} <a href="{{ request.urlgen( - 'mediagoblin.listings.tags_listing', - tag=tag['slug']) }}">{{ tag['name'] }}</a></li> + 'mediagoblin.listings.tags_listing', + tag=tag['slug']) }}">{{ tag['name'] }}</a>. + {% elif loop.revindex == 2 %} + <a href="{{ request.urlgen( + 'mediagoblin.listings.tags_listing', + tag=tag['slug']) }}">{{ tag['name'] }}</a> + {% else %} + <a href="{{ request.urlgen( + 'mediagoblin.listings.tags_listing', + tag=tag['slug']) }}">{{ tag['name'] }}</a>, + {% endif %} {% endfor %} - </ul> + </p> {% endblock %} diff --git a/mediagoblin/templates/mediagoblin/utils/wtforms.html b/mediagoblin/templates/mediagoblin/utils/wtforms.html index 6a86fd24..cc30388f 100644 --- a/mediagoblin/templates/mediagoblin/utils/wtforms.html +++ b/mediagoblin/templates/mediagoblin/utils/wtforms.html @@ -18,18 +18,18 @@ {# Generically render a field #} {% macro render_field_div(field) %} - <div class="form_field_box"> - <div class="form_field_label">{{ _(field.label.text) }}</div> - <div class="form_field_input">{{ field }}</div> + {% if field.label.text -%} + <p class="form_field_label"><label for="{{ field.name }}">{{ _(field.label.text) }}</label></p> + {%- endif %} + <div class="form_field_input"> + {{ field }} {%- if field.errors -%} {% for error in field.errors %} - <div class="form_field_error"> - {{ error }} - </div> + <p class="form_field_error">{{ error }}</p> {% endfor %} {%- endif %} {% if field.description -%} - <div class="form_field_description">{{ _(field.description) }}</div> + <p class="form_field_description">{{ _(field.description) }}</p> {%- endif %} </div> {%- endmacro %} diff --git a/mediagoblin/tests/test_auth.py b/mediagoblin/tests/test_auth.py index 40961eca..d3b8caf1 100644 --- a/mediagoblin/tests/test_auth.py +++ b/mediagoblin/tests/test_auth.py @@ -20,7 +20,7 @@ import datetime from nose.tools import assert_equal from mediagoblin.auth import lib as auth_lib -from mediagoblin.tests.tools import setup_fresh_app +from mediagoblin.tests.tools import setup_fresh_app, fixture_add_user from mediagoblin import mg_globals from mediagoblin.tools import template, mail @@ -162,13 +162,13 @@ def test_register_views(test_app): new_user = mg_globals.database.User.find_one( {'username': 'happygirl'}) assert new_user - assert new_user['status'] == u'needs_email_verification' - assert new_user['email_verified'] == False + assert new_user.status == u'needs_email_verification' + assert new_user.email_verified == False ## Make sure user is logged in request = template.TEMPLATE_TEST_CONTEXT[ 'mediagoblin/user_pages/user.html']['request'] - assert request.session['user_id'] == unicode(new_user['_id']) + assert request.session['user_id'] == unicode(new_user._id) ## Make sure we get email confirmation, and try verifying assert len(mail.EMAIL_TEST_INBOX) == 1 @@ -185,15 +185,15 @@ def test_register_views(test_app): ### user should have these same parameters assert parsed_get_params['userid'] == [ - unicode(new_user['_id'])] + unicode(new_user._id)] assert parsed_get_params['token'] == [ - new_user['verification_key']] + new_user.verification_key] ## Try verifying with bs verification key, shouldn't work template.clear_test_template_context() response = test_app.get( "/auth/verify_email/?userid=%s&token=total_bs" % unicode( - new_user['_id'])) + new_user._id)) response.follow() context = template.TEMPLATE_TEST_CONTEXT[ 'mediagoblin/user_pages/user.html'] @@ -202,8 +202,8 @@ def test_register_views(test_app): new_user = mg_globals.database.User.find_one( {'username': 'happygirl'}) assert new_user - assert new_user['status'] == u'needs_email_verification' - assert new_user['email_verified'] == False + assert new_user.status == u'needs_email_verification' + assert new_user.email_verified == False ## Verify the email activation works template.clear_test_template_context() @@ -216,8 +216,8 @@ def test_register_views(test_app): new_user = mg_globals.database.User.find_one( {'username': 'happygirl'}) assert new_user - assert new_user['status'] == u'active' - assert new_user['email_verified'] == True + assert new_user.status == u'active' + assert new_user.email_verified == True # Uniqueness checks # ----------------- @@ -269,28 +269,28 @@ def test_register_views(test_app): # user should have matching parameters new_user = mg_globals.database.User.find_one({'username': 'happygirl'}) - assert parsed_get_params['userid'] == [unicode(new_user['_id'])] - assert parsed_get_params['token'] == [new_user['fp_verification_key']] + assert parsed_get_params['userid'] == [unicode(new_user._id)] + assert parsed_get_params['token'] == [new_user.fp_verification_key] ### The forgotten password token should be set to expire in ~ 10 days # A few ticks have expired so there are only 9 full days left... - assert (new_user['fp_token_expire'] - datetime.datetime.now()).days == 9 + assert (new_user.fp_token_expire - datetime.datetime.now()).days == 9 ## Try using a bs password-changing verification key, shouldn't work template.clear_test_template_context() response = test_app.get( "/auth/forgot_password/verify/?userid=%s&token=total_bs" % unicode( - new_user['_id']), status=400) - assert response.status == '400 Bad Request' + new_user._id), status=404) + assert_equal(response.status, '404 Not Found') ## Try using an expired token to change password, shouldn't work template.clear_test_template_context() - real_token_expiration = new_user['fp_token_expire'] - new_user['fp_token_expire'] = datetime.datetime.now() + real_token_expiration = new_user.fp_token_expire + new_user.fp_token_expire = datetime.datetime.now() new_user.save() - response = test_app.get("%s?%s" % (path, get_params), status=400) - assert response.status == '400 Bad Request' - new_user['fp_token_expire'] = real_token_expiration + response = test_app.get("%s?%s" % (path, get_params), status=404) + assert_equal(response.status, '404 Not Found') + new_user.fp_token_expire = real_token_expiration new_user.save() ## Verify step 1 of password-change works -- can see form to change password @@ -332,11 +332,7 @@ def test_authentication_views(test_app): Test logging in and logging out """ # Make a new user - test_user = mg_globals.database.User() - test_user['username'] = u'chris' - test_user['email'] = u'chris@example.com' - test_user['pw_hash'] = auth_lib.bcrypt_gen_password_hash('toast') - test_user.save() + test_user = fixture_add_user(active_user=False) # Get login # --------- @@ -412,7 +408,7 @@ def test_authentication_views(test_app): # Make sure user is in the session context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html'] session = context['request'].session - assert session['user_id'] == unicode(test_user['_id']) + assert session['user_id'] == unicode(test_user._id) # Successful logout # ----------------- diff --git a/mediagoblin/tests/test_celery_setup.py b/mediagoblin/tests/test_celery_setup.py index 348a4357..19a9b899 100644 --- a/mediagoblin/tests/test_celery_setup.py +++ b/mediagoblin/tests/test_celery_setup.py @@ -50,7 +50,7 @@ def test_setup_celery_from_config(): assert isinstance(fake_celery_module.CELERYD_ETA_SCHEDULER_PRECISION, float) assert fake_celery_module.CELERY_RESULT_PERSISTENT is True assert fake_celery_module.CELERY_IMPORTS == [ - 'foo.bar.baz', 'this.is.an.import', 'mediagoblin.process_media'] + 'foo.bar.baz', 'this.is.an.import', 'mediagoblin.processing'] assert fake_celery_module.CELERY_MONGODB_BACKEND_SETTINGS == { 'database': 'mediagoblin'} assert fake_celery_module.CELERY_RESULT_BACKEND == 'mongodb' @@ -74,7 +74,7 @@ def test_setup_celery_from_config(): assert isinstance(fake_celery_module.CELERYD_ETA_SCHEDULER_PRECISION, float) assert fake_celery_module.CELERY_RESULT_PERSISTENT is False assert fake_celery_module.CELERY_IMPORTS == [ - 'baz.bar.foo', 'import.is.a.this', 'mediagoblin.process_media'] + 'baz.bar.foo', 'import.is.a.this', 'mediagoblin.processing'] assert fake_celery_module.CELERY_MONGODB_BACKEND_SETTINGS == { 'database': 'captain_lollerskates', 'host': 'mongodb.example.org', diff --git a/mediagoblin/tests/test_csrf_middleware.py b/mediagoblin/tests/test_csrf_middleware.py index 691f10b9..c8fca23a 100644 --- a/mediagoblin/tests/test_csrf_middleware.py +++ b/mediagoblin/tests/test_csrf_middleware.py @@ -27,7 +27,7 @@ from mediagoblin import mg_globals def test_csrf_cookie_set(test_app): cookie_name = mg_globals.app_config['csrf_cookie_name'] - + # get login page response = test_app.get('/auth/login/') @@ -69,3 +69,22 @@ def test_csrf_token_must_match(test_app): mg_globals.app_config['csrf_cookie_name'])}, extra_environ={'gmg.verify_csrf': True}).\ status_int == 200 + +@setup_fresh_app +def test_csrf_exempt(test_app): + + # monkey with the views to decorate a known endpoint + import mediagoblin.auth.views + from mediagoblin.meddleware.csrf import csrf_exempt + + mediagoblin.auth.views.login = csrf_exempt( + mediagoblin.auth.views.login + ) + + # construct a request with no cookie or form token + assert test_app.post('/auth/login/', + extra_environ={'gmg.verify_csrf': True}, + expect_errors=False).status_int == 200 + + # restore the CSRF protection in case other tests expect it + mediagoblin.auth.views.login.csrf_enabled = True diff --git a/mediagoblin/tests/test_edit.py b/mediagoblin/tests/test_edit.py new file mode 100644 index 00000000..0cf71e9b --- /dev/null +++ b/mediagoblin/tests/test_edit.py @@ -0,0 +1,99 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +from mediagoblin import mg_globals +from mediagoblin.tests.tools import setup_fresh_app, fixture_add_user +from mediagoblin.tools import template +from mediagoblin.auth.lib import bcrypt_check_password + + +@setup_fresh_app +def test_change_password(test_app): + """Test changing password correctly and incorrectly""" + # set up new user + test_user = fixture_add_user() + + test_app.post( + '/auth/login/', { + 'username': u'chris', + 'password': 'toast'}) + + # test that the password can be changed + # template.clear_test_template_context() + test_app.post( + '/edit/profile/', { + 'bio': u'', + 'url': u'', + 'old_password': 'toast', + 'new_password': '123456', + 'confirm_password': '123456'}) + + # test_user has to be fetched again in order to have the current values + test_user = mg_globals.database.User.one({'username': 'chris'}) + + assert bcrypt_check_password('123456', test_user.pw_hash) + + # test that the password cannot be changed if the given old_password + # is wrong + # template.clear_test_template_context() + test_app.post( + '/edit/profile/', { + 'bio': u'', + 'url': u'', + 'old_password': 'toast', + 'new_password': '098765', + 'confirm_password': '098765'}) + + test_user = mg_globals.database.User.one({'username': 'chris'}) + + assert not bcrypt_check_password('098765', test_user.pw_hash) + + +@setup_fresh_app +def change_bio_url(test_app): + """Test changing bio and URL""" + # set up new user + test_user = fixture_add_user() + + # test changing the bio and the URL properly + test_app.post( + '/edit/profile/', { + 'bio': u'I love toast!', + 'url': u'http://dustycloud.org/'}) + + test_user = mg_globals.database.User.one({'username': 'chris'}) + + assert test_user.bio == u'I love toast!' + assert test_user.url == u'http://dustycloud.org/' + + # test changing the bio and the URL inproperly + too_long_bio = 150 * 'T' + 150 * 'o' + 150 * 'a' + 150 * 's' + 150* 't' + + test_app.post( + '/edit/profile/', { + # more than 500 characters + 'bio': too_long_bio, + 'url': 'this-is-no-url'}) + + test_user = mg_globals.database.User.one({'username': 'chris'}) + + context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/edit/edit_profile.html'] + form = context['edit_profile_form'] + + assert form.bio.errors == [u'Field must be between 0 and 500 characters long.'] + assert form.url.errors == [u'Improperly formed URL'] + + # test changing the url inproperly diff --git a/mediagoblin/tests/test_mgoblin_app.ini b/mediagoblin/tests/test_mgoblin_app.ini index f979e810..2525a4f9 100644 --- a/mediagoblin/tests/test_mgoblin_app.ini +++ b/mediagoblin/tests/test_mgoblin_app.ini @@ -5,7 +5,6 @@ email_debug_mode = true db_name = __mediagoblin_tests__ # tag parsing -tags_delimiter = "," tags_max_length = 50 # Celery shouldn't be set up by the application as it's setup via diff --git a/mediagoblin/middleware/__init__.py b/mediagoblin/tests/test_misc.py index 05325ee5..09623355 100644 --- a/mediagoblin/middleware/__init__.py +++ b/mediagoblin/tests/test_misc.py @@ -14,7 +14,13 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -ENABLED_MIDDLEWARE = ( - 'mediagoblin.middleware.noop:NoOpMiddleware', - 'mediagoblin.middleware.csrf:CsrfMiddleware', - ) +from nose.tools import assert_equal + +from mediagoblin.tests.tools import setup_fresh_app + + +@setup_fresh_app +def test_404_for_non_existent(test_app): + assert_equal(test_app.get('/does-not-exist/', + expect_errors=True).status_int, + 404) diff --git a/mediagoblin/tests/test_storage.py b/mediagoblin/tests/test_storage.py index 46ecb2ec..eab4d032 100644 --- a/mediagoblin/tests/test_storage.py +++ b/mediagoblin/tests/test_storage.py @@ -57,6 +57,10 @@ class FakeRemoteStorage(storage.filestorage.BasicFileStorage): # should force copying to the workbench local_storage = False + def copy_local_to_storage(self, *args, **kwargs): + return storage.StorageInterface.copy_local_to_storage( + self, *args, **kwargs) + def test_storage_system_from_config(): this_storage = storage.storage_system_from_config( @@ -252,3 +256,26 @@ def test_basic_storage_copy_locally(): this_storage.copy_locally(filepath, new_file_dest) assert file(new_file_dest).read() == 'Testing this file' + + +def _test_copy_local_to_storage_works(tmpdir, this_storage): + local_filename = tempfile.mktemp() + with file(local_filename, 'w') as tmpfile: + tmpfile.write('haha') + + this_storage.copy_local_to_storage( + local_filename, ['dir1', 'dir2', 'copiedto.txt']) + + assert file( + os.path.join(tmpdir, 'dir1/dir2/copiedto.txt'), + 'r').read() == 'haha' + + +def test_basic_storage_copy_local_to_storage(): + tmpdir, this_storage = get_tmp_filestorage() + _test_copy_local_to_storage_works(tmpdir, this_storage) + + +def test_general_storage_copy_local_to_storage(): + tmpdir, this_storage = get_tmp_filestorage(fake_remote=True) + _test_copy_local_to_storage_works(tmpdir, this_storage) diff --git a/mediagoblin/tests/test_submission.py b/mediagoblin/tests/test_submission.py index 1c657e6c..7c372745 100644 --- a/mediagoblin/tests/test_submission.py +++ b/mediagoblin/tests/test_submission.py @@ -19,8 +19,8 @@ import pkg_resources from nose.tools import assert_equal, assert_true, assert_false -from mediagoblin.auth import lib as auth_lib -from mediagoblin.tests.tools import setup_fresh_app, get_test_app +from mediagoblin.tests.tools import setup_fresh_app, get_test_app, \ + fixture_add_user from mediagoblin import mg_globals from mediagoblin.tools import template, common @@ -45,13 +45,7 @@ class TestSubmission: # TODO: Possibly abstract into a decorator like: # @as_authenticated_user('chris') - test_user = mg_globals.database.User() - test_user['username'] = u'chris' - test_user['email'] = u'chris@example.com' - test_user['email_verified'] = True - test_user['status'] = u'active' - test_user['pw_hash'] = auth_lib.bcrypt_gen_password_hash('toast') - test_user.save() + test_user = fixture_add_user() self.test_user = test_user @@ -176,8 +170,8 @@ class TestSubmission: response = self.test_app.post( request.urlgen('mediagoblin.user_pages.media_confirm_delete', # No work: user=media.uploader().username, - user=self.test_user['username'], - media=media['_id']), + user=self.test_user.username, + media=media._id), # no value means no confirm {}) @@ -196,8 +190,8 @@ class TestSubmission: response = self.test_app.post( request.urlgen('mediagoblin.user_pages.media_confirm_delete', # No work: user=media.uploader().username, - user=self.test_user['username'], - media=media['_id']), + user=self.test_user.username, + media=media._id), {'confirm': 'y'}) response.follow() @@ -208,7 +202,7 @@ class TestSubmission: # Does media entry still exist? assert_false( request.db.MediaEntry.find( - {'_id': media['_id']}).count()) + {'_id': media._id}).count()) def test_malicious_uploads(self): # Test non-suppoerted file with non-supported extension @@ -222,7 +216,7 @@ class TestSubmission: context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html'] form = context['submit_form'] - assert form.file.errors == ['The file doesn\'t seem to be an image!'] + assert form.file.errors == [u'Invalid file type.'] # NOTE: The following 2 tests will ultimately fail, but they # *will* pass the initial form submission step. Instead, @@ -246,7 +240,7 @@ class TestSubmission: assert_equal(entry['state'], 'failed') assert_equal( entry['fail_error'], - u'mediagoblin.process_media.errors:BadMediaFail') + u'mediagoblin.processing:BadMediaFail') # Test non-supported file with .png extension # ------------------------------------------- @@ -266,4 +260,4 @@ class TestSubmission: assert_equal(entry['state'], 'failed') assert_equal( entry['fail_error'], - u'mediagoblin.process_media.errors:BadMediaFail') + u'mediagoblin.processing:BadMediaFail') diff --git a/mediagoblin/tests/test_tags.py b/mediagoblin/tests/test_tags.py index a05831c9..583c1a55 100644 --- a/mediagoblin/tests/test_tags.py +++ b/mediagoblin/tests/test_tags.py @@ -39,11 +39,4 @@ def test_list_of_dicts_conversion(test_app): # Make sure converting the list of dicts to a string works assert text.media_tags_as_string([{'name': u'yin', 'slug': u'yin'}, {'name': u'yang', 'slug': u'yang'}]) == \ - u'yin,yang' - - # If the tag delimiter is a space then we expect different results - mg_globals.app_config['tags_delimiter'] = u' ' - assert text.convert_to_tag_list_of_dicts('unicorn ceramic nazi') == [ - {'name': u'unicorn', 'slug': u'unicorn'}, - {'name': u'ceramic', 'slug': u'ceramic'}, - {'name': u'nazi', 'slug': u'nazi'}] + u'yin, yang' diff --git a/mediagoblin/tests/test_tests.py b/mediagoblin/tests/test_tests.py index bc5f9a8d..25bb52b3 100644 --- a/mediagoblin/tests/test_tests.py +++ b/mediagoblin/tests/test_tests.py @@ -27,9 +27,9 @@ def test_get_test_app_wipes_db(): assert mg_globals.database.User.find().count() == 0 new_user = mg_globals.database.User() - new_user['username'] = u'lolcat' - new_user['email'] = u'lol@cats.example.org' - new_user['pw_hash'] = u'pretend_this_is_a_hash' + new_user.username = u'lolcat' + new_user.email = u'lol@cats.example.org' + new_user.pw_hash = u'pretend_this_is_a_hash' new_user.save() assert mg_globals.database.User.find().count() == 1 diff --git a/mediagoblin/tests/tools.py b/mediagoblin/tests/tools.py index 420d9ba8..49a3d33e 100644 --- a/mediagoblin/tests/tools.py +++ b/mediagoblin/tests/tools.py @@ -26,6 +26,8 @@ from mediagoblin.tools import testing from mediagoblin.init.config import read_mediagoblin_config from mediagoblin.decorators import _make_safe from mediagoblin.db.open import setup_connection_and_db_from_config +from mediagoblin.meddleware import BaseMeddleware +from mediagoblin.auth.lib import bcrypt_gen_password_hash MEDIAGOBLIN_TEST_DB_NAME = u'__mediagoblin_tests__' @@ -50,9 +52,9 @@ $ CELERY_CONFIG_MODULE=mediagoblin.init.celery.from_tests ./bin/nosetests""" class BadCeleryEnviron(Exception): pass -class TestingMiddleware(object): +class TestingMeddleware(BaseMeddleware): """ - Middleware for the Unit tests + Meddleware for the Unit tests It might make sense to perform some tests on all requests/responses. Or prepare them in a special @@ -60,7 +62,7 @@ class TestingMiddleware(object): for being valid html *after* being rendered. This module is getting inserted at the front of the - middleware list, which means: requests are handed here + meddleware list, which means: requests are handed here first, responses last. So this wraps up the "normal" app. @@ -69,12 +71,6 @@ class TestingMiddleware(object): create a new method and call it from process_*. """ - def __init__(self, mg_app): - self.app = mg_app - - def process_request(self, request): - pass - def process_response(self, request, response): # All following tests should be for html only! if response.content_type != "text/html": @@ -149,11 +145,11 @@ def get_test_app(dump_old_app=True): test_app = loadapp( 'config:' + TEST_SERVER_CONFIG) - # Insert the TestingMiddleware, which can do some + # Insert the TestingMeddleware, which can do some # sanity checks on every request/response. # Doing it this way is probably not the cleanest way. # We'll fix it, when we have plugins! - mg_globals.app.middleware.insert(0, TestingMiddleware(mg_globals.app)) + mg_globals.app.meddleware.insert(0, TestingMeddleware(mg_globals.app)) app = TestApp(test_app) MGOBLIN_APP = app @@ -205,3 +201,19 @@ def assert_db_meets_expected(db, expected): document = collection.find_one({'_id': expected_document['_id']}) assert document is not None # make sure it exists assert document == expected_document # make sure it matches + + +def fixture_add_user(username = u'chris', password = 'toast', + active_user = True): + test_user = mg_globals.database.User() + test_user.username = username + test_user.email = username + u'@example.com' + if password is not None: + test_user.pw_hash = bcrypt_gen_password_hash(password) + if active_user: + test_user.email_verified = True + test_user.status = u'active' + + test_user.save() + + return test_user diff --git a/mediagoblin/tools/common.py b/mediagoblin/tools/common.py index ea4541a8..12d8309e 100644 --- a/mediagoblin/tools/common.py +++ b/mediagoblin/tools/common.py @@ -21,6 +21,7 @@ DISPLAY_IMAGE_FETCHING_ORDER = [u'medium', u'original', u'thumb'] global TESTS_ENABLED TESTS_ENABLED = False + def import_component(import_string): """ Import a module component defined by STRING. Probably a method, diff --git a/mediagoblin/tools/mail.py b/mediagoblin/tools/mail.py index 826acdbf..9e00be7d 100644 --- a/mediagoblin/tools/mail.py +++ b/mediagoblin/tools/mail.py @@ -24,7 +24,7 @@ from mediagoblin.tools import common ### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # We have two "test inboxes" here: -# +# # EMAIL_TEST_INBOX: # ---------------- # If you're writing test views, you'll probably want to check this. @@ -44,11 +44,12 @@ from mediagoblin.tools import common # ***IMPORTANT!*** # ---------------- # Before running tests that call functions which send email, you should -# always call _clear_test_inboxes() to "wipe" the inboxes clean. +# always call _clear_test_inboxes() to "wipe" the inboxes clean. EMAIL_TEST_INBOX = [] EMAIL_TEST_MBOX_INBOX = [] + class FakeMhost(object): """ Just a fake mail host so we can capture and test messages @@ -63,12 +64,14 @@ class FakeMhost(object): 'to': to_addrs, 'message': message}) + def _clear_test_inboxes(): global EMAIL_TEST_INBOX global EMAIL_TEST_MBOX_INBOX EMAIL_TEST_INBOX = [] EMAIL_TEST_MBOX_INBOX = [] + ### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ### </Special email test stuff> ### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/mediagoblin/tools/pagination.py b/mediagoblin/tools/pagination.py index 3ea96e6d..5ebc3c5a 100644 --- a/mediagoblin/tools/pagination.py +++ b/mediagoblin/tools/pagination.py @@ -19,8 +19,10 @@ import copy from math import ceil, floor from itertools import izip, count + PAGINATION_DEFAULT_PER_PAGE = 30 + class Pagination(object): """ Pagination class for mongodb queries. @@ -37,9 +39,9 @@ class Pagination(object): Args: - page: requested page - per_page: number of objects per page - - cursor: db cursor - - jump_to_id: ObjectId, sets the page to the page containing the object - with _id == jump_to_id. + - cursor: db cursor + - jump_to_id: ObjectId, sets the page to the page containing the + object with _id == jump_to_id. """ self.page = page self.per_page = per_page @@ -51,7 +53,7 @@ class Pagination(object): cursor = copy.copy(self.cursor) for (doc, increment) in izip(cursor, count(0)): - if doc['_id'] == jump_to_id: + if doc._id == jump_to_id: self.page = 1 + int(floor(increment / self.per_page)) self.active_id = jump_to_id @@ -91,19 +93,19 @@ class Pagination(object): last = num def get_page_url_explicit(self, base_url, get_params, page_no): - """ + """ Get a page url by adding a page= parameter to the base url - """ + """ new_get_params = copy.copy(get_params or {}) new_get_params['page'] = page_no return "%s?%s" % ( base_url, urllib.urlencode(new_get_params)) def get_page_url(self, request, page_no): - """ + """ Get a new page url based of the request, and the new page number. This is a nice wrapper around get_page_url_explicit() - """ + """ return self.get_page_url_explicit( request.full_path, request.GET, page_no) diff --git a/mediagoblin/tools/response.py b/mediagoblin/tools/response.py index 1477b9bc..c905097c 100644 --- a/mediagoblin/tools/response.py +++ b/mediagoblin/tools/response.py @@ -17,22 +17,25 @@ from webob import Response, exc from mediagoblin.tools.template import render_template + def render_to_response(request, template, context, status=200): """Much like Django's shortcut.render()""" return Response( render_template(request, template, context), status=status) + def render_404(request): """ Render a 404. """ return render_to_response( - request, 'mediagoblin/404.html', {}, status=400) + request, 'mediagoblin/404.html', {}, status=404) + def redirect(request, *args, **kwargs): """Returns a HTTPFound(), takes a request and then urlgen params""" - + querystring = None if kwargs.get('querystring'): querystring = kwargs.get('querystring') diff --git a/mediagoblin/tools/template.py b/mediagoblin/tools/template.py index a773ca99..d0400347 100644 --- a/mediagoblin/tools/template.py +++ b/mediagoblin/tools/template.py @@ -17,18 +17,19 @@ from math import ceil import jinja2 from babel.localedata import exists -from babel.support import LazyProxy from mediagoblin import mg_globals from mediagoblin import messages from mediagoblin.tools import common from mediagoblin.tools.translate import setup_gettext -from mediagoblin.middleware.csrf import render_csrf_form_token +from mediagoblin.meddleware.csrf import render_csrf_form_token + SETUP_JINJA_ENVS = {} + def get_jinja_env(template_loader, locale): """ - Set up the Jinja environment, + Set up the Jinja environment, (In the future we may have another system for providing theming; for now this is good enough.) @@ -51,15 +52,19 @@ def get_jinja_env(template_loader, locale): # All templates will know how to ... # ... fetch all waiting messages and remove them from the queue # ... construct a grid of thumbnails or other media + # ... have access to the global and app config template_env.globals['fetch_messages'] = messages.fetch_messages template_env.globals['gridify_list'] = gridify_list template_env.globals['gridify_cursor'] = gridify_cursor + template_env.globals['app_config'] = mg_globals.app_config + template_env.globals['global_config'] = mg_globals.global_config if exists(locale): SETUP_JINJA_ENVS[locale] = template_env return template_env + # We'll store context information here when doing unit tests TEMPLATE_TEST_CONTEXT = {} @@ -74,10 +79,12 @@ def render_template(request, template_path, context): template = request.template_env.get_template( template_path) context['request'] = request - context['csrf_token'] = render_csrf_form_token(request) + rendered_csrf_token = render_csrf_form_token(request) + if rendered_csrf_token is not None: + context['csrf_token'] = render_csrf_form_token(request) rendered = template.render(context) - - if common.TESTS_ENABLED: + + if common.TESTS_ENABLED: TEMPLATE_TEST_CONTEXT[template_path] = context return rendered @@ -87,6 +94,7 @@ def clear_test_template_context(): global TEMPLATE_TEST_CONTEXT TEMPLATE_TEST_CONTEXT = {} + def gridify_list(this_list, num_cols=5): """ Generates a list of lists where each sub-list's length depends on diff --git a/mediagoblin/tools/text.py b/mediagoblin/tools/text.py index de4bb281..d576224d 100644 --- a/mediagoblin/tools/text.py +++ b/mediagoblin/tools/text.py @@ -21,6 +21,7 @@ from lxml.html.clean import Cleaner from mediagoblin import mg_globals from mediagoblin.tools import url + # A super strict version of the lxml.html cleaner class HTML_CLEANER = Cleaner( scripts=True, @@ -42,6 +43,8 @@ HTML_CLEANER = Cleaner( host_whitelist=(), whitelist_tags=set([])) +TAGS_DELIMITER=','; + def clean_html(html): # clean_html barfs on an empty string if not html: @@ -49,6 +52,7 @@ def clean_html(html): return HTML_CLEANER.clean_html(html) + def convert_to_tag_list_of_dicts(tag_string): """ Filter input from incoming string containing user tags, @@ -64,7 +68,7 @@ def convert_to_tag_list_of_dicts(tag_string): # Split the tag string into a list of tags for tag in stripped_tag_string.split( - mg_globals.app_config['tags_delimiter']): + TAGS_DELIMITER): # Ignore empty or duplicate tags if tag.strip() and tag.strip() not in [t['name'] for t in taglist]: @@ -73,6 +77,7 @@ def convert_to_tag_list_of_dicts(tag_string): 'slug': url.slugify(tag.strip())}) return taglist + def media_tags_as_string(media_entry_tags): """ Generate a string from a media item's tags, stored as a list of dicts @@ -81,13 +86,15 @@ def media_tags_as_string(media_entry_tags): """ media_tag_string = '' if media_entry_tags: - media_tag_string = mg_globals.app_config['tags_delimiter'].join( + media_tag_string = (TAGS_DELIMITER+u' ').join( [tag['name'] for tag in media_entry_tags]) return media_tag_string + TOO_LONG_TAG_WARNING = \ u'Tags must be shorter than %s characters. Tags that are too long: %s' + def tag_length_validator(form, field): """ Make sure tags do not exceed the maximum tag length. @@ -105,6 +112,7 @@ def tag_length_validator(form, field): MARKDOWN_INSTANCE = markdown.Markdown(safe_mode='escape') + def cleaned_markdown_conversion(text): """ Take a block of text, run it through MarkDown, and clean its HTML. diff --git a/mediagoblin/tools/url.py b/mediagoblin/tools/url.py index 458ef2c8..78b5dd63 100644 --- a/mediagoblin/tools/url.py +++ b/mediagoblin/tools/url.py @@ -17,8 +17,10 @@ import re import translitcodec + _punct_re = re.compile(r'[\t !"#$%&\'()*\-/<=>?@\[\\\]^_`{|},.]+') + def slugify(text, delim=u'-'): """ Generates an ASCII-only slug. Taken from http://flask.pocoo.org/snippets/5/ diff --git a/mediagoblin/user_pages/__init__.py b/mediagoblin/user_pages/__init__.py index 576bd0f5..ba347c69 100644 --- a/mediagoblin/user_pages/__init__.py +++ b/mediagoblin/user_pages/__init__.py @@ -13,5 +13,3 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. - - diff --git a/mediagoblin/user_pages/forms.py b/mediagoblin/user_pages/forms.py index 301f1f0a..e04fd559 100644 --- a/mediagoblin/user_pages/forms.py +++ b/mediagoblin/user_pages/forms.py @@ -21,7 +21,7 @@ from mediagoblin.tools.translate import fake_ugettext_passthrough as _ class MediaCommentForm(wtforms.Form): comment_content = wtforms.TextAreaField( - _('Comment'), + _(''), [wtforms.validators.Required()]) diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py index 484c1e28..87b82c74 100644 --- a/mediagoblin/user_pages/views.py +++ b/mediagoblin/user_pages/views.py @@ -30,6 +30,8 @@ from mediagoblin.decorators import (uses_pagination, get_user_media_entry, from werkzeug.contrib.atom import AtomFeed +from mediagoblin.media_types import get_media_manager + @uses_pagination def user_home(request, page): @@ -38,14 +40,14 @@ def user_home(request, page): 'username': request.matchdict['user']}) if not user: return render_404(request) - elif user['status'] != u'active': + elif user.status != u'active': return render_to_response( request, 'mediagoblin/user_pages/user.html', {'user': user}) cursor = request.db.MediaEntry.find( - {'uploader': user['_id'], + {'uploader': user._id, 'state': 'processed'}).sort('created', DESCENDING) pagination = Pagination(page, cursor) @@ -54,10 +56,10 @@ def user_home(request, page): #if no data is available, return NotFound if media_entries == None: return render_404(request) - + user_gallery_url = request.urlgen( 'mediagoblin.user_pages.user_gallery', - user=user['username']) + user=user.username) return render_to_response( request, @@ -67,6 +69,7 @@ def user_home(request, page): 'media_entries': media_entries, 'pagination': pagination}) + @uses_pagination def user_gallery(request, page): """'Gallery' of a User()""" @@ -77,7 +80,7 @@ def user_gallery(request, page): return render_404(request) cursor = request.db.MediaEntry.find( - {'uploader': user['_id'], + {'uploader': user._id, 'state': 'processed'}).sort('created', DESCENDING) pagination = Pagination(page, cursor) @@ -86,7 +89,7 @@ def user_gallery(request, page): #if no data is available, return NotFound if media_entries == None: return render_404(request) - + return render_to_response( request, 'mediagoblin/user_pages/gallery.html', @@ -96,6 +99,7 @@ def user_gallery(request, page): MEDIA_COMMENTS_PER_PAGE = 50 + @get_user_media_entry @uses_pagination def media_home(request, media, page, **kwargs): @@ -104,19 +108,25 @@ def media_home(request, media, page, **kwargs): """ if ObjectId(request.matchdict.get('comment')): pagination = Pagination( - page, media.get_comments(), MEDIA_COMMENTS_PER_PAGE, + page, media.get_comments( + mg_globals.app_config['comments_ascending']), + MEDIA_COMMENTS_PER_PAGE, ObjectId(request.matchdict.get('comment'))) else: pagination = Pagination( - page, media.get_comments(), MEDIA_COMMENTS_PER_PAGE) + page, media.get_comments( + mg_globals.app_config['comments_ascending']), + MEDIA_COMMENTS_PER_PAGE) comments = pagination() comment_form = user_forms.MediaCommentForm(request.POST) + media_template_name = get_media_manager(media.media_type)['display_template'] + return render_to_response( request, - 'mediagoblin/user_pages/media.html', + media_template_name, {'media': media, 'comments': comments, 'pagination': pagination, @@ -133,8 +143,8 @@ def media_post_comment(request, media): assert request.method == 'POST' comment = request.db.MediaComment() - comment['media_entry'] = media['_id'] - comment['author'] = request.user['_id'] + comment['media_entry'] = media._id + comment['author'] = request.user._id comment['content'] = unicode(request.POST['comment_content']) comment['content_html'] = cleaned_markdown_conversion(comment['content']) @@ -142,13 +152,13 @@ def media_post_comment(request, media): messages.add_message( request, messages.ERROR, - _("Empty comments are not allowed.")) + _("Oops, your comment was empty.")) else: comment.save() messages.add_message( request, messages.SUCCESS, - _('Comment posted!')) + _('Your comment has been posted!')) return exc.HTTPFound( location=media.url_for_self(request.urlgen)) @@ -163,21 +173,26 @@ def media_confirm_delete(request, media): if request.method == 'POST' and form.validate(): if form.confirm.data is True: - username = media.uploader()['username'] + username = media.get_uploader().username # Delete all files on the public storage delete_media_files(media) media.delete() + messages.add_message( + request, messages.SUCCESS, _('You deleted the media.')) return redirect(request, "mediagoblin.user_pages.user_home", user=username) else: + messages.add_message( + request, messages.ERROR, + _("The media was not deleted because you didn't check that you were sure.")) return exc.HTTPFound( location=media.url_for_self(request.urlgen)) - if ((request.user[u'is_admin'] and - request.user[u'_id'] != media.uploader()[u'_id'])): + if ((request.user.is_admin and + request.user._id != media.get_uploader()._id)): messages.add_message( request, messages.WARNING, _("You are about to delete another user's media. " @@ -192,6 +207,7 @@ def media_confirm_delete(request, media): ATOM_DEFAULT_NR_OF_UPDATED_ITEMS = 15 + def atom_feed(request): """ generates the atom feed with the newest images @@ -204,7 +220,7 @@ def atom_feed(request): return render_404(request) cursor = request.db.MediaEntry.find({ - 'uploader': user['_id'], + 'uploader': user._id, 'state': 'processed'}) \ .sort('created', DESCENDING) \ .limit(ATOM_DEFAULT_NR_OF_UPDATED_ITEMS) @@ -212,7 +228,7 @@ def atom_feed(request): feed = AtomFeed(request.matchdict['user'], feed_url=request.url, url=request.host_url) - + for entry in cursor: feed.add(entry.get('title'), entry.get('description_html'), @@ -238,7 +254,7 @@ def processing_panel(request): # Make sure the user exists and is active if not user: return render_404(request) - elif user['status'] != u'active': + elif user.status != u'active': return render_to_response( request, 'mediagoblin/user_pages/user.html', @@ -248,7 +264,7 @@ def processing_panel(request): # # Make sure we have permission to access this user's panel. Only # admins and this user herself should be able to do so. - if not (user[u'_id'] == request.user[u'_id'] + if not (user._id == request.user._id or request.user.is_admin): # No? Let's simply redirect to this user's homepage then. return redirect( @@ -257,12 +273,12 @@ def processing_panel(request): # Get media entries which are in-processing processing_entries = request.db.MediaEntry.find( - {'uploader': user['_id'], + {'uploader': user._id, 'state': 'processing'}).sort('created', DESCENDING) # Get media entries which have failed to process failed_entries = request.db.MediaEntry.find( - {'uploader': user['_id'], + {'uploader': user._id, 'state': 'failed'}).sort('created', DESCENDING) # Render to response diff --git a/mediagoblin/views.py b/mediagoblin/views.py index 22f9268d..1e1db6c3 100644 --- a/mediagoblin/views.py +++ b/mediagoblin/views.py @@ -20,6 +20,8 @@ from mediagoblin.tools.response import render_to_response from mediagoblin.db.util import DESCENDING from mediagoblin.decorators import uses_pagination + + @uses_pagination def root_view(request, page): cursor = request.db.MediaEntry.find( @@ -27,7 +29,6 @@ def root_view(request, page): pagination = Pagination(page, cursor) media_entries = pagination() - return render_to_response( request, 'mediagoblin/root.html', {'media_entries': media_entries, diff --git a/mediagoblin/workbench.py b/mediagoblin/workbench.py index 722f8e27..9578494c 100644 --- a/mediagoblin/workbench.py +++ b/mediagoblin/workbench.py @@ -42,10 +42,15 @@ class Workbench(object): def __unicode__(self): return unicode(self.dir) + def __str__(self): return str(self.dir) + def __repr__(self): - return repr(self.dir) + try: + return str(self) + except AttributeError: + return 'None' def joinpath(self, *args): return os.path.join(self.dir, *args) @@ -140,7 +145,7 @@ class WorkbenchManager(object): self.base_workbench_dir = os.path.abspath(base_workbench_dir) if not os.path.exists(self.base_workbench_dir): os.makedirs(self.base_workbench_dir) - + def create_workbench(self): """ Create and return the path to a new workbench (directory). diff --git a/runtests.sh b/runtests.sh index 1dfbf093..4265326c 100755 --- a/runtests.sh +++ b/runtests.sh @@ -23,7 +23,8 @@ elif which nosetests > /dev/null; then echo "Using nosetests from \$PATH"; export NOSETESTS="nosetests"; else - echo "No nosetests found, exiting! X_X"; + echo "nosetests not found. X_X"; + echo "Please install 'nose'. Exiting."; exit 1 fi @@ -29,16 +29,17 @@ def get_version(): if mo: return mo.group(1) else: - raise RuntimeError("Unable to find version string in %s." % VERSIONFILE) + raise RuntimeError("Unable to find version string in %s." % + VERSIONFILE) setup( - name = "mediagoblin", - version = get_version(), + name="mediagoblin", + version=get_version(), packages=find_packages(exclude=['ez_setup', 'examples', 'tests']), zip_safe=False, # scripts and dependencies - install_requires = [ + install_requires=[ 'setuptools', 'PasteScript', 'beaker', @@ -60,13 +61,13 @@ setup( 'webtest', 'ConfigObj', 'Markdown', - 'python-cloudfiles', ## For now we're expecting that users will install this from ## their package managers. # 'lxml', ], + # requires=['gst'], test_suite='nose.collector', - entry_points = """\ + entry_points="""\ [console_scripts] gmg = mediagoblin.gmg_commands:main_cli pybabel = mediagoblin.babel.messages.frontend:main @@ -83,7 +84,6 @@ setup( [babel.extractors] jinja2 = jinja2.ext:babel_extract """, - license='AGPLv3', author='Free Software Foundation and contributors', author_email='cwebber@gnu.org', |