diff options
109 files changed, 1974 insertions, 1349 deletions
@@ -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 b944a3d3..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/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/_version.py b/mediagoblin/_version.py index d6c6e20d..5e3f4e5a 100644 --- a/mediagoblin/_version.py +++ b/mediagoblin/_version.py @@ -14,4 +14,4 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -__version__ = "0.1.0" +__version__ = "0.3.0-dev" diff --git a/mediagoblin/app.py b/mediagoblin/app.py index 7f087ed9..04eb2acc 100644 --- a/mediagoblin/app.py +++ b/mediagoblin/app.py @@ -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() diff --git a/mediagoblin/auth/forms.py b/mediagoblin/auth/forms.py index dcb6766c..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(), diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py index cf4a2b83..c0af3b5b 100644 --- a/mediagoblin/auth/lib.py +++ b/mediagoblin/auth/lib.py @@ -105,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'])}) + 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 @@ -140,16 +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'])}) + 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/views.py b/mediagoblin/auth/views.py index d01861d1..919aa3cd 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -80,9 +80,9 @@ def register(request): 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) @@ -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, @@ -166,10 +166,10 @@ def verify_email(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): @@ -212,7 +212,7 @@ def resend_activation(request): return redirect(request, "mediagoblin.user_pages.user_home", user=request.user['username']) - request.user[u'verification_key'] = unicode(uuid.uuid4()) + request.user.verification_key = unicode(uuid.uuid4()) request.user.save() email_debug_message(request) @@ -224,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): @@ -249,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() @@ -268,7 +268,7 @@ 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 return redirect(request, 'mediagoblin.auth.fp_email_sent') @@ -301,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') diff --git a/mediagoblin/config_spec.ini b/mediagoblin/config_spec.ini index c057f432..eb22bc1b 100644 --- a/mediagoblin/config_spec.ini +++ b/mediagoblin/config_spec.ini @@ -28,7 +28,6 @@ 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 @@ -62,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/models.py b/mediagoblin/db/models.py index 265fe36d..569c3600 100644 --- a/mediagoblin/db/models.py +++ b/mediagoblin/db/models.py @@ -96,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): @@ -131,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} @@ -139,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. @@ -249,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): """ @@ -268,12 +268,12 @@ class MediaEntry(Document): 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'], + user=uploader.username, media=unicode(self._id)) def url_to_prev(self, urlgen): @@ -281,30 +281,30 @@ class MediaEntry(Document): 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'], + 'uploader': self.uploader, 'state': 'processed'}).sort( '_id', ASCENDING).limit(1) if cursor.count(): return urlgen('mediagoblin.user_pages.media_home', - user=self.get_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'], + 'uploader': self.uploader, 'state': 'processed'}).sort( '_id', DESCENDING).limit(1) if cursor.count(): return urlgen('mediagoblin.user_pages.media_home', - user=self.get_uploader()['username'], - media=unicode(cursor[0]['slug'])) + user=self.get_uploader().username, + media=unicode(cursor[0].slug)) def get_uploader(self): - return self.db.User.find_one({'_id': self['uploader']}) + return self.db.User.find_one({'_id': self.uploader}) def get_fail_exception(self): """ diff --git a/mediagoblin/decorators.py b/mediagoblin/decorators.py index 1cdce23a..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" % ( @@ -59,7 +59,7 @@ def user_may_delete_media(controller): def wrapper(request, *args, **kwargs): uploader = request.db.MediaEntry.find_one( {'_id': ObjectId(request.matchdict['media'])}).get_uploader() - if not (request.user['is_admin'] or + if not (request.user.is_admin or request.user._id == uploader._id): return exc.HTTPForbidden() @@ -95,7 +95,6 @@ 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', diff --git a/mediagoblin/edit/lib.py b/mediagoblin/edit/lib.py index 458b704e..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 673409bd..4cb98c15 100644 --- a/mediagoblin/edit/views.py +++ b/mediagoblin/edit/views.py @@ -43,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( @@ -57,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'], + '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, @@ -147,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': @@ -176,14 +176,14 @@ def edit_profile(request): {'user': user, 'form': form}) - user['url'] = unicode(request.POST['url']) - user['bio'] = unicode(request.POST['bio']) + user.url = unicode(request.POST['url']) + user.bio = unicode(request.POST['bio']) if password_matches: user['pw_hash'] = auth_lib.bcrypt_gen_password_hash( request.POST['new_password']) - user['bio_html'] = cleaned_markdown_conversion(user['bio']) + user.bio_html = cleaned_markdown_conversion(user['bio']) user.save() diff --git a/mediagoblin/gmg_commands/import_export.py b/mediagoblin/gmg_commands/import_export.py index 4ec17d47..1308f09e 100644 --- a/mediagoblin/gmg_commands/import_export.py +++ b/mediagoblin/gmg_commands/import_export.py @@ -67,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') @@ -209,7 +209,7 @@ def _export_media(db, args): for entry in db.media_entries.find(): for name, path in entry['media_files'].items(): _log.info(u'Exporting {0} - {1}'.format( - entry['title'], + entry.title, name)) try: mc_file = media_cache.get_file(path, mode='wb') diff --git a/mediagoblin/gmg_commands/users.py b/mediagoblin/gmg_commands/users.py index 4c4b0c1b..4bfe30a5 100644 --- a/mediagoblin/gmg_commands/users.py +++ b/mediagoblin/gmg_commands/users.py @@ -18,23 +18,26 @@ 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({ @@ -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)" @@ -70,7 +73,7 @@ def makeadmin(args): 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: @@ -93,7 +96,7 @@ def changepw(args): 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: 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 40e8b1cd..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-27 15:25-0600\n" -"PO-Revision-Date: 2011-11-27 21:28+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" @@ -102,7 +102,7 @@ msgid "Tags" msgstr "الوسوم" #: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 -msgid "Seperate tags by commas or spaces." +msgid "Seperate tags by commas." msgstr "" #: mediagoblin/edit/forms.py:33 @@ -156,7 +156,7 @@ msgstr "" msgid "Profile edited!" msgstr "" -#: mediagoblin/media_types/__init__.py:61 +#: mediagoblin/media_types/__init__.py:65 msgid "Could not find any file extension in \"{filename}\"" msgstr "" @@ -236,7 +236,9 @@ msgid "Hi there, welcome to this MediaGoblin site!" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:28 -msgid "Your finest source for all goblin-related media." +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:29 @@ -265,6 +267,11 @@ msgstr "أحدث الوسائط" msgid "Enter your new password" 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 "" @@ -378,10 +385,6 @@ msgstr "" 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" @@ -392,6 +395,31 @@ msgstr "" 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/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 msgid "Really delete %(title)s?" @@ -517,6 +545,10 @@ 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 "" @@ -534,11 +566,11 @@ msgid "I am sure I want to delete this" msgstr "أنا متأكد من رغبتي بحذف هذا العمل" #: mediagoblin/user_pages/views.py:155 -msgid "Empty comments are not allowed." +msgid "Oops, your comment was empty." msgstr "" #: mediagoblin/user_pages/views.py:161 -msgid "Comment posted!" +msgid "Your comment has been posted!" msgstr "" #: mediagoblin/user_pages/views.py:183 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 f07ab2d6..9609cb34 100644 --- a/mediagoblin/i18n/ca/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/ca/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-27 15:25-0600\n" -"PO-Revision-Date: 2011-11-27 21:28+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" @@ -100,7 +100,7 @@ msgid "Tags" msgstr "Etiquetes" #: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 -msgid "Seperate tags by commas or spaces." +msgid "Seperate tags by commas." msgstr "" #: mediagoblin/edit/forms.py:33 @@ -152,7 +152,7 @@ msgstr "" msgid "Profile edited!" msgstr "" -#: mediagoblin/media_types/__init__.py:61 +#: mediagoblin/media_types/__init__.py:65 msgid "Could not find any file extension in \"{filename}\"" msgstr "" @@ -233,7 +233,9 @@ msgid "Hi there, welcome to this MediaGoblin site!" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:28 -msgid "Your finest source for all goblin-related media." +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:29 @@ -262,6 +264,11 @@ msgstr "" msgid "Enter your new password" msgstr "" +#: 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 "" @@ -368,10 +375,6 @@ msgstr "" 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" @@ -382,6 +385,31 @@ msgstr "" 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/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 msgid "Really delete %(title)s?" @@ -509,6 +537,10 @@ 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 "" @@ -526,11 +558,11 @@ msgid "I am sure I want to delete this" msgstr "" #: mediagoblin/user_pages/views.py:155 -msgid "Empty comments are not allowed." +msgid "Oops, your comment was empty." msgstr "" #: mediagoblin/user_pages/views.py:161 -msgid "Comment posted!" +msgid "Your comment has been posted!" msgstr "" #: mediagoblin/user_pages/views.py:183 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 f5907eda..e2765357 100644 --- a/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/de/LC_MESSAGES/mediagoblin.po @@ -16,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-27 15:25-0600\n" -"PO-Revision-Date: 2011-11-27 21:28+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 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" @@ -65,7 +65,7 @@ msgstr "Leider gibt es bereits einen Benutzer mit diesem Namen." #: mediagoblin/auth/views.py:77 msgid "Sorry, a user with that email address already exists." -msgstr "" +msgstr "Leider gibt es bereits einen Benutzer mit dieser E-Mail-Adresse." #: mediagoblin/auth/views.py:179 msgid "" @@ -85,7 +85,7 @@ msgstr "" #: mediagoblin/auth/views.py:211 msgid "You've already verified your email address!" -msgstr "" +msgstr "Deine E-Mail-Adresse wurde bereits bestätigt." #: mediagoblin/auth/views.py:224 msgid "Resent your verification email." @@ -109,7 +109,7 @@ msgid "Tags" msgstr "Markierungen" #: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 -msgid "Seperate tags by commas or spaces." +msgid "Seperate tags by commas." msgstr "" #: mediagoblin/edit/forms.py:33 @@ -137,11 +137,11 @@ msgstr "Webseite" #: mediagoblin/edit/forms.py:49 msgid "Old password" -msgstr "" +msgstr "Altes Passwort" #: mediagoblin/edit/forms.py:52 msgid "New Password" -msgstr "" +msgstr "Neues Passwort" #: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." @@ -157,13 +157,13 @@ msgstr "Du bearbeitest das Profil eines Anderen. Bitte sei vorsichtig." #: mediagoblin/edit/views.py:171 msgid "Wrong password" -msgstr "" +msgstr "Falsches Passwort" #: mediagoblin/edit/views.py:192 msgid "Profile edited!" -msgstr "" +msgstr "Das Profil wurde aktualisiert" -#: mediagoblin/media_types/__init__.py:61 +#: mediagoblin/media_types/__init__.py:65 msgid "Could not find any file extension in \"{filename}\"" msgstr "" @@ -185,7 +185,7 @@ msgstr "Yeeeaaah! Geschafft!" #: mediagoblin/submit/views.py:133 msgid "Invalid file type." -msgstr "" +msgstr "Ungültiger Dateityp." #: mediagoblin/templates/mediagoblin/404.html:21 msgid "Oops!" @@ -217,11 +217,11 @@ msgstr "Medien hochladen" #: mediagoblin/templates/mediagoblin/base.html:65 msgid "Verify your email!" -msgstr "" +msgstr "Bitte bestätige deine E-Mail-Adresse!" #: mediagoblin/templates/mediagoblin/base.html:72 msgid "log out" -msgstr "" +msgstr "Abmelden" #: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 @@ -246,7 +246,9 @@ msgid "Hi there, welcome to this MediaGoblin site!" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:28 -msgid "Your finest source for all goblin-related media." +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:29 @@ -275,9 +277,14 @@ msgstr "Neuste Medien" msgid "Enter your new password" msgstr "Neues Passwort 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 "" +msgstr "Passwort wiederherstellen" #: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 msgid "Send instructions" @@ -379,7 +386,7 @@ msgstr "%(username)ss Profil bearbeiten" #: mediagoblin/templates/mediagoblin/listings/tag.html:35 #, python-format msgid "Media tagged with: %(tag_name)s" -msgstr "" +msgstr ": %(tag_name)s" #: mediagoblin/templates/mediagoblin/media_displays/video.html:19 msgid "Original" @@ -389,20 +396,41 @@ msgstr "" 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 "" +msgstr "%(username)ss Medien" #: 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/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 msgid "Really delete %(title)s?" @@ -535,13 +563,17 @@ 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 "" +msgstr "Markiert mit" #: mediagoblin/templates/mediagoblin/utils/tags.html:25 msgid "and" -msgstr "" +msgstr "und" #: mediagoblin/user_pages/forms.py:24 msgid "Comment" @@ -552,12 +584,12 @@ msgid "I am sure I want to delete this" msgstr "Ja, wirklich löschen" #: mediagoblin/user_pages/views.py:155 -msgid "Empty comments are not allowed." -msgstr "Leere Kommentare sind nicht erlaubt." +msgid "Oops, your comment was empty." +msgstr "" #: mediagoblin/user_pages/views.py:161 -msgid "Comment posted!" -msgstr "Kommentar hinzugefügt!" +msgid "Your comment has been posted!" +msgstr "" #: mediagoblin/user_pages/views.py:183 msgid "You deleted the media." diff --git a/mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po b/mediagoblin/i18n/en/LC_MESSAGES/mediagoblin.po index c1f3fd7f..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-27 15:25-0600\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" @@ -94,7 +94,7 @@ msgid "Tags" msgstr "" #: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 -msgid "Seperate tags by commas or spaces." +msgid "Seperate tags by commas." msgstr "" #: mediagoblin/edit/forms.py:33 @@ -145,7 +145,7 @@ msgstr "" msgid "Profile edited!" msgstr "" -#: mediagoblin/media_types/__init__.py:61 +#: mediagoblin/media_types/__init__.py:65 msgid "Could not find any file extension in \"{filename}\"" msgstr "" @@ -224,7 +224,9 @@ msgid "Hi there, welcome to this MediaGoblin site!" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:28 -msgid "Your finest source for all goblin-related media." +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:29 @@ -256,6 +258,11 @@ msgstr "" msgid "Enter your new password" 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 "" @@ -355,10 +362,6 @@ msgstr "" 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" @@ -369,6 +372,31 @@ msgstr "" msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" 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 msgid "Really delete %(title)s?" @@ -490,6 +518,10 @@ 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 "" @@ -507,11 +539,11 @@ msgid "I am sure I want to delete this" msgstr "" #: mediagoblin/user_pages/views.py:155 -msgid "Empty comments are not allowed." +msgid "Oops, your comment was empty." msgstr "" #: mediagoblin/user_pages/views.py:161 -msgid "Comment posted!" +msgid "Your comment has been posted!" msgstr "" #: mediagoblin/user_pages/views.py:183 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 2cffe874..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-27 15:25-0600\n" -"PO-Revision-Date: 2011-11-27 21:28+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" @@ -59,7 +59,7 @@ msgstr "Bedaŭrinde, uzanto kun tiu nomo jam ekzistas." #: mediagoblin/auth/views.py:77 msgid "Sorry, a user with that email address already exists." -msgstr "" +msgstr "Ni bedaŭras, sed konto kun tiu retpoŝtadreso jam ekzistas." #: mediagoblin/auth/views.py:179 msgid "" @@ -75,11 +75,11 @@ msgstr "La kontrol-kodo aŭ la uzantonomo ne estas korekta" #: mediagoblin/auth/views.py:203 msgid "You must be logged in so we know who to send the email to!" -msgstr "" +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 "" +msgstr "Vi jam konfirmis vian retpoŝtadreson!" #: mediagoblin/auth/views.py:224 msgid "Resent your verification email." @@ -102,8 +102,8 @@ msgid "Tags" msgstr "Etikedoj" #: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 -msgid "Seperate tags by commas or spaces." -msgstr "" +msgid "Seperate tags by commas." +msgstr "Dividu la etikedojn per komoj." #: mediagoblin/edit/forms.py:33 msgid "Slug" @@ -130,11 +130,11 @@ msgstr "Retejo" #: mediagoblin/edit/forms.py:49 msgid "Old password" -msgstr "" +msgstr "La malnova pasvorto" #: mediagoblin/edit/forms.py:52 msgid "New Password" -msgstr "" +msgstr "La nova pasvorto" #: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." @@ -150,15 +150,15 @@ msgstr "Vi redaktas profilon de alia uzanto. Agu singardeme." #: mediagoblin/edit/views.py:171 msgid "Wrong password" -msgstr "" +msgstr "Malĝusta pasvorto" #: mediagoblin/edit/views.py:192 msgid "Profile edited!" -msgstr "" +msgstr "La profilŝanĝo faritas!" -#: mediagoblin/media_types/__init__.py:61 +#: mediagoblin/media_types/__init__.py:65 msgid "Could not find any file extension in \"{filename}\"" -msgstr "" +msgstr "Ŝajnas, ke en «{filename}» mankas dosiernoma finaĵo" #: mediagoblin/submit/forms.py:25 msgid "File" @@ -178,7 +178,7 @@ msgstr "Hura! Alŝutitas!" #: mediagoblin/submit/views.py:133 msgid "Invalid file type." -msgstr "" +msgstr "Netaŭga dosiertipo." #: mediagoblin/templates/mediagoblin/404.html:21 msgid "Oops!" @@ -210,11 +210,11 @@ msgstr "Alŝuti aŭd-vid-dosieron" #: mediagoblin/templates/mediagoblin/base.html:65 msgid "Verify your email!" -msgstr "" +msgstr "Konfirmu viecon de la retpoŝtadreso!" #: mediagoblin/templates/mediagoblin/base.html:72 msgid "log out" -msgstr "" +msgstr "elsaluti" #: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 @@ -232,25 +232,32 @@ msgstr "" #: mediagoblin/templates/mediagoblin/root.html:24 msgid "Explore" -msgstr "" +msgstr "Ĉirkaŭrigardi" #: mediagoblin/templates/mediagoblin/root.html:27 msgid "Hi there, welcome to this MediaGoblin site!" -msgstr "" +msgstr "Saluton, kaj bonvenon al ĉi tiu MediaGoblina retpaĝaro!" #: mediagoblin/templates/mediagoblin/root.html:28 -msgid "Your finest source for all goblin-related media." +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." msgstr "" +"Ĉ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:29 msgid "" "To add your own media, place comments, save your favourites and more, you " "can log in with your MediaGoblin account." msgstr "" +"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:31 msgid "Don't have one yet? It's easy!" -msgstr "" +msgstr "Ĉu vi ankoraŭ ne havas tian? Ne malĝoju!" #: mediagoblin/templates/mediagoblin/root.html:32 #, python-format @@ -259,22 +266,30 @@ msgid "" " or\n" " <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\">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: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/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 "" +msgstr "Ekhavo de nova pasvorto" #: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 msgid "Send instructions" -msgstr "" +msgstr "Sendi instrukcion" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 msgid "Your password has been changed. Try to log in now." @@ -372,30 +387,51 @@ msgstr "Redaktado de l’profilo de %(username)s'" #: mediagoblin/templates/mediagoblin/listings/tag.html:35 #, python-format msgid "Media tagged with: %(tag_name)s" -msgstr "" +msgstr "Dosieroj kun etikedo: %(tag_name)s" #: mediagoblin/templates/mediagoblin/media_displays/video.html:19 msgid "Original" -msgstr "" +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 "" +msgstr "Dosieroj de %(username)s" #: 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/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 msgid "Really delete %(title)s?" @@ -527,13 +563,17 @@ 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 "" +msgstr "Markita per: " #: mediagoblin/templates/mediagoblin/utils/tags.html:25 msgid "and" -msgstr "" +msgstr "kaj" #: mediagoblin/user_pages/forms.py:24 msgid "Comment" @@ -544,20 +584,22 @@ msgid "I am sure I want to delete this" msgstr "Mi estas certa, ke mi volas forigi ĉi tion" #: mediagoblin/user_pages/views.py:155 -msgid "Empty comments are not allowed." -msgstr "Malplenaj komentoj ne estas afiŝeblaj." +msgid "Oops, your comment was empty." +msgstr "Oj, via komento estis malplena." #: mediagoblin/user_pages/views.py:161 -msgid "Comment posted!" -msgstr "La komento estas afiŝita!" +msgid "Your comment has been posted!" +msgstr "Via komento estis afiŝita!" #: mediagoblin/user_pages/views.py:183 msgid "You deleted the media." -msgstr "" +msgstr "Vi forigis la dosieron." #: 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:198 msgid "You are about to delete another user's media. Proceed with caution." 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 6ab070af..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-27 15:25-0600\n" -"PO-Revision-Date: 2011-11-27 21:28+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" @@ -64,7 +65,7 @@ msgstr "Lo sentimos, ya existe un usuario con ese nombre." #: mediagoblin/auth/views.py:77 msgid "Sorry, a user with that email address already exists." -msgstr "" +msgstr "Lo sentimos, ya existe un usuario con esa dirección de email." #: mediagoblin/auth/views.py:179 msgid "" @@ -82,10 +83,12 @@ msgstr "" #: 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 "" +msgstr "¡Ya has verificado tu dirección de correo!" #: mediagoblin/auth/views.py:224 msgid "Resent your verification email." @@ -109,8 +112,8 @@ msgid "Tags" msgstr "Etiquetas" #: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 -msgid "Seperate tags by commas or spaces." -msgstr "" +msgid "Seperate tags by commas." +msgstr "Separa las etiquetas con comas." #: mediagoblin/edit/forms.py:33 msgid "Slug" @@ -137,11 +140,11 @@ msgstr "Sitio web" #: mediagoblin/edit/forms.py:49 msgid "Old password" -msgstr "" +msgstr "Vieja contraseña" #: mediagoblin/edit/forms.py:52 msgid "New Password" -msgstr "" +msgstr "Nueva contraseña" #: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." @@ -157,15 +160,15 @@ msgstr "Estás editando un perfil de usuario. Proceder con precaución." #: mediagoblin/edit/views.py:171 msgid "Wrong password" -msgstr "" +msgstr "Contraseña incorrecta" #: mediagoblin/edit/views.py:192 msgid "Profile edited!" -msgstr "" +msgstr "¡Perfil editado!" -#: mediagoblin/media_types/__init__.py:61 +#: mediagoblin/media_types/__init__.py:65 msgid "Could not find any file extension in \"{filename}\"" -msgstr "" +msgstr "No se pudo encontrar la extensión del archivo en \"{filename}\"" #: mediagoblin/submit/forms.py:25 msgid "File" @@ -181,15 +184,15 @@ msgstr "Debes proporcionar un archivo." #: mediagoblin/submit/views.py:127 msgid "Woohoo! Submitted!" -msgstr "¡Woohoo! ¡Enviado!" +msgstr "¡Yujú! ¡Enviado!" #: mediagoblin/submit/views.py:133 msgid "Invalid file type." -msgstr "" +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!" @@ -217,11 +220,11 @@ msgstr "Enviar contenido" #: mediagoblin/templates/mediagoblin/base.html:65 msgid "Verify your email!" -msgstr "" +msgstr "¡Verifica tu email!" #: mediagoblin/templates/mediagoblin/base.html:72 msgid "log out" -msgstr "" +msgstr "Cerrar sesión" #: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 @@ -243,21 +246,28 @@ msgstr "Explorar" #: mediagoblin/templates/mediagoblin/root.html:27 msgid "Hi there, welcome to this MediaGoblin site!" -msgstr "" +msgstr "Hola, ¡bienvenido a este sitio de MediaGoblin!" #: mediagoblin/templates/mediagoblin/root.html:28 -msgid "Your finest source for all goblin-related media." +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." msgstr "" +"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:29 msgid "" "To add your own media, place comments, save your favourites and more, you " "can log in with your MediaGoblin account." msgstr "" +"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:31 msgid "Don't have one yet? It's easy!" -msgstr "" +msgstr "¿Aún no tienes una? ¡Es fácil!" #: mediagoblin/templates/mediagoblin/root.html:32 #, python-format @@ -266,6 +276,9 @@ msgid "" " or\n" " <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\">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:44 msgid "Most recent media" @@ -275,13 +288,18 @@ msgstr "El contenido más reciente" msgid "Enter your new password" msgstr "Ingrese su nueva contraseña" +#: 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 "" +msgstr "Recuperar contraseña" #: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 msgid "Send instructions" -msgstr "" +msgstr "Enviar instrucciones" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 msgid "Your password has been changed. Try to log in now." @@ -307,10 +325,13 @@ 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!" @@ -355,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 @@ -376,34 +397,55 @@ msgstr "Editando el perfil de %(username)s" #: mediagoblin/templates/mediagoblin/listings/tag.html:35 #, python-format msgid "Media tagged with: %(tag_name)s" -msgstr "" +msgstr "Contenido etiquetado con: %(tag_name)s" #: mediagoblin/templates/mediagoblin/media_displays/video.html:19 msgid "Original" -msgstr "" +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 "" +msgstr "Contenidos de %(username)s" #: 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/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" @@ -449,7 +491,7 @@ msgstr "Es necesario un correo electrónico de verificación" #: 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:58 msgid "" @@ -532,13 +574,17 @@ 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 "" +msgstr "Etiquetado con" #: mediagoblin/templates/mediagoblin/utils/tags.html:25 msgid "and" -msgstr "" +msgstr "y" #: mediagoblin/user_pages/forms.py:24 msgid "Comment" @@ -549,20 +595,20 @@ msgid "I am sure I want to delete this" msgstr "Estoy seguro de que quiero borrar esto" #: mediagoblin/user_pages/views.py:155 -msgid "Empty comments are not allowed." -msgstr "" +msgid "Oops, your comment was empty." +msgstr "Ups, tu comentario estaba vacío." #: mediagoblin/user_pages/views.py:161 -msgid "Comment posted!" -msgstr "" +msgid "Your comment has been posted!" +msgstr "¡Tu comentario ha sido publicado!" #: mediagoblin/user_pages/views.py:183 msgid "You deleted the media." -msgstr "" +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 "" +msgstr "El contenido no se eliminó porque no marcaste que estabas seguro." #: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." 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 b37f5217..8d1e2711 100644 --- a/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/fr/LC_MESSAGES/mediagoblin.po @@ -13,8 +13,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-27 15:25-0600\n" -"PO-Revision-Date: 2011-11-27 21:28+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" @@ -64,7 +64,7 @@ msgstr "Un utilisateur existe déjà avec ce nom, désolé." #: mediagoblin/auth/views.py:77 msgid "Sorry, a user with that email address already exists." -msgstr "" +msgstr "Désolé, il existe déjà un utilisateur ayant cette adresse e-mail." #: mediagoblin/auth/views.py:179 msgid "" @@ -81,10 +81,11 @@ msgstr "La clé de vérification ou le nom d'utilisateur est incorrect." #: 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 "" +msgstr "Votre adresse e-mail a déjà été vérifiée !" #: mediagoblin/auth/views.py:224 msgid "Resent your verification email." @@ -107,7 +108,7 @@ msgid "Tags" msgstr "Tags" #: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 -msgid "Seperate tags by commas or spaces." +msgid "Seperate tags by commas." msgstr "" #: mediagoblin/edit/forms.py:33 @@ -135,11 +136,11 @@ msgstr "Site web" #: mediagoblin/edit/forms.py:49 msgid "Old password" -msgstr "" +msgstr "Ancien mot de passe." #: mediagoblin/edit/forms.py:52 msgid "New Password" -msgstr "" +msgstr "Nouveau mot de passe" #: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." @@ -159,15 +160,15 @@ msgstr "" #: mediagoblin/edit/views.py:171 msgid "Wrong password" -msgstr "" +msgstr "Mauvais mot de passe" #: mediagoblin/edit/views.py:192 msgid "Profile edited!" -msgstr "" +msgstr "Profile mis à jour !" -#: mediagoblin/media_types/__init__.py:61 +#: mediagoblin/media_types/__init__.py:65 msgid "Could not find any file extension in \"{filename}\"" -msgstr "" +msgstr "Impossible d'extraire une extension de fichier de \"{nomfichier}\"" #: mediagoblin/submit/forms.py:25 msgid "File" @@ -187,11 +188,11 @@ msgstr "Youhou, c'est envoyé !" #: mediagoblin/submit/views.py:133 msgid "Invalid file type." -msgstr "" +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!" @@ -219,11 +220,11 @@ msgstr "Soumettre un média" #: mediagoblin/templates/mediagoblin/base.html:65 msgid "Verify your email!" -msgstr "" +msgstr "Vérifiez votre adresse e-mail !" #: mediagoblin/templates/mediagoblin/base.html:72 msgid "log out" -msgstr "" +msgstr "déconnexion" #: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 @@ -245,10 +246,12 @@ msgstr "Explorer" #: mediagoblin/templates/mediagoblin/root.html:27 msgid "Hi there, welcome to this MediaGoblin site!" -msgstr "" +msgstr "Bonjour, et bienvenu sur ce site MediaGoblin !" #: mediagoblin/templates/mediagoblin/root.html:28 -msgid "Your finest source for all goblin-related media." +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:29 @@ -256,10 +259,12 @@ msgid "" "To add your own media, place comments, save your favourites and more, you " "can log in with your MediaGoblin account." msgstr "" +"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:31 msgid "Don't have one yet? It's easy!" -msgstr "" +msgstr "Vous n'en avez pas ? C'est facile !" #: mediagoblin/templates/mediagoblin/root.html:32 #, python-format @@ -268,6 +273,9 @@ msgid "" " or\n" " <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\">Créez un compte sur ce site</a>\n" +" ou\n" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Déployez MediaGoblin sur votre propre serveur</a>" #: mediagoblin/templates/mediagoblin/root.html:44 msgid "Most recent media" @@ -277,13 +285,18 @@ msgstr "Tout derniers media" msgid "Enter your new password" msgstr "Entrez un nouveau mot de passe" +#: 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 "" +msgstr "Récupérer le mot de passe" #: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 msgid "Send instructions" -msgstr "" +msgstr "Envoyer les instructions" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 msgid "Your password has been changed. Try to log in now." @@ -326,11 +339,11 @@ msgstr "La connexion a échoué!" #: 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:36 msgid "Create one here!" -msgstr "Créez-en un ici!" +msgstr "Créez-en un ici !" #: mediagoblin/templates/mediagoblin/auth/login.html:42 msgid "Forgot your password?" @@ -338,7 +351,7 @@ msgstr "Vous avez oublié votre mot de passe ?" #: 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" @@ -384,30 +397,51 @@ msgstr "Modification du profil de %(username)s" #: mediagoblin/templates/mediagoblin/listings/tag.html:35 #, python-format msgid "Media tagged with: %(tag_name)s" -msgstr "" +msgstr "Médias taggés avec : %(tag_name)s " #: mediagoblin/templates/mediagoblin/media_displays/video.html:19 msgid "Original" -msgstr "" +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 "" +msgstr "Medias de %(username)s" #: 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/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 msgid "Really delete %(title)s?" @@ -542,13 +576,17 @@ 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 "" +msgstr "Taggé avec" #: mediagoblin/templates/mediagoblin/utils/tags.html:25 msgid "and" -msgstr "" +msgstr "et" #: mediagoblin/user_pages/forms.py:24 msgid "Comment" @@ -559,20 +597,22 @@ msgid "I am sure I want to delete this" msgstr "Je suis sûr de vouloir supprimer cela" #: mediagoblin/user_pages/views.py:155 -msgid "Empty comments are not allowed." -msgstr "Les commentaires vides ne sont pas autorisés." +msgid "Oops, your comment was empty." +msgstr "" #: mediagoblin/user_pages/views.py:161 -msgid "Comment posted!" -msgstr "Votre commentaire a été posté !" +msgid "Your comment has been posted!" +msgstr "" #: mediagoblin/user_pages/views.py:183 msgid "You deleted the media." -msgstr "" +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:198 msgid "You are about to delete another user's media. Proceed with caution." 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 a4f1f8d7..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-27 15:25-0600\n" -"PO-Revision-Date: 2011-11-27 21:28+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" @@ -96,7 +96,7 @@ msgid "Tags" msgstr "" #: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 -msgid "Seperate tags by commas or spaces." +msgid "Seperate tags by commas." msgstr "" #: mediagoblin/edit/forms.py:33 @@ -148,7 +148,7 @@ msgstr "" msgid "Profile edited!" msgstr "" -#: mediagoblin/media_types/__init__.py:61 +#: mediagoblin/media_types/__init__.py:65 msgid "Could not find any file extension in \"{filename}\"" msgstr "" @@ -227,7 +227,9 @@ msgid "Hi there, welcome to this MediaGoblin site!" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:28 -msgid "Your finest source for all goblin-related media." +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:29 @@ -256,6 +258,11 @@ msgstr "" msgid "Enter your new password" 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 "" @@ -356,10 +363,6 @@ msgstr "" 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" @@ -370,6 +373,31 @@ msgstr "" msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" 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 msgid "Really delete %(title)s?" @@ -493,6 +521,10 @@ 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 "" @@ -510,11 +542,11 @@ msgid "I am sure I want to delete this" msgstr "" #: mediagoblin/user_pages/views.py:155 -msgid "Empty comments are not allowed." +msgid "Oops, your comment was empty." msgstr "" #: mediagoblin/user_pages/views.py:161 -msgid "Comment posted!" +msgid "Your comment has been posted!" msgstr "" #: mediagoblin/user_pages/views.py:183 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 25700f8f..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-27 15:25-0600\n" -"PO-Revision-Date: 2011-11-27 21:28+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" @@ -98,7 +98,7 @@ msgid "Tags" msgstr "Tags" #: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 -msgid "Seperate tags by commas or spaces." +msgid "Seperate tags by commas." msgstr "" #: mediagoblin/edit/forms.py:33 @@ -152,7 +152,7 @@ msgstr "" msgid "Profile edited!" msgstr "" -#: mediagoblin/media_types/__init__.py:61 +#: mediagoblin/media_types/__init__.py:65 msgid "Could not find any file extension in \"{filename}\"" msgstr "" @@ -235,7 +235,9 @@ msgid "Hi there, welcome to this MediaGoblin site!" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:28 -msgid "Your finest source for all goblin-related media." +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:29 @@ -264,6 +266,11 @@ msgstr "Documenti multimediali più recenti" msgid "Enter your new password" msgstr "Inserisci la tua nuova password" +#: 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 "" @@ -369,10 +376,6 @@ msgstr "" 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" @@ -383,6 +386,31 @@ msgstr "" 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/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 msgid "Really delete %(title)s?" @@ -513,6 +541,10 @@ 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 "" @@ -530,11 +562,11 @@ msgid "I am sure I want to delete this" msgstr "Sono sicuro di volerlo cancellare" #: mediagoblin/user_pages/views.py:155 -msgid "Empty comments are not allowed." +msgid "Oops, your comment was empty." msgstr "" #: mediagoblin/user_pages/views.py:161 -msgid "Comment posted!" +msgid "Your comment has been posted!" msgstr "" #: mediagoblin/user_pages/views.py:183 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 f2989e0e..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-27 15:25-0600\n" -"PO-Revision-Date: 2011-11-27 21:28+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" @@ -96,7 +96,7 @@ msgid "Tags" msgstr "タグ" #: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 -msgid "Seperate tags by commas or spaces." +msgid "Seperate tags by commas." msgstr "" #: mediagoblin/edit/forms.py:33 @@ -148,7 +148,7 @@ msgstr "" msgid "Profile edited!" msgstr "" -#: mediagoblin/media_types/__init__.py:61 +#: mediagoblin/media_types/__init__.py:65 msgid "Could not find any file extension in \"{filename}\"" msgstr "" @@ -227,7 +227,9 @@ msgid "Hi there, welcome to this MediaGoblin site!" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:28 -msgid "Your finest source for all goblin-related media." +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:29 @@ -256,6 +258,11 @@ msgstr "" msgid "Enter your new password" 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 "" @@ -361,10 +368,6 @@ msgstr "" 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" @@ -375,6 +378,31 @@ msgstr "" 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/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 msgid "Really delete %(title)s?" @@ -498,6 +526,10 @@ 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 "" @@ -515,11 +547,11 @@ msgid "I am sure I want to delete this" msgstr "" #: mediagoblin/user_pages/views.py:155 -msgid "Empty comments are not allowed." +msgid "Oops, your comment was empty." msgstr "" #: mediagoblin/user_pages/views.py:161 -msgid "Comment posted!" +msgid "Your comment has been posted!" msgstr "" #: mediagoblin/user_pages/views.py:183 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 84957014..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-27 15:25-0600\n" -"PO-Revision-Date: 2011-11-27 21:28+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" @@ -98,7 +98,7 @@ msgid "Tags" msgstr "Etiket" #: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 -msgid "Seperate tags by commas or spaces." +msgid "Seperate tags by commas." msgstr "" #: mediagoblin/edit/forms.py:33 @@ -153,7 +153,7 @@ msgstr "" msgid "Profile edited!" msgstr "" -#: mediagoblin/media_types/__init__.py:61 +#: mediagoblin/media_types/__init__.py:65 msgid "Could not find any file extension in \"{filename}\"" msgstr "" @@ -232,7 +232,9 @@ msgid "Hi there, welcome to this MediaGoblin site!" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:28 -msgid "Your finest source for all goblin-related media." +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:29 @@ -261,6 +263,11 @@ msgstr "" msgid "Enter your new password" msgstr "" +#: 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 "" @@ -363,10 +370,6 @@ msgstr "" 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" @@ -377,6 +380,31 @@ msgstr "" 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/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 msgid "Really delete %(title)s?" @@ -504,6 +532,10 @@ 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 "" @@ -521,11 +553,11 @@ msgid "I am sure I want to delete this" msgstr "" #: mediagoblin/user_pages/views.py:155 -msgid "Empty comments are not allowed." +msgid "Oops, your comment was empty." msgstr "" #: mediagoblin/user_pages/views.py:161 -msgid "Comment posted!" +msgid "Your comment has been posted!" msgstr "" #: mediagoblin/user_pages/views.py:183 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 21cfdda5..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-27 15:25-0600\n" -"PO-Revision-Date: 2011-11-27 21:28+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" @@ -99,7 +99,7 @@ msgid "Tags" msgstr "Merkelappar" #: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 -msgid "Seperate tags by commas or spaces." +msgid "Seperate tags by commas." msgstr "" #: mediagoblin/edit/forms.py:33 @@ -151,7 +151,7 @@ msgstr "" msgid "Profile edited!" msgstr "" -#: mediagoblin/media_types/__init__.py:61 +#: mediagoblin/media_types/__init__.py:65 msgid "Could not find any file extension in \"{filename}\"" msgstr "" @@ -234,7 +234,9 @@ msgid "Hi there, welcome to this MediaGoblin site!" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:28 -msgid "Your finest source for all goblin-related media." +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:29 @@ -263,6 +265,11 @@ msgstr "Nyaste mediefiler" msgid "Enter your new password" msgstr "Fyll inn passord" +#: 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 "" @@ -377,10 +384,6 @@ msgstr "" 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" @@ -391,6 +394,31 @@ msgstr "" 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/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 msgid "Really delete %(title)s?" @@ -516,6 +544,10 @@ 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 "" @@ -533,12 +565,12 @@ msgid "I am sure I want to delete this" msgstr "Eg er sikker eg vil sletta dette" #: mediagoblin/user_pages/views.py:155 -msgid "Empty comments are not allowed." -msgstr "Du må skriva noko i innspelet." +msgid "Oops, your comment was empty." +msgstr "" #: mediagoblin/user_pages/views.py:161 -msgid "Comment posted!" -msgstr "Innspel lagt til." +msgid "Your comment has been posted!" +msgstr "" #: mediagoblin/user_pages/views.py:183 msgid "You deleted the media." 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 c4f77f8a..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-27 15:25-0600\n" -"PO-Revision-Date: 2011-11-27 21:28+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" @@ -59,7 +59,7 @@ msgstr "Desculpe, um usuário com este nome já existe." #: mediagoblin/auth/views.py:77 msgid "Sorry, a user with that email address already exists." -msgstr "" +msgstr "Desculpe, um usuário com esse email já esta cadastrado" #: mediagoblin/auth/views.py:179 msgid "" @@ -75,11 +75,11 @@ msgstr "A chave de verificação ou nome usuário estão incorretos." #: mediagoblin/auth/views.py:203 msgid "You must be logged in so we know who to send the email to!" -msgstr "" +msgstr " " #: mediagoblin/auth/views.py:211 msgid "You've already verified your email address!" -msgstr "" +msgstr "Você já verifico seu email!" #: mediagoblin/auth/views.py:224 msgid "Resent your verification email." @@ -102,8 +102,8 @@ msgid "Tags" msgstr "Etiquetas" #: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 -msgid "Seperate tags by commas or spaces." -msgstr "" +msgid "Seperate tags by commas." +msgstr "Separar tags por virgulas." #: mediagoblin/edit/forms.py:33 msgid "Slug" @@ -129,11 +129,11 @@ msgstr "Website" #: mediagoblin/edit/forms.py:49 msgid "Old password" -msgstr "" +msgstr "Senha antiga" #: mediagoblin/edit/forms.py:52 msgid "New Password" -msgstr "" +msgstr "Nova Senha" #: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." @@ -149,15 +149,15 @@ msgstr "Você está editando um perfil de usuário. Tenha cuidado." #: mediagoblin/edit/views.py:171 msgid "Wrong password" -msgstr "" +msgstr "Senha errada" #: mediagoblin/edit/views.py:192 msgid "Profile edited!" -msgstr "" +msgstr "Perfil editado!" -#: mediagoblin/media_types/__init__.py:61 +#: mediagoblin/media_types/__init__.py:65 msgid "Could not find any file extension in \"{filename}\"" -msgstr "" +msgstr " " #: mediagoblin/submit/forms.py:25 msgid "File" @@ -177,7 +177,7 @@ msgstr "Eba! Enviado!" #: mediagoblin/submit/views.py:133 msgid "Invalid file type." -msgstr "" +msgstr "Tipo de arquivo inválido." #: mediagoblin/templates/mediagoblin/404.html:21 msgid "Oops!" @@ -209,11 +209,11 @@ msgstr "Enviar mídia" #: mediagoblin/templates/mediagoblin/base.html:65 msgid "Verify your email!" -msgstr "" +msgstr "Verifique seu email!" #: mediagoblin/templates/mediagoblin/base.html:72 msgid "log out" -msgstr "" +msgstr "Sair" #: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 @@ -235,21 +235,23 @@ msgstr "Explorar" #: mediagoblin/templates/mediagoblin/root.html:27 msgid "Hi there, welcome to this MediaGoblin site!" -msgstr "" +msgstr "Olá, bemvindo ao site de MediaGoblin." #: mediagoblin/templates/mediagoblin/root.html:28 -msgid "Your finest source for all goblin-related media." +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:29 msgid "" "To add your own media, place comments, save your favourites and more, you " "can log in with your MediaGoblin account." -msgstr "" +msgstr " " #: mediagoblin/templates/mediagoblin/root.html:31 msgid "Don't have one yet? It's easy!" -msgstr "" +msgstr " " #: mediagoblin/templates/mediagoblin/root.html:32 #, python-format @@ -267,13 +269,18 @@ msgstr "Mídia mais recente" msgid "Enter your new password" msgstr "Digite sua nova senha" +#: 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 "" +msgstr "Recuperar senha" #: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 msgid "Send instructions" -msgstr "" +msgstr "Mandar instruções" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 msgid "Your password has been changed. Try to log in now." @@ -376,16 +383,12 @@ msgstr "" #: mediagoblin/templates/mediagoblin/media_displays/video.html:19 msgid "Original" -msgstr "" +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" @@ -396,6 +399,31 @@ msgstr "" 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/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 msgid "Really delete %(title)s?" @@ -526,13 +554,17 @@ 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 "" +msgstr "e" #: mediagoblin/user_pages/forms.py:24 msgid "Comment" @@ -543,16 +575,16 @@ msgid "I am sure I want to delete this" msgstr "Eu tenho certeza de que quero pagar isso" #: mediagoblin/user_pages/views.py:155 -msgid "Empty comments are not allowed." -msgstr "" +msgid "Oops, your comment was empty." +msgstr "Opa, seu comentáio estava vazio." #: mediagoblin/user_pages/views.py:161 -msgid "Comment posted!" -msgstr "" +msgid "Your comment has been posted!" +msgstr "Seu comentário foi postado!" #: mediagoblin/user_pages/views.py:183 msgid "You deleted the media." -msgstr "" +msgstr "Você deletou a mídia." #: mediagoblin/user_pages/views.py:190 msgid "The media was not deleted because you didn't check that you were sure." 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 96fd46d8..b747fc3a 100644 --- a/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/ro/LC_MESSAGES/mediagoblin.po @@ -4,13 +4,14 @@ # # 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-27 15:25-0600\n" -"PO-Revision-Date: 2011-11-27 21:28+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 18:41+0000\n" +"Last-Translator: gap <gapop@hotmail.com>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -57,14 +58,14 @@ msgstr "Ne pare rău, există deja un utilizator cu același nume." #: mediagoblin/auth/views.py:77 msgid "Sorry, a user with that email address already exists." -msgstr "" +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 @@ -73,11 +74,11 @@ msgstr "Cheie de verificare sau user ID incorect." #: mediagoblin/auth/views.py:203 msgid "You must be logged in so we know who to send the email to!" -msgstr "" +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 "" +msgstr "Adresa ta de e-mail a fost deja verificată!" #: mediagoblin/auth/views.py:224 msgid "Resent your verification email." @@ -89,7 +90,7 @@ msgid "" "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" @@ -97,11 +98,11 @@ msgstr "Titlu" #: mediagoblin/edit/forms.py:28 mediagoblin/submit/forms.py:32 msgid "Tags" -msgstr "Etichete" +msgstr "Tag-uri" #: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 -msgid "Seperate tags by commas or spaces." -msgstr "" +msgid "Seperate tags by commas." +msgstr "Desparte tag-urile prin virgulă." #: mediagoblin/edit/forms.py:33 msgid "Slug" @@ -128,11 +129,11 @@ msgstr "Sit Web" #: mediagoblin/edit/forms.py:49 msgid "Old password" -msgstr "" +msgstr "Vechea parolă" #: mediagoblin/edit/forms.py:52 msgid "New Password" -msgstr "" +msgstr "Noua parolă" #: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." @@ -149,15 +150,15 @@ msgstr "Editezi profilul unui utilizator. Se recomandă prudență." #: mediagoblin/edit/views.py:171 msgid "Wrong password" -msgstr "" +msgstr "Parolă incorectă" #: mediagoblin/edit/views.py:192 msgid "Profile edited!" -msgstr "" +msgstr "Profilul a fost modificat!" -#: mediagoblin/media_types/__init__.py:61 +#: mediagoblin/media_types/__init__.py:65 msgid "Could not find any file extension in \"{filename}\"" -msgstr "" +msgstr "Nu pot extrage extensia din „{filename}”" #: mediagoblin/submit/forms.py:25 msgid "File" @@ -173,19 +174,19 @@ msgstr "Trebuie să selectezi un fișier." #: mediagoblin/submit/views.py:127 msgid "Woohoo! Submitted!" -msgstr "Gata, trimis!" +msgstr "Ura! Trimis!" #: mediagoblin/submit/views.py:133 msgid "Invalid file type." -msgstr "" +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 "" @@ -209,11 +210,11 @@ msgstr "Transmite un fișier media" #: mediagoblin/templates/mediagoblin/base.html:65 msgid "Verify your email!" -msgstr "" +msgstr "Verifică adresa de e-mail!" #: mediagoblin/templates/mediagoblin/base.html:72 msgid "log out" -msgstr "" +msgstr "ieșire" #: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 @@ -235,21 +236,27 @@ msgstr "Explorează" #: mediagoblin/templates/mediagoblin/root.html:27 msgid "Hi there, welcome to this MediaGoblin site!" -msgstr "" +msgstr "Salut, bine ai venit pe acest site MediaGoblin!" #: mediagoblin/templates/mediagoblin/root.html:28 -msgid "Your finest source for all goblin-related media." +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." msgstr "" +"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:29 msgid "" "To add your own media, place comments, save your favourites and more, you " "can log in with your MediaGoblin account." msgstr "" +"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:31 msgid "Don't have one yet? It's easy!" -msgstr "" +msgstr "Încă nu ai unul? E simplu!" #: mediagoblin/templates/mediagoblin/root.html:32 #, python-format @@ -258,6 +265,9 @@ msgid "" " or\n" " <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\">Creează un cont pe acest site</a>\n" +" sau\n" +" <a class=\"button_action\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Instalează MediaGoblin pe propriul tău server</a>" #: mediagoblin/templates/mediagoblin/root.html:44 msgid "Most recent media" @@ -267,13 +277,18 @@ msgstr "Cele mai recente fișiere" msgid "Enter your new password" msgstr "Introdu noua parolă" +#: 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 "" +msgstr "Recuperează parola" #: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 msgid "Send instructions" -msgstr "" +msgstr "Trimite instrucțiuni" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 msgid "Your password has been changed. Try to log in now." @@ -371,30 +386,51 @@ msgstr "Editare profil %(username)s" #: mediagoblin/templates/mediagoblin/listings/tag.html:35 #, python-format msgid "Media tagged with: %(tag_name)s" -msgstr "" +msgstr "Fișier etichetat cu tag-urile: %(tag_name)s" #: mediagoblin/templates/mediagoblin/media_displays/video.html:19 msgid "Original" -msgstr "" +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 "" +msgstr "Fișierele lui %(username)s" #: 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/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 msgid "Really delete %(title)s?" @@ -438,7 +474,7 @@ 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:53 msgid "Almost done! Your account still needs to be activated." @@ -524,13 +560,17 @@ 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 "" +msgstr "Tag-uri" #: mediagoblin/templates/mediagoblin/utils/tags.html:25 msgid "and" -msgstr "" +msgstr "și" #: mediagoblin/user_pages/forms.py:24 msgid "Comment" @@ -541,20 +581,20 @@ msgid "I am sure I want to delete this" msgstr "Sunt sigur că doresc să șterg" #: mediagoblin/user_pages/views.py:155 -msgid "Empty comments are not allowed." -msgstr "Comentariul trebuie să aibă un conținut." +msgid "Oops, your comment was empty." +msgstr "Hopa, ai uitat să scrii comentariul." #: mediagoblin/user_pages/views.py:161 -msgid "Comment posted!" -msgstr "Comentariul a fost transmis." +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 "" +msgstr "Ai șters acest fișier" #: mediagoblin/user_pages/views.py:190 msgid "The media was not deleted because you didn't check that you were sure." -msgstr "" +msgstr "Fișierul nu a fost șters deoarece nu ai confirmat că ești sigur." #: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." 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 9fb1ce08..098ea38c 100644 --- a/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/ru/LC_MESSAGES/mediagoblin.po @@ -8,9 +8,9 @@ msgid "" msgstr "" "Project-Id-Version: GNU MediaGoblin\n" "Report-Msgid-Bugs-To: http://bugs.foocorp.net/projects/mediagoblin/issues\n" -"POT-Creation-Date: 2011-11-27 15:25-0600\n" -"PO-Revision-Date: 2011-11-27 21:28+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 19:58+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" @@ -58,6 +58,8 @@ msgstr "Извините, пользователь с этим именем уж #: mediagoblin/auth/views.py:77 msgid "Sorry, a user with that email address already exists." msgstr "" +"Сожалеем, но на этот адрес электронной почты уже зарегистрирована другая " +"учётная запись." #: mediagoblin/auth/views.py:179 msgid "" @@ -73,11 +75,11 @@ msgstr "Неверный ключ проверки или идентификат #: mediagoblin/auth/views.py:203 msgid "You must be logged in so we know who to send the email to!" -msgstr "" +msgstr "Вам надо представиться, чтобы мы знали, кому отправлять сообщение!" #: mediagoblin/auth/views.py:211 msgid "You've already verified your email address!" -msgstr "" +msgstr "Вы уже потвердили свой адрес электронной почты!" #: mediagoblin/auth/views.py:224 msgid "Resent your verification email." @@ -101,8 +103,8 @@ msgid "Tags" msgstr "Метки" #: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 -msgid "Seperate tags by commas or spaces." -msgstr "" +msgid "Seperate tags by commas." +msgstr "Разделяйте метки запятыми." #: mediagoblin/edit/forms.py:33 msgid "Slug" @@ -129,11 +131,11 @@ msgstr "Сайт" #: mediagoblin/edit/forms.py:49 msgid "Old password" -msgstr "" +msgstr "Старый пароль" #: mediagoblin/edit/forms.py:52 msgid "New Password" -msgstr "" +msgstr "Новый пароль" #: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." @@ -150,15 +152,15 @@ msgstr "Вы редактируете профиль пользователя. #: mediagoblin/edit/views.py:171 msgid "Wrong password" -msgstr "" +msgstr "Неправильный пароль" #: mediagoblin/edit/views.py:192 msgid "Profile edited!" -msgstr "" +msgstr "Профиль изменён!" -#: mediagoblin/media_types/__init__.py:61 +#: mediagoblin/media_types/__init__.py:65 msgid "Could not find any file extension in \"{filename}\"" -msgstr "" +msgstr "В «{filename}» не обнаружено расширение имени файла" #: mediagoblin/submit/forms.py:25 msgid "File" @@ -178,7 +180,7 @@ msgstr "Ура! Файл загружен!" #: mediagoblin/submit/views.py:133 msgid "Invalid file type." -msgstr "" +msgstr "Неподходящий тип файла." #: mediagoblin/templates/mediagoblin/404.html:21 msgid "Oops!" @@ -208,11 +210,11 @@ msgstr "Загрузить файл" #: mediagoblin/templates/mediagoblin/base.html:65 msgid "Verify your email!" -msgstr "" +msgstr "Подтвердите ваш адрес электронной почты!" #: mediagoblin/templates/mediagoblin/base.html:72 msgid "log out" -msgstr "" +msgstr "завершение сеанса" #: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 @@ -230,25 +232,32 @@ msgstr "" #: mediagoblin/templates/mediagoblin/root.html:24 msgid "Explore" -msgstr "" +msgstr "Смотреть" #: mediagoblin/templates/mediagoblin/root.html:27 msgid "Hi there, welcome to this MediaGoblin site!" -msgstr "" +msgstr "Привет! Добро пожаловать на наш MediaGoblin’овый сайт!" #: mediagoblin/templates/mediagoblin/root.html:28 -msgid "Your finest source for all goblin-related media." +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." msgstr "" +"Этот сайт работает на <a href=\"http://mediagoblin.org\">MediaGoblin</a>, " +"необыкновенно замечательном ПО для хостинга мультимедийных файлов." #: mediagoblin/templates/mediagoblin/root.html:29 msgid "" "To add your own media, place comments, save your favourites and more, you " "can log in with your MediaGoblin account." msgstr "" +"Для добавления собственных файлов, комментирования, ведения списка любимых " +"файлов и т. п. вы можете представиться с помощью вашей MediaGoblin’овой " +"учётной записи." #: mediagoblin/templates/mediagoblin/root.html:31 msgid "Don't have one yet? It's easy!" -msgstr "" +msgstr "У вас её ещё нет? Не проблема!" #: mediagoblin/templates/mediagoblin/root.html:32 #, python-format @@ -257,6 +266,9 @@ msgid "" " or\n" " <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:44 msgid "Most recent media" @@ -266,13 +278,18 @@ msgstr "Самые новые файлы" msgid "Enter your new password" 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 "" +msgstr "Сброс пароля" #: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 msgid "Send instructions" -msgstr "" +msgstr "Отправить инструкцию" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 msgid "Your password has been changed. Try to log in now." @@ -372,30 +389,51 @@ msgstr "Редактирование профиля %(username)s" #: mediagoblin/templates/mediagoblin/listings/tag.html:35 #, python-format msgid "Media tagged with: %(tag_name)s" -msgstr "" +msgstr "Файлы с меткой: %(tag_name)s" #: mediagoblin/templates/mediagoblin/media_displays/video.html:19 msgid "Original" -msgstr "" +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 "" +msgstr "Файлы %(username)s" #: 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/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 msgid "Really delete %(title)s?" @@ -525,13 +563,17 @@ 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 "" +msgstr "Метки:" #: mediagoblin/templates/mediagoblin/utils/tags.html:25 msgid "and" -msgstr "" +msgstr "и" #: mediagoblin/user_pages/forms.py:24 msgid "Comment" @@ -542,20 +584,20 @@ msgid "I am sure I want to delete this" msgstr "Я уверен, что хочу удалить это" #: mediagoblin/user_pages/views.py:155 -msgid "Empty comments are not allowed." -msgstr "Empty comments are not allowed." +msgid "Oops, your comment was empty." +msgstr "Ой, ваш комментарий был пуст." #: mediagoblin/user_pages/views.py:161 -msgid "Comment posted!" -msgstr "Комментарий размещён!" +msgid "Your comment has been posted!" +msgstr "Ваш комментарий размещён!" #: mediagoblin/user_pages/views.py:183 msgid "You deleted the media." -msgstr "" +msgstr "Вы удалили файл." #: mediagoblin/user_pages/views.py:190 msgid "The media was not deleted because you didn't check that you were sure." -msgstr "" +msgstr "Файл не удалён, так как вы не подтвердили свою уверенность галочкой." #: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." 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 bee7b3b5..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-27 15:25-0600\n" -"PO-Revision-Date: 2011-11-27 21:28+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" @@ -57,7 +57,7 @@ msgstr "Prepáč, rovnaké prihlasovacie meno už niekto používa." #: mediagoblin/auth/views.py:77 msgid "Sorry, a user with that email address already exists." -msgstr "" +msgstr "Prepáč, používateľ s rovnakou e-mailovou adresou už existuje." #: mediagoblin/auth/views.py:179 msgid "" @@ -73,11 +73,11 @@ msgstr "Nesprávny overovací kľúč alebo používateľské ID" #: mediagoblin/auth/views.py:203 msgid "You must be logged in so we know who to send the email to!" -msgstr "" +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 "" +msgstr "Tvoja e-mailová adresa už bola raz overená!" #: mediagoblin/auth/views.py:224 msgid "Resent your verification email." @@ -100,8 +100,8 @@ msgid "Tags" msgstr "Štítky" #: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 -msgid "Seperate tags by commas or spaces." -msgstr "" +msgid "Seperate tags by commas." +msgstr "Oddeľ štítky pomocou čiarky." #: mediagoblin/edit/forms.py:33 msgid "Slug" @@ -126,11 +126,11 @@ msgstr "Webstránka" #: mediagoblin/edit/forms.py:49 msgid "Old password" -msgstr "" +msgstr "Staré heslo" #: mediagoblin/edit/forms.py:52 msgid "New Password" -msgstr "" +msgstr "Nové heslo" #: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." @@ -146,15 +146,15 @@ msgstr "Upravuješ používateľský profil. Pristupuj opatrne." #: mediagoblin/edit/views.py:171 msgid "Wrong password" -msgstr "" +msgstr "Nesprávne heslo" #: mediagoblin/edit/views.py:192 msgid "Profile edited!" -msgstr "" +msgstr "Profil upravený!" -#: mediagoblin/media_types/__init__.py:61 +#: mediagoblin/media_types/__init__.py:65 msgid "Could not find any file extension in \"{filename}\"" -msgstr "" +msgstr "Nebolo možné nájsť žiadnu príponu v súbore \"{filename}\"" #: mediagoblin/submit/forms.py:25 msgid "File" @@ -174,7 +174,7 @@ msgstr "Juchú! Úspešne vložené!" #: mediagoblin/submit/views.py:133 msgid "Invalid file type." -msgstr "" +msgstr "Nesprávny typ súboru." #: mediagoblin/templates/mediagoblin/404.html:21 msgid "Oops!" @@ -206,11 +206,11 @@ msgstr "Vložiť výtvor" #: mediagoblin/templates/mediagoblin/base.html:65 msgid "Verify your email!" -msgstr "" +msgstr "Over si e-mail!" #: mediagoblin/templates/mediagoblin/base.html:72 msgid "log out" -msgstr "" +msgstr "odhlásenie" #: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 @@ -232,21 +232,27 @@ msgstr "Preskúmať" #: mediagoblin/templates/mediagoblin/root.html:27 msgid "Hi there, welcome to this MediaGoblin site!" -msgstr "" +msgstr "Ahoj, vitaj na tejto MediaGoblin stránke!" #: mediagoblin/templates/mediagoblin/root.html:28 -msgid "Your finest source for all goblin-related media." +msgid "" +"This site is running <a href=\"http://mediagoblin.org\">MediaGoblin</a>, an " +"extraordinarily great piece of media hosting software." msgstr "" +"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:29 msgid "" "To add your own media, place comments, save your favourites and more, you " "can log in with your MediaGoblin account." msgstr "" +"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:31 msgid "Don't have one yet? It's easy!" -msgstr "" +msgstr "Ešte žiaden nemáš? Je to jednoduché!" #: mediagoblin/templates/mediagoblin/root.html:32 #, python-format @@ -255,6 +261,9 @@ msgid "" " or\n" " <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" +" alebo\n" +" <a class=\"header_submit\" href=\"http://wiki.mediagoblin.org/HackingHowto\">Sprevádzkovať MediaGoblin na vlastnom serveri</a>" #: mediagoblin/templates/mediagoblin/root.html:44 msgid "Most recent media" @@ -264,13 +273,18 @@ msgstr "Najčerstvejšie výtvory" msgid "Enter your new password" msgstr "Vlož svoje nové heslo" +#: 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 "" +msgstr "Obnoviť heslo" #: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 msgid "Send instructions" -msgstr "" +msgstr "Zaslať inštrukcie" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 msgid "Your password has been changed. Try to log in now." @@ -370,30 +384,51 @@ msgstr "Úprava profilu, ktorý vlastní %(username)s" #: mediagoblin/templates/mediagoblin/listings/tag.html:35 #, python-format msgid "Media tagged with: %(tag_name)s" -msgstr "" +msgstr "Výtvory označené s: %(tag_name)s" #: mediagoblin/templates/mediagoblin/media_displays/video.html:19 msgid "Original" -msgstr "" +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 "" +msgstr "Výtvory používateľa %(username)s" #: 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/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 msgid "Really delete %(title)s?" @@ -522,13 +557,17 @@ 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 "" +msgstr "Označené s" #: mediagoblin/templates/mediagoblin/utils/tags.html:25 msgid "and" -msgstr "" +msgstr "a" #: mediagoblin/user_pages/forms.py:24 msgid "Comment" @@ -539,20 +578,20 @@ msgid "I am sure I want to delete this" msgstr "Jednoznačne to chcem odstrániť" #: mediagoblin/user_pages/views.py:155 -msgid "Empty comments are not allowed." -msgstr "Komentáre bez obsahu nepovolené." +msgid "Oops, your comment was empty." +msgstr "Ajaj, tvoj komentár bol prázdny." #: mediagoblin/user_pages/views.py:161 -msgid "Comment posted!" -msgstr "Komentár odoslaný!" +msgid "Your comment has been posted!" +msgstr "Tvoj komentár bol zaslaný!" #: mediagoblin/user_pages/views.py:183 msgid "You deleted the media." -msgstr "" +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 "" +msgstr "Výtvor nebol odstránený, nakoľko chýbala tvoja konfirmácia." #: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." 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 77273ebe..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-27 15:25-0600\n" -"PO-Revision-Date: 2011-11-27 21:28+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" @@ -98,7 +98,7 @@ msgid "Tags" msgstr "Oznake" #: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 -msgid "Seperate tags by commas or spaces." +msgid "Seperate tags by commas." msgstr "" #: mediagoblin/edit/forms.py:33 @@ -150,7 +150,7 @@ msgstr "" msgid "Profile edited!" msgstr "" -#: mediagoblin/media_types/__init__.py:61 +#: mediagoblin/media_types/__init__.py:65 msgid "Could not find any file extension in \"{filename}\"" msgstr "" @@ -231,7 +231,9 @@ msgid "Hi there, welcome to this MediaGoblin site!" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:28 -msgid "Your finest source for all goblin-related media." +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:29 @@ -260,6 +262,11 @@ msgstr "" msgid "Enter your new password" msgstr "" +#: 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 "" @@ -366,10 +373,6 @@ msgstr "" 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" @@ -380,6 +383,31 @@ msgstr "" 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/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 msgid "Really delete %(title)s?" @@ -507,6 +535,10 @@ 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 "" @@ -524,11 +556,11 @@ msgid "I am sure I want to delete this" msgstr "" #: mediagoblin/user_pages/views.py:155 -msgid "Empty comments are not allowed." +msgid "Oops, your comment was empty." msgstr "" #: mediagoblin/user_pages/views.py:161 -msgid "Comment posted!" +msgid "Your comment has been posted!" msgstr "" #: mediagoblin/user_pages/views.py:183 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 0bdfc21c..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-27 15:25-0600\n" -"PO-Revision-Date: 2011-11-27 21:28+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" @@ -95,7 +95,7 @@ msgid "Tags" msgstr "" #: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 -msgid "Seperate tags by commas or spaces." +msgid "Seperate tags by commas." msgstr "" #: mediagoblin/edit/forms.py:33 @@ -147,7 +147,7 @@ msgstr "" msgid "Profile edited!" msgstr "" -#: mediagoblin/media_types/__init__.py:61 +#: mediagoblin/media_types/__init__.py:65 msgid "Could not find any file extension in \"{filename}\"" msgstr "" @@ -226,7 +226,9 @@ msgid "Hi there, welcome to this MediaGoblin site!" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:28 -msgid "Your finest source for all goblin-related media." +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:29 @@ -255,6 +257,11 @@ msgstr "" msgid "Enter your new password" 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 "" @@ -355,10 +362,6 @@ msgstr "" 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" @@ -369,6 +372,31 @@ msgstr "" msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" 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 msgid "Really delete %(title)s?" @@ -492,6 +520,10 @@ 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 "" @@ -509,11 +541,11 @@ msgid "I am sure I want to delete this" msgstr "" #: mediagoblin/user_pages/views.py:155 -msgid "Empty comments are not allowed." +msgid "Oops, your comment was empty." msgstr "" #: mediagoblin/user_pages/views.py:161 -msgid "Comment posted!" +msgid "Your comment has been posted!" msgstr "" #: mediagoblin/user_pages/views.py:183 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 37bd36c1..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-27 15:25-0600\n" -"PO-Revision-Date: 2011-11-27 21:28+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" @@ -101,7 +101,7 @@ msgid "Tags" msgstr "Taggar" #: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 -msgid "Seperate tags by commas or spaces." +msgid "Seperate tags by commas." msgstr "" #: mediagoblin/edit/forms.py:33 @@ -153,7 +153,7 @@ msgstr "" msgid "Profile edited!" msgstr "" -#: mediagoblin/media_types/__init__.py:61 +#: mediagoblin/media_types/__init__.py:65 msgid "Could not find any file extension in \"{filename}\"" msgstr "" @@ -236,7 +236,9 @@ msgid "Hi there, welcome to this MediaGoblin site!" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:28 -msgid "Your finest source for all goblin-related media." +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:29 @@ -265,6 +267,11 @@ msgstr "Senast medier" msgid "Enter your new password" msgstr "Fyll i ditt 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 "" @@ -380,10 +387,6 @@ msgstr "" 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" @@ -394,6 +397,31 @@ msgstr "" 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/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 msgid "Really delete %(title)s?" @@ -525,6 +553,10 @@ 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 "" @@ -542,11 +574,11 @@ 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:155 -msgid "Empty comments are not allowed." +msgid "Oops, your comment was empty." msgstr "" #: mediagoblin/user_pages/views.py:161 -msgid "Comment posted!" +msgid "Your comment has been posted!" msgstr "" #: mediagoblin/user_pages/views.py:183 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 064fa7d1..f7bbd6ac 100644 --- a/mediagoblin/i18n/te/LC_MESSAGES/mediagoblin.po +++ b/mediagoblin/i18n/te/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-27 15:25-0600\n" -"PO-Revision-Date: 2011-11-27 21:28+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" @@ -96,7 +96,7 @@ msgid "Tags" msgstr "" #: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 -msgid "Seperate tags by commas or spaces." +msgid "Seperate tags by commas." msgstr "" #: mediagoblin/edit/forms.py:33 @@ -148,7 +148,7 @@ msgstr "" msgid "Profile edited!" msgstr "" -#: mediagoblin/media_types/__init__.py:61 +#: mediagoblin/media_types/__init__.py:65 msgid "Could not find any file extension in \"{filename}\"" msgstr "" @@ -227,7 +227,9 @@ msgid "Hi there, welcome to this MediaGoblin site!" msgstr "" #: mediagoblin/templates/mediagoblin/root.html:28 -msgid "Your finest source for all goblin-related media." +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:29 @@ -256,6 +258,11 @@ msgstr "" msgid "Enter your new password" 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 "" @@ -356,10 +363,6 @@ msgstr "" 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" @@ -370,6 +373,31 @@ msgstr "" msgid "<a href=\"%(user_url)s\">%(username)s</a>'s media" 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 msgid "Really delete %(title)s?" @@ -493,6 +521,10 @@ 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 "" @@ -510,11 +542,11 @@ msgid "I am sure I want to delete this" msgstr "" #: mediagoblin/user_pages/views.py:155 -msgid "Empty comments are not allowed." +msgid "Oops, your comment was empty." msgstr "" #: mediagoblin/user_pages/views.py:161 -msgid "Comment posted!" +msgid "Your comment has been posted!" msgstr "" #: mediagoblin/user_pages/views.py:183 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 5e406b41..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-27 15:25-0600\n" -"PO-Revision-Date: 2011-11-27 21:28+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" @@ -58,7 +58,7 @@ msgstr "抱歉, 這個使用者名稱已經存在." #: mediagoblin/auth/views.py:77 msgid "Sorry, a user with that email address already exists." -msgstr "" +msgstr "抱歉,此電子郵件已被註冊了。" #: mediagoblin/auth/views.py:179 msgid "" @@ -72,11 +72,11 @@ msgstr "認證碼或是使用者帳號錯誤" #: mediagoblin/auth/views.py:203 msgid "You must be logged in so we know who to send the email to!" -msgstr "" +msgstr "你必須登入,我們才知道信要送給誰!" #: mediagoblin/auth/views.py:211 msgid "You've already verified your email address!" -msgstr "" +msgstr "你的電子郵件已經確認了!" #: mediagoblin/auth/views.py:224 msgid "Resent your verification email." @@ -97,7 +97,7 @@ msgid "Tags" msgstr "標籤" #: mediagoblin/edit/forms.py:30 mediagoblin/submit/forms.py:34 -msgid "Seperate tags by commas or spaces." +msgid "Seperate tags by commas." msgstr "" #: mediagoblin/edit/forms.py:33 @@ -123,11 +123,11 @@ msgstr "網站" #: mediagoblin/edit/forms.py:49 msgid "Old password" -msgstr "" +msgstr "舊的密碼" #: mediagoblin/edit/forms.py:52 msgid "New Password" -msgstr "" +msgstr "新的密碼" #: mediagoblin/edit/views.py:65 msgid "An entry with that slug already exists for this user." @@ -143,15 +143,15 @@ msgstr "你正在編輯一位用戶的檔案. 請謹慎處理." #: mediagoblin/edit/views.py:171 msgid "Wrong password" -msgstr "" +msgstr "密碼錯誤" #: mediagoblin/edit/views.py:192 msgid "Profile edited!" -msgstr "" +msgstr "個人資料已被編輯了!" -#: mediagoblin/media_types/__init__.py:61 +#: mediagoblin/media_types/__init__.py:65 msgid "Could not find any file extension in \"{filename}\"" -msgstr "" +msgstr "找不到任何 \"{filename}\" 的附檔名。" #: mediagoblin/submit/forms.py:25 msgid "File" @@ -171,7 +171,7 @@ msgstr "呼呼! 送出去嚕!" #: mediagoblin/submit/views.py:133 msgid "Invalid file type." -msgstr "" +msgstr "不正確的檔案格式" #: mediagoblin/templates/mediagoblin/404.html:21 msgid "Oops!" @@ -201,11 +201,11 @@ msgstr "遞交媒體" #: mediagoblin/templates/mediagoblin/base.html:65 msgid "Verify your email!" -msgstr "" +msgstr "確認你的電子郵件" #: mediagoblin/templates/mediagoblin/base.html:72 msgid "log out" -msgstr "" +msgstr "登出" #: mediagoblin/templates/mediagoblin/base.html:75 #: mediagoblin/templates/mediagoblin/auth/login.html:27 @@ -227,21 +227,23 @@ msgstr "探索" #: mediagoblin/templates/mediagoblin/root.html:27 msgid "Hi there, welcome to this MediaGoblin site!" -msgstr "" +msgstr "嘿!歡迎來到 媒體怪獸(MediaGoblin) 網站" #: mediagoblin/templates/mediagoblin/root.html:28 -msgid "Your finest source for all goblin-related media." +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:29 msgid "" "To add your own media, place comments, save your favourites and more, you " "can log in with your MediaGoblin account." -msgstr "" +msgstr "你可以用 媒體怪獸 帳號登入,加入你自己的媒體檔案,加入評語,把你的最愛儲存起來。" #: mediagoblin/templates/mediagoblin/root.html:31 msgid "Don't have one yet? It's easy!" -msgstr "" +msgstr "還沒有嗎?其實非常簡單!" #: mediagoblin/templates/mediagoblin/root.html:32 #, python-format @@ -250,6 +252,9 @@ msgid "" " or\n" " <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\">建立一個自己的媒體怪獸(MedaiGoblin)</a>" #: mediagoblin/templates/mediagoblin/root.html:44 msgid "Most recent media" @@ -259,13 +264,18 @@ msgstr "最新的媒體" msgid "Enter your new password" 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 "" +msgstr "找回密碼" #: mediagoblin/templates/mediagoblin/auth/forgot_password.html:30 msgid "Send instructions" -msgstr "" +msgstr "送出指示" #: mediagoblin/templates/mediagoblin/auth/fp_changed_success.html:22 msgid "Your password has been changed. Try to log in now." @@ -361,30 +371,51 @@ msgstr "編輯 %(username)s'的檔案中" #: mediagoblin/templates/mediagoblin/listings/tag.html:35 #, python-format msgid "Media tagged with: %(tag_name)s" -msgstr "" +msgstr "此媒體被標識為:%(tag_name)s" #: mediagoblin/templates/mediagoblin/media_displays/video.html:19 msgid "Original" -msgstr "" +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 "" +msgstr "%(username)s的媒體" #: 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/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 msgid "Really delete %(title)s?" @@ -508,13 +539,17 @@ 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 "" +msgstr "被標籤為" #: mediagoblin/templates/mediagoblin/utils/tags.html:25 msgid "and" -msgstr "" +msgstr "且" #: mediagoblin/user_pages/forms.py:24 msgid "Comment" @@ -525,20 +560,20 @@ msgid "I am sure I want to delete this" msgstr "我確定我想要刪除" #: mediagoblin/user_pages/views.py:155 -msgid "Empty comments are not allowed." -msgstr "評論不能空白。" +msgid "Oops, your comment was empty." +msgstr "" #: mediagoblin/user_pages/views.py:161 -msgid "Comment posted!" -msgstr "評論已經張貼!" +msgid "Your comment has been posted!" +msgstr "" #: mediagoblin/user_pages/views.py:183 msgid "You deleted the media." -msgstr "" +msgstr "你已刪除此媒體檔案。" #: mediagoblin/user_pages/views.py:190 msgid "The media was not deleted because you didn't check that you were sure." -msgstr "" +msgstr "此媒體檔案尚未被刪除因為你還沒有確認你真的要刪除。" #: mediagoblin/user_pages/views.py:198 msgid "You are about to delete another user's media. Proceed with caution." diff --git a/mediagoblin/listings/views.py b/mediagoblin/listings/views.py index 5a09de43..6b83ffcf 100644 --- a/mediagoblin/listings/views.py +++ b/mediagoblin/listings/views.py @@ -86,7 +86,7 @@ def tag_atom_feed(request): feed.add(entry.get('title'), entry.get('description_html'), content_type='html', - author=entry.get_uploader()['username'], + author=entry.get_uploader().username, updated=entry.get('created'), url=entry.url_for_self(request.urlgen)) diff --git a/mediagoblin/meddleware/csrf.py b/mediagoblin/meddleware/csrf.py index 16541bee..a4e4e5c6 100644 --- a/mediagoblin/meddleware/csrf.py +++ b/mediagoblin/meddleware/csrf.py @@ -50,6 +50,9 @@ 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 diff --git a/mediagoblin/media_types/__init__.py b/mediagoblin/media_types/__init__.py index 4fa56bc3..6f94c714 100644 --- a/mediagoblin/media_types/__init__.py +++ b/mediagoblin/media_types/__init__.py @@ -60,6 +60,10 @@ def get_media_manager(_media_type): 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): ''' diff --git a/mediagoblin/media_types/video/processing.py b/mediagoblin/media_types/video/processing.py index 6125e49c..7d261226 100644 --- a/mediagoblin/media_types/video/processing.py +++ b/mediagoblin/media_types/video/processing.py @@ -41,6 +41,8 @@ def process_video(entry): 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'] @@ -75,7 +77,7 @@ def process_video(entry): entry['media_files']['webm_640'] = medium_filepath # Save the width and height of the transcoded video - entry['media_data']['video'] = { + entry.media_data['video'] = { u'width': transcoder.dst_data.videowidth, u'height': transcoder.dst_data.videoheight} @@ -94,25 +96,24 @@ def process_video(entry): entry['media_files']['thumb'] = thumbnail_filepath + if video_config['keep_original']: + # Push original file to public storage + queued_file = file(queued_filename, 'rb') - # 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 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') + 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 + entry['media_files']['original'] = original_filepath mgg.queue_store.delete_file(queued_filepath) - # Save the MediaEntry entry.save() diff --git a/mediagoblin/processing.py b/mediagoblin/processing.py index 89c4ac89..7dd5cc7d 100644 --- a/mediagoblin/processing.py +++ b/mediagoblin/processing.py @@ -55,8 +55,8 @@ class ProcessMedia(Task): # Try to process, and handle expected errors. try: - #__import__(entry['media_type']) - manager = get_media_manager(entry['media_type']) + #__import__(entry.media_type) + manager = get_media_manager(entry.media_type) manager['processor'](entry) except BaseProcessingFail, exc: mark_entry_failed(entry._id, exc) diff --git a/mediagoblin/static/css/base.css b/mediagoblin/static/css/base.css index 12d88ffa..2a78006d 100644 --- a/mediagoblin/static/css/base.css +++ b/mediagoblin/static/css/base.css @@ -96,6 +96,7 @@ input, textarea { a.mediagoblin_logo{ color: #fff; font-weight: bold; + margin-right: 8px; } .mediagoblin_footer { @@ -117,27 +118,27 @@ a.mediagoblin_logo{ /* common website elements */ -.button_action, .button_action_highlight{ +.button_action, .button_action_highlight { + display: inline-block; color: #c3c3c3; background-color: #363636; border: 1px solid; border-color: #464646 #2B2B2B #252525; border-radius: 4px; - margin: 8px; padding: 3px 8px; + font-size: 16px; text-decoration: none; font-style: normal; font-weight: bold; - font-size: 1em; + cursor: pointer; } -.button_action_highlight{ +.button_action_highlight { background-color: #86D4B1; border-color: #A2DEC3 #6CAA8E #5C9179; color: #283F35; } - .button_form, .cancel_link { height: 32px; min-width: 99px; @@ -171,15 +172,15 @@ a.mediagoblin_logo{ background-image: linear-gradient(top, #D2D2D2, #aaa); } -.pagination{ +.pagination { text-align: center; } -.pagination_arrow{ +.pagination_arrow { margin: 5px; } -.empty_space{ +.empty_space { background-image: url("../images/empty_back.png"); font-style: italic; text-align: center; @@ -187,6 +188,18 @@ text-align: center; padding-top: 70px; } +.right_align { + float: right; +} + +textarea#comment_content { + width: 634px; + height: 90px; + border: none; + background-color: #f1f1f1; + padding: 3px; +} + /* forms */ .form_box { @@ -273,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; @@ -305,7 +322,7 @@ img.media_icon{ margin: 0 0 20px } -.navigation_left{ +.navigation_left { margin-right: 6px; } 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/submit/views.py b/mediagoblin/submit/views.py index 3def44ce..4e4c7c43 100644 --- a/mediagoblin/submit/views.py +++ b/mediagoblin/submit/views.py @@ -55,16 +55,16 @@ def submit_start(request): # create entry and save in database entry = request.db.MediaEntry() entry['_id'] = ObjectId() - entry['media_type'] = unicode(media_type) - entry['title'] = ( + 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.description = unicode(request.POST.get('description')) + entry.description_html = cleaned_markdown_conversion( + entry.description) - entry['uploader'] = request.user['_id'] + entry.uploader = request.user._id # Process the user's folksonomy "tags" entry['tags'] = convert_to_tag_list_of_dicts( @@ -127,7 +127,7 @@ def submit_start(request): add_message(request, SUCCESS, _('Woohoo! Submitted!')) return redirect(request, "mediagoblin.user_pages.user_home", - user=request.user['username']) + user=request.user.username) except InvalidFileType, exc: submit_form.file.errors.append( _(u'Invalid file type.')) diff --git a/mediagoblin/templates/mediagoblin/auth/register.html b/mediagoblin/templates/mediagoblin/auth/register.html index a0d0a277..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') }}" diff --git a/mediagoblin/templates/mediagoblin/base.html b/mediagoblin/templates/mediagoblin/base.html index 29639026..b8061f24 100644 --- a/mediagoblin/templates/mediagoblin/base.html +++ b/mediagoblin/templates/mediagoblin/base.html @@ -32,10 +32,11 @@ 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"> @@ -48,7 +49,7 @@ ><img src="{{ request.staticdirect('/images/logo.png') }}" alt="{% trans %}MediaGoblin logo{% endtrans %}" /></a> {% endblock %} - {% if request.user and request.user['status'] == 'active' %} + {% if request.user and request.user.status == 'active' %} <a class="button_action" href="{{ request.urlgen('mediagoblin.submit.start') }}"> {% trans %}Submit media{% endtrans %} @@ -60,14 +61,14 @@ {# 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']) }}" + 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') }}">{% trans %}log out{% endtrans %}</a>) {% else %} diff --git a/mediagoblin/templates/mediagoblin/edit/edit_profile.html b/mediagoblin/templates/mediagoblin/edit/edit_profile.html index bf8fe5c1..2d5daa95 100644 --- a/mediagoblin/templates/mediagoblin/edit/edit_profile.html +++ b/mediagoblin/templates/mediagoblin/edit/edit_profile.html @@ -22,11 +22,11 @@ {% 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> diff --git a/mediagoblin/templates/mediagoblin/media_displays/video.html b/mediagoblin/templates/mediagoblin/media_displays/video.html index 5b8ec789..5ef1a782 100644 --- a/mediagoblin/templates/mediagoblin/media_displays/video.html +++ b/mediagoblin/templates/mediagoblin/media_displays/video.html @@ -21,5 +21,5 @@ {%- endtrans -%} </a> </p> - {% endif %} + {% endif %} {% endblock %} diff --git a/mediagoblin/templates/mediagoblin/root.html b/mediagoblin/templates/mediagoblin/root.html index 25ce9e96..0f769f2f 100644 --- a/mediagoblin/templates/mediagoblin/root.html +++ b/mediagoblin/templates/mediagoblin/root.html @@ -25,7 +25,7 @@ {% 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> diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html index 7434664c..5760a68c 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/media.html +++ b/mediagoblin/templates/mediagoblin/user_pages/media.html @@ -22,144 +22,156 @@ {% block title %}{{ media.title }} — {{ super() }}{% endblock %} -{% block mediagoblin_content %} - {% if media %} - <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)) %} +{% 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 %} - {# if there's a medium file size, that means the medium size - # isn't the original... so link to the original! - #} - {% if media['media_files'].has_key('medium') %} - <a href="{{ request.app.public_store.file_url( - media['media_files']['original']) }}"> - <img class="media_image" - src="{{ display_media }}" - alt="Image for {{ media.title }}" /> - </a> - {% else %} +{% block mediagoblin_content %} + <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! + #} + {% if media['media_files'].has_key('medium') %} + <a href="{{ request.app.public_store.file_url( + media['media_files']['original']) }}"> <img class="media_image" src="{{ display_media }}" alt="Image for {{ media.title }}" /> + </a> + {% else %} + <img class="media_image" + src="{{ display_media }}" + alt="Image for {{ media.title }}" /> + {% endif %} + {% 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 }}. Licensed under an <a href="#">X license</a>. + {%- 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 %} - {% endblock %} + 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.get_uploader().username), - username=media.get_uploader().username -%} - By <a href="{{ user_url }}">{{ username }}</a> on {{ date }} - {%- endtrans %} - </p> - <h3></h3> - {% if request.user and comments.count() %} - <p><a href="#comment_form">{% trans %}Post a comment{% endtrans %}</a></p> + </h3> + {# 0 comments. Be the first to add one! #} + {% if request.user %} + <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 %} + {% if pagination.active_id == comment._id %} <div class="comment_wrapper comment_active" id="comment-{{ comment._id }}"> - <a name="comment" id="comment"></a> + <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.get_uploader().username, - media = media._id) }}#comment"> - {{ comment.created.strftime("%I:%M%p %Y-%m-%d") }} - </a> - </div> - </div> + {% 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.get_uploader().username, - media=media._id) }}" method="POST"> - {{ wtforms_util.render_divs(comment_form) }} - <div class="form_submit_buttons"> - <input type="submit" value="{% trans %}Post comment!{% endtrans %}" class="button_form" /> - {{ csrf_token }} - </div> - </form> - {% endif %} - - {{ render_pagination(request, pagination, - request.urlgen('mediagoblin.user_pages.media_home', - user = media.get_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'] %} - <p> - {% set edit_url = request.urlgen('mediagoblin.edit.edit_media', - user= media.get_uploader().username, - media= media._id) %} - <a href="{{ edit_url }}">{% trans %}Edit{% endtrans %}</a> - </p> - <p> - {% set delete_url = request.urlgen('mediagoblin.user_pages.media_confirm_delete', - user= media.get_uploader().username, - media= media._id) %} - <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.get_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 058351a5..7c7218ae 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html +++ b/mediagoblin/templates/mediagoblin/user_pages/media_confirm_delete.html @@ -27,7 +27,7 @@ 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> 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 5a39aaa5..b952e88c 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/user.html +++ b/mediagoblin/templates/mediagoblin/user_pages/user.html @@ -89,7 +89,7 @@ {%- trans username=user.username %}{{ username }}'s profile{% endtrans -%} </h1> - {% if not user['url'] and not user['bio'] %} + {% if not user.url and not user.bio %} {% if request.user._id == user._id %} <div class="grid_6 alpha empty_space"> <p> @@ -113,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 -%} 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 3c12f93c..caa79fcc 100644 --- a/mediagoblin/templates/mediagoblin/utils/pagination.html +++ b/mediagoblin/templates/mediagoblin/utils/pagination.html @@ -36,15 +36,13 @@ {% 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 /> {% trans %}Go to page:{% endtrans %} diff --git a/mediagoblin/templates/mediagoblin/utils/prev_next.html b/mediagoblin/templates/mediagoblin/utils/prev_next.html index 3363891b..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 }}"> - ← newer + ← {% trans %}newer{% endtrans %} </a> {% else %} {# This is the first entry. display greyed-out 'previous' image #} <p class="navigation_button navigation_left"> - ← newer + ← {% 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 }}"> - older → + {% trans %}older{% endtrans %} → </a> {% else %} {# This is the last entry. display greyed-out 'next' image #} <p class="navigation_button"> - older → + {% trans %}older{% endtrans %} → </p> {% endif %} </div> diff --git a/mediagoblin/templates/mediagoblin/utils/tags.html b/mediagoblin/templates/mediagoblin/utils/tags.html index c7dfc8eb..1f587411 100644 --- a/mediagoblin/templates/mediagoblin/utils/tags.html +++ b/mediagoblin/templates/mediagoblin/utils/tags.html @@ -17,12 +17,12 @@ #} {% block tags_content -%} - <p>{% trans %}Tagged with{% endtrans %} + <p>{% trans %}View more media tagged with{% endtrans %} {% for tag in media.tags %} {% if loop.last %} {# the 'and' should only appear if there is more than one tag #} {% if media.tags|length > 1 %} - {% trans %}and{% endtrans %} + {% trans %}or{% endtrans %} {% endif %} <a href="{{ request.urlgen( 'mediagoblin.listings.tags_listing', diff --git a/mediagoblin/tests/test_auth.py b/mediagoblin/tests/test_auth.py index 153c6e53..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,8 +162,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 ## Make sure user is logged in request = template.TEMPLATE_TEST_CONTEXT[ @@ -187,7 +187,7 @@ def test_register_views(test_app): assert parsed_get_params['userid'] == [ 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() @@ -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 # ----------------- @@ -270,27 +270,27 @@ 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['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 # --------- diff --git a/mediagoblin/tests/test_edit.py b/mediagoblin/tests/test_edit.py index 3637b046..0cf71e9b 100644 --- a/mediagoblin/tests/test_edit.py +++ b/mediagoblin/tests/test_edit.py @@ -15,23 +15,16 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. from mediagoblin import mg_globals -from mediagoblin.tests.tools import setup_fresh_app +from mediagoblin.tests.tools import setup_fresh_app, fixture_add_user from mediagoblin.tools import template -from mediagoblin.auth.lib import bcrypt_check_password, \ - bcrypt_gen_password_hash +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 = mg_globals.database.User() - test_user['username'] = u'chris' - test_user['email'] = u'chris@example.com' - test_user['email_verified'] = True - test_user['status'] = u'active' - test_user['pw_hash'] = bcrypt_gen_password_hash('toast') - test_user.save() + test_user = fixture_add_user() test_app.post( '/auth/login/', { @@ -51,7 +44,7 @@ def test_change_password(test_app): # 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']) + assert bcrypt_check_password('123456', test_user.pw_hash) # test that the password cannot be changed if the given old_password # is wrong @@ -66,20 +59,14 @@ def test_change_password(test_app): test_user = mg_globals.database.User.one({'username': 'chris'}) - assert not bcrypt_check_password('098765', test_user['pw_hash']) + assert not bcrypt_check_password('098765', test_user.pw_hash) @setup_fresh_app def change_bio_url(test_app): """Test changing bio and URL""" # set up new user - test_user = mg_globals.database.User() - test_user['username'] = u'chris' - test_user['email'] = u'chris@example.com' - test_user['email_verified'] = True - test_user['status'] = u'active' - test_user['pw_hash'] = bcrypt_gen_password_hash('toast') - test_user.save() + test_user = fixture_add_user() # test changing the bio and the URL properly test_app.post( @@ -89,8 +76,8 @@ def change_bio_url(test_app): 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/' + 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' 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/tests/test_misc.py b/mediagoblin/tests/test_misc.py new file mode 100644 index 00000000..09623355 --- /dev/null +++ b/mediagoblin/tests/test_misc.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 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_submission.py b/mediagoblin/tests/test_submission.py index eea5747f..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,7 +170,7 @@ 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'], + user=self.test_user.username, media=media._id), # no value means no confirm {}) @@ -196,7 +190,7 @@ 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'], + user=self.test_user.username, media=media._id), {'confirm': 'y'}) 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 01813e96..49a3d33e 100644 --- a/mediagoblin/tests/tools.py +++ b/mediagoblin/tests/tools.py @@ -27,6 +27,7 @@ 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__' @@ -200,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/response.py b/mediagoblin/tools/response.py index b01d31a2..c905097c 100644 --- a/mediagoblin/tools/response.py +++ b/mediagoblin/tools/response.py @@ -30,7 +30,7 @@ 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): diff --git a/mediagoblin/tools/template.py b/mediagoblin/tools/template.py index f48b7c2e..d0400347 100644 --- a/mediagoblin/tools/template.py +++ b/mediagoblin/tools/template.py @@ -79,7 +79,9 @@ 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: diff --git a/mediagoblin/tools/text.py b/mediagoblin/tools/text.py index be1adb00..d576224d 100644 --- a/mediagoblin/tools/text.py +++ b/mediagoblin/tools/text.py @@ -43,6 +43,7 @@ HTML_CLEANER = Cleaner( host_whitelist=(), whitelist_tags=set([])) +TAGS_DELIMITER=','; def clean_html(html): # clean_html barfs on an empty string @@ -67,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]: @@ -85,7 +86,7 @@ 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 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 3d9735f7..87b82c74 100644 --- a/mediagoblin/user_pages/views.py +++ b/mediagoblin/user_pages/views.py @@ -40,7 +40,7 @@ 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', @@ -59,7 +59,7 @@ def user_home(request, page): user_gallery_url = request.urlgen( 'mediagoblin.user_pages.user_gallery', - user=user['username']) + user=user.username) return render_to_response( request, @@ -122,7 +122,7 @@ def media_home(request, media, page, **kwargs): comment_form = user_forms.MediaCommentForm(request.POST) - media_template_name = get_media_manager(media['media_type'])['display_template'] + media_template_name = get_media_manager(media.media_type)['display_template'] return render_to_response( request, @@ -152,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)) @@ -173,7 +173,7 @@ def media_confirm_delete(request, media): if request.method == 'POST' and form.validate(): if form.confirm.data is True: - username = media.get_uploader()['username'] + username = media.get_uploader().username # Delete all files on the public storage delete_media_files(media) @@ -191,7 +191,7 @@ def media_confirm_delete(request, media): return exc.HTTPFound( location=media.url_for_self(request.urlgen)) - if ((request.user[u'is_admin'] and + if ((request.user.is_admin and request.user._id != media.get_uploader()._id)): messages.add_message( request, messages.WARNING, @@ -254,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', 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 @@ -61,7 +61,6 @@ setup( 'webtest', 'ConfigObj', 'Markdown', - 'python-cloudfiles', ## For now we're expecting that users will install this from ## their package managers. # 'lxml', |